Microsoft shopping for Java alternative
alan at objectpeople.com
Sun Feb 14 05:27:56 UTC 1999
At 10:07 PM 2/13/99 -0500, David Chase wrote:
.... much omitted...
>I wonder rather much how testing and verification
>works in Smalltalk land; just the exception-signature checking
>in Modula-3 and Java has saved my butt quite a few times (and
>checking for proper disposition of errors is a major pain,
>because you can't always get an error when you want it). It's
>clear, having worked in Scheme and FP84 and BCPL, that non-static
>typing allows you to get tremendous leverage from code reuse, and
>that means that you've got less code to write in the first place,
>and much more tested code to work with, but static typing also
>is a big leg up when you are flinging together components
>written by Other People, where it is not clear that reuse
>would have bought you that much in the first place, and you
>do need to be sure that you get the interfaces right and
>handle all the errors.
>I don't want to start another one of those static vs. dynamic
>flame wars, I just want Smalltalk fans to consider that those
>people who prefer static typing just might not be freshly
>fallen from the turnip truck. Either we've got some sort of
>a very different mindset, or we're working on very different
>applications, or we've got different tolerance for errors,
>or we've got a very very different testing methodology.
>Something's clearly different, and I don't think it's just
>as matter of stupid versus smart.
.... definitely not wanting to start one of the interminable discussions,
but here's my two cents
Either side in these would clearly be foolish to think the other are
stupid. They're just coming at things from very different perspectives and
cultures. The typical non-productive discussion starts with "My way of
developing software addresses problem X using this technique Y. Your way
can't use technique Y, so it's obviously subject to problem X", not
understanding that the problems are probably addressed in different ways
(and that different communities do place priorities differently). Dynamic
programmers don't always appreciate the extent of errors that a good system
might catch. Static programmers don't always understand the degree of
implicit testing from an environment where you rarely write 10 lines of
code without running them.
It's also very unlikely that a developer really understands all the
available points of view. There are a lot of different varieties of static
typing, and a lot of varieties of non-static. A Smalltalk programmer who
thinks of static typing as standard Pascal or even Java will not have a lot
of success communicating with an ML programmer who thinks of dynamic typing
as pre-ANSI C or FORTH.
Now, for most purposes I come down fairly firmly on the side of dynamic
typing, and since I've started, let me explain some of my reasons.
First, IMHO, the benefits of dynamic typing are not nearly so much in
re-use as in malleability. I don't care nearly as much if someone can
re-use my code as that I can make it adapt to my changing requirements.
Fundamentally, static typing inserts redundant information into the code
(let's ignore type-inferencing systems, since the issues are different and
I've never used one in anger) in order to catch errors. It can certainly
catch more errors, but it does so at the cost of building additional
structures which can be very brittle when the underlying program changes.
This is often described as "the structure of your types is an important
part of your design", which, like any statement of that form, is normally
read "You had better get the structure of your types right up front because
it's going to be very difficult to change later on".
You gave a specific example of exception signatures in methods in Modula-3
and Java. This is actually a pet peeve of mine, since in my opinion it
leads to extreme brittleness. One of the worst examples is in Java RMI,
where a remote class is never polymorphic with a local class, since remote
methods all throw RemoteException. Ugh.
In general, the problem I see with putting exceptions into the signature is
that you typically don't want to catch exceptions precisely at the point
they are raised (if we did, we'd use a simpler mechanism). This means the
exception will have to be propogated up through multiple levels, each of
which gets to include it in the signature. Throwing one new exception deep
down in the code requires changes to lots and lots of layers above it. This
is a bad thing. Objects help give us, ideally, the property that if the
internals of an object change we don't have to change any of the callers at
all, as long as the interface remains stable. This is a good thing, but
perhaps even more important is "negative feedback" in the changes. Even if
the interface changes a lot, I want the changes to damp out as quickly as
possible, so that an interface change doesn't percolate throughout the
system. Things like exceptions and const in method signatures inhibit this.
This is also a good example of handling things differently, and of having
different values. You're talking about catching errors, I'm talking about
keeping the software flexible. Those values are also appropriate in
different places. I can entirely believe that there are places that it's
important to have information about what exceptions might be thrown,
particulary at the boundaries of those "Other People's Components". I agree
that testing exceptional cases is tricky. I'm equally certain that I don't
want that information to be part of every method signature and have to
specify and deal with it on every method.
This gets into a broader issue, that of the granularity where things apply.
There are "important ideas" that apply at various levels of software (and
more general) engineering, like encapsulation, like declarative forms, like
formal verification. With some of these things it works even better if you
push these down to the lowest-level. For example, pushing the ideas of
encapsulation and message-sending down to the lowest-level essentially
gives us objects, and I think everyone here would agree that's worked out
well. Other ideas, while important at the higher levels don't push down
nearly so well, and in my opinion many of the formalisms fall in this
category (proving program correctness, design by contract, etc.). Contracts
are an important idea in the real world as in software, but in both of
those there's a reason we don't have fully-specified contracts for every
little thing we do. I just don't want the proof that my program is working
to take more time and get in the way of the program actually doing its job,
especially when that job changes constantly. It smacks too much of
-- Alan "trying not to rant too hard" Knight
P.S. A couple of technicality rants.
- I don't see why I should have to specify the exceptions. Given a
static type system, the environment should be able to figure out which
exceptions were raised dynamically, but that would require it to do global
searching, which doesn't fit in well with the mindset of files, separate
compilation, and lack of tools.
- More powerful exception handling also makes this kind of thing less
necessary. e.g. In Java an exception unwinds the stack before it hits the
handler, a "feature I could go on about at length". In Smalltalk it doesn't
(and I assume in Squeak, though I've never checked), so you can do much
more complex things at a higher-level handler, like reconnect to the
database and resume from where it was thrown (or anywhere else in between).
You can also specify a default handler, so you can say what happens when an
exception hits the top level without being caught, regardless of the thread
it happens in.
Alan Knight knight at acm.org
The Object People http://www.objectpeople.com
613.225.8812(v) 613.225.5943(f) Skinheads for Smalltalk!
GO SMALLTALK! - http://www.stic.org
More information about the Squeak-dev