Compiler as mediator in Smalltalk and Java
Overview
This is a discussion of the benefits to Java static typing and the
ability of the Java compiler to find bugs at coding time.
The following is a reference to the main thread-point that this short paper is on:
Original Posting: Compiler as mediator in Smalltalk and Java
Peter Kwangjun Suk wrote:
[SNIPPED CONTEXT]
> IMHO, no one who has looked honestly into both Java and Smalltalk
> could say that Java mediates better between people. Type safety just
> doesn't seem to buy that much in the context of Smalltalk. The fact
> that you have to go through this edit-compile-debug cycle, and that
> you don't have *everything* in your image conveniently available
> causes a shift in perspective.
To be fair to Java, you really need to compare VisualAge/Java against
the standard Smalltalk IDEs. For this comparison, the edit-compile
cycle is exactly the same granularity as Smalltalk (i.e. by method and
class declaration) and you do have *everything* in your image that you
want to have in it (as well as everything else available in the
repository). You also have a decent debugger and other similar
capabilities. Some things are missing but they are not that important
or could be added with time (e.g. the Refactory browser would be even
more useful in Java)
In this comparison context, the "mediation" capability of Java
interfaces can be witnessed to its best advantage [however good that
is]: VisualAge simply places an 'X' on any method/class that has a
static-typing problem. Is this useful in comparison to Smalltalk
behavior? I would say yes with heavy qualifications (because of all the
other implications of static-typing). The type-checking certainly makes
the client immediately aware of any "typing" problems in their code
without being too intrusive: if the method is not necessary for
execution, you can still "run" your program. Note though, that this is
behavior beyond Java-compliant capabilities [and see far below]. In the
best (rose-tinted) light, this "mediation" simply shows
DoesNotUnderstand exceptions at the earliest possible moment[1]. And
although I agree with previous threads that "typing" problems are not
the most serious/common problems in good OO software it is kind of nice
to be reminded of them as soon as possible and to have a continuous
status of how many of them are remaining[2]. I do think this helps
beginning programmers significantly and others moderately.
Qualifications
Now some of the qualifications. First note that I use a lot of
"semi-unusual" standards in Java to ameliorate the failings/pains of
static typing and Java-specific problems. These failings include:
- Typing to Classes [implementation]. This horribly impedes reuse,
limits generalization, and makes a system intollerant of growth/changes.
- Poor granularity of Types. Frequently a Type will be specified
that has too many operations (is too specific) to be useful in multiple
contexts even though subsets of those operations (a more general
concept) is widely useful. Since it costs effort to name and create
each Type, there is an impetus of reduction that again impedes reuse and
generalization. Save now, pay later.
- Loss of precise type information when objects are fed through more
generic structures.
- Using types as a "poor-man's" documentation of an operation's
responsibility 'do(Buffer,int)'
- The horrible 'static' keyword used with methods: Static methods
aren't really methods at all (there is no object for them), do not
support inheritence, are not compatible with interfaces, and are
completely bound at compile-time [OK, that is the true problem, the
others are just symptoms].
So again, I use a bunch of standards to avoid these problems in Java.
Some of these are documented in [3] and I will mention the most relevant
here:
- Interface with interfaces: Interfaces own the normal
"namespace"[4] and almost all variables should be typed to an
interface. This makes clients able to specify the capabilities they
require without coupling them to a specific implementation and the
implementer is able to choose/enhance/change the implementation as needs
dictate.
- Almost no static methods other than 'main's: Instead, conceptually
static methods are moved to singletons, factories, pack objects (see
[3]), and similar objects.
- Potentially multiple interfaces for different types of clients
(General, Extended, Factory, various Friends, etc.)
- Woven parameters: Parameters are woven into operation names with
an underscore ('_') as a placeholder (fooX:y: -> fooX_y) so the caller
has a good idea of parameter order just from reading the operation's
name.
- No overloading methods on parameter types: toString(Object) and
toString(String) are not acceptable.
- Casting/typechecking '(Foo)' is perfectly acceptable, especially
with collections and similar type-losing structures.
- It is acceptable to throw a "ShouldNotImplement" exception if a
class only mostly conforms to a 'Type'/Interface. This is the same
behavior as the JDK started with the new Collection classes and somewhat
works around the granularity problems.
- Only public and protected visibility usage in 99% of the code.
Also, a bit of a tendency to promote visibility to 'public' and control
access through the interfaces in (1) and (3).
The above and similar standards make some of the failings of
static-typing and Java go away or at least live in a much smaller island
within a better behaved world of objects.
The need to have strong standards to avoid these problems is itself a
heavy qualification. Most of the above are work arounds for static
problems: it isn't that I wouldn't like the compiler to check and
mediate between developers, third party libraries, or even myself with
myself, but the compiler is just not doing a good job. Its mediation
is even discouraging good designs that cause static-typing
difficulties[5]. So the compiler is relegated to having more
constrained responsibilities and we also need to have bad constructs
"linted" out. Also, the whole concept of Envy extensions, intelligent
proxies, true meta-classes, etc. is pretty much impossible in the
Java/static environment.
VisualAge capabilities and universal VMs
Anyway, on to a slightly different topic to counterpoint some of the
comments above. Note that VisualAge is able to execute Java in ways
that are beyond the standard Java specifications. The ability of
VisualAge to run Java classes when there are errors in it is the most
striking example of this, but there are lots of other unusual
capabilities. Well, we all know it can do this because it is actually
running Java on top of a more universal/Smalltalk-supporting VM. So in
some ways VisualAge/Java is a bad argument for Java because it is really
acting with a core of Smalltalk behavior that simply emulates some of
the restrictions and "metadata" that are available to Java. And the
point is: this augmented behavior is *extremely* useful, especially
during development.
So, maybe we should just think of Java as both a (somewhat poor) semi-OO
training language and a (reasonable) open VM for a sandboxed simplified
Smalltalk with Types. The second of these suggest Java is better
considered a *target* language and only a poor-man's development
language. Smalltalk, Dylan, Eiffel, etc. enhanced with Java
understanding are actually the real development languages. And this is
exactly the case with VisualAge except the Smalltalk portion has been
hidden away.
Yes, it would be better if the Java VM was a bit more universal. Yes,
it would be better if the Java language got rid of its messes and
supported DBC as well as Eiffel. Which takes us back to the "How to get
SUN to augment the JVM with broader language/OO-concept support"
thread...
--Mark
mark.fussell@chimu.com
|