Tuesday, 5/15/01
Java, and Java 2.0 (aka .NET), have brought with them the end of
object-orientation. Of course, by that I mean that object-orientation is no
longer a question — it’s just how we program. Even our scripting languages
have classes and objects now. That fight is over, as are the advances in that
area. Object-oriented programming, with inheritance, polymorphism and
encapsulation, is just the way we do things now and Java and .NET represent the
end of that line and the beginning of several others:
Generic Programming
Generic programming (aka “generics”) provides the ability to write a partial
type or function and let the compiler or runtime environment fill in the
details based on client usage. Of course, C++ templates have provided generics
via templates for a long time. Unfortunately, no modern object-oriented
languages, i.e. Java and C#, have generics as yet, but they’re coming.
My favorite research paper in this area describes how generics can be added to
.NET languages, using C# as an example, written by Microsoft’s own
researchers, Andrew Kennedy and Don Syme.
Generics have been around for a long, long time, so if you aren’t already
familiar with them, you’re behind. Only C++ programmers do this now, but very
soon, everyone will be.
Component-based Programming
Components differ from objects in that they are binary objects, often callable
from languages other than that in which they were written. COM, Java and .NET
are popular modern component development environments, but even DLLs have
provided component-like features since Windows. Components provide a degree of
encapsulation that often exceeds that of source-based OO environments, often at
the expense of ease of use (although both Java and .NET work real hard to make
components look and feel like objects).
Aspect-Oriented Programming
Aspect-oriented programming (AOP) provides the ability to define a set of
characteristics of an object or a component that are actually implemented by
the hosting runtime. The benefit, of course, is that it’s much easier to
declare the need for some feature, e.g. method tracing or the need for a
component to be part of a transaction, than it is to write the code. To date,
we’ve had pretty primitive support of AOP in the popular programming
environments, but it’s been there, e.g.
-
COM+ catalog attributes that describe services provided by the COM+ runtime to
components or groups of components (called “applications”), e.g. transactions,
object pooling or role-based security.
-
Keywords in Java, e.g. the transient keyword that signals to the serialization
engine whether to serialize an object’s member variable or not.
-
.NET attributes that extend a component’s metadata, which is available via .NET
reflection to clients, some of which are built into the .NET runtime and some
of which that are custom to your particular application.
-
And my personal favorite, as pointed out to me by Don Box, is the PE attribute
that marks an EXE as a Win32 Console application. This is primitive, but this
attribute tells the OS to set up a console window for routing of stdio.
The .NET attribute mechanism represents a giant step forward in AOP. It’s the
first popular environment that provides a convenient, extensible mechanism for
not only declaring attributes, but also implementing custom attribute provides,
i.e. those bits of code that are activated when an attribute is encountered.
Extensible .NET metadata is replacing the COM+ catalog and providing exactly
what the Java serialization keywords provide and I expect most language to
converge on the AOP style that .NET provides.
Generative Programming
Generative programming is the newest of these new programming styles. The term
itself was boasted into popular usage by the
book of the same name by Krzysztof Czarnecki and Ulrich Eisenecker.
Generative programming is about representing your system’s design requirements
in some computer-readable form, e.g. SQL schemas, XML, UML, etc, and feeding it
to some kind of metaprogram that will generate your program. The main benefit
of generative programming is that as the design requirements change, your
programs can be regenerated, saving you from manually replicating design
changes into the code. Likewise, as the implementation choices need to change,
e.g. from Java to C# or from Linux to Windows, the metaprograms can change and
your programs can be regenerated, saving you from doing the porting work.
Macro languages, e.g. the C preprocessor, are generative languages for
generating code within files. ASP and PHP are both generative languages for
building web pages. Of course,
DevelopMentor’s own Gen<X>, was built from the ground up to be a
generative programming tool (although we designed and built it long before we’d
heard the term). Generative programming has a vast potential, I think (although
I’m biased), because it encourages you to specify your design requirements and
keep them up to date with the code, but also because of the potential for
generating large parts of a system’s code, testing data and even documentation.
In fact, in building Gen<X> itself, we find ourselves generating more and
more of the next version using the previous version. We don’t use it for unique
code, but we use it for the repetitive horizontal or hierarchical code as well
as reference docs and test data. Highly recommended.
[new] Comment from Mickey Williams
[mickey.williams@codevtech.com], Mon 7/2/2001 10:54 AM:
“I’d like to remind you that Eiffel has had generics longer than C++, and
Eiffel’s generics work on .NET. So there.
“Best regards from the Eiffel bigot,
“Mickey”
That’s true, Mickey. I knew that Eiffel
supported templates, but I didn’t know that
Eiffel# (the .NET version of Eiffel) did, so that’s really cool.