Well, I'm back from Smalltalk Solutions, and now that I've caught up on my sleep, reflecting a bit on what I saw and heard. Rather than reporting blow by blow from the conference, I like to record what I learned while I was there.
For me, the highlight of the official program was Eric Evans' keynote. He took us through a fairly simple refactoring of a hypothetical shipping application, showing some of the techniques he uses to distill a domain expert's knowledge into a model that can drive the design of the application. His thesis was that a good model provides the language that the team uses to communicate about the domain, and should be directly reflected in the code.
One of the points Eric made in his talk was that he preferred language rather than pictures for modelling, and as such, he preferred modelling in Smalltalk or Java rather than UML. Later in the day, I joined a conversation he was having with Blaine Buxton, and the three of us spent quite some time arguing about language design. If Smalltalk is the best modelling language we've yet encountered, and we were to design something better, what would it be like?
One of the key things we settled on was that it would be object-oriented, but not message-oriented. Eric insisted that sending messages is a much lower-level operation than what we do when we talk about models with experts in the business domain, and that a good modelling language should operate at that level. What's missing from OOP, we decided, is explicit capture of the relationships between objects.
Thinking about it over the last few days, it occurred to me that relationships are also at the heart of many of the Design Patterns that have become popular in the OO world over the last several years. Indeed Ubiquitous Language and Pattern Languages serve much the same purpose in a software development context. Of course, the term "language" is overloaded here - human languages, such as English, computer languages such as Smalltalk and pattern languages such as those created by Christopher Alexander or the Gang of Four.
One of the primary criticisms of design patterns is that they're really just techniques for working around language deficiencies. Dynamic typing, block closures and metaclasses make many of the patterns used in the C++ and Java unnecessary in Smalltalk.
Iterator is a classic example. An iterator object encapsulates the state required to loop over the contents of
a collection. In Smalltalk, one might use an iterator to send
#doSomething to all the objects in a
iterator := aCollection iterator. [iterator hasNext] whileTrue: [iterator next doSomething]
The beauty of iterators is that by encapsulating the loop state, they make all collections polymorphic. One
can use the same looping code to iterate over any collection, be it an Array, a Set or a LinkedList. The problem
with iterators is that they are an incomplete abstraction. They capture the state of the loop, but leave the
looping behavior its self implicit, and require the loop to be duplicated wherever the iterator is used. In
#do: method provides the complete abstraction: by making the implicit loop
explicit, it provides resusable polymorphism.
I think that step of making the implicit explicit is important. How might we make explicit, for example, the relationship between an AST and a Visitor? I don't know, but I think such a language would be good for domain driven development.
Posted in design