I last came across Mead at the very first International Conference on Neural Networks in San Diego in 1988. His iconoclastic embrace of neural networks, which were then themselves just emerging from a twenty-year "dark age" brought on by their having been declared heresy at the hands of orthodox AI Perceptron critics like Minsky and his ilk, had impressed me at the time...
December 2005 Archives
In ancient Rome
There was a Poem
About a Dog
Who found two Bones
He picked at One
He licked the Other
He went in Circles
He dropped Dead
--Devo, Freedom of Choice
I stumbled across an interesting discussion in from Ruby-land through a link on Martin Fowler's website. At least I thought I did, I can't find the reference now. No matter I suppose.
It’s an intriguing, but somewhat iconoclastic idea from David Heinemeier Hansson, by way of meme consolidator Tim Case, to the effect that the notion that a framework be an ultra-flexible jack-of-all-trades has run its course. The claim is that frameworks that employ fixed conventions in lieu of elaborate configuration mechanisms are easier to learn and use, at least in the most typical and common cases. A framework should be really really good at one thing. It should do one thing, and do it well.
At first blush, this would seem at odds with conventional / customary / traditional framework development lore. Nonetheless, I find the idea quite compelling, given the right circumstances…
My first thought is that it is a sign of a healthy, mature ecosystem that the carrying capacity for frameworks that do a single thing well exists. Code that does one thing right can be easier to read, and easier to extend (using code), that code that straddles a range of requirements. There is an element of neoteny, of reverting to a less mature form in this. This is what a green fields framework often looks like too, at first.
Normally, over time, as new requirements emerge, the framework grows, to accommodate a range of requirements. The code to accommodate this variety, this diversity, is refactored as the framework grows, the commonalities rise, as if in some code chromatographic centrifuge, to the upper levels of the class hierarchy, and out into distinct components, and yes, out into the data, and into databases and configuration files.The prize: flexibility, market share, and libraries of redeployable abstractions. The price: inevitable complexity, and a steeper learning curve.
Reversion to convention marks a break with such evolutionary trends, with midlife growth. It is tempting to speculate that such breaks are inevitability generational. That drawing-back-to-leap entails a fresh draft, a new generation, a new codebase. Hence, I suspect, the phenomenon discussed here is not warmed over YAGNI (You are not going to need it); not a response to premature generalization, but a late, mature reaction to a rising tide, and a mature understanding of where flexibility is needed in a given domain, and where it is superfluous.
Neoteny is a "back to the future" reaction, in some ways, but not a "worse is better" reflex.
An analogy drawn from the realm of stadia in the United States came (once again) to mind. During the sixties, multipurpose facilities that could accommodate the needs of several sports were constructed. They met those of all of them adequately, but met none of them well. Is a Swiss Army Knife ever really better that the right tool for the right job? Or is it just easier to afford and to carry?
During the nineties (and beyond) these cookie-cutter concrete white elephants were razed, and replaced with single-purpose facilities better suited to just baseball, or just football. Even adjusted for inflation, these replacements were considerably more expensive than the stadia they replaced. But a bigger, more affluent population, craving the thrill of vicarious victory enough to support skyboxes and three-figure seat prices, was able to support this extravagance.
Could it be, that in a red-shift, expanding universe, the growth of the internet itself, and of web application demand, is such that we now have niches for single-purpose frameworks that might only have been filled by less satisfactory general purpose code even five years ago? There is a slightly decadent, postmodern redolence about all this.
Is there any way that conventional frameworks might exhibit this same level of convenience? Perhaps, if their elements are engineered to WORK OUT OF THE BOX. By exhibiting, generating, and maintaining reasonable defaults, programmers might provide the same kind of 80% / 20% Pareto's Law hands-free convenience to the bulk of their clients, while still being able to cater to more exotic tastes as well.
Now, to be fair, one of the factors at play here is that (post-)modern scripting languages like Ruby are easier to change than relatively hidebound type-pecked tongues such as C++ and (alas, now) Java. I'm recalling Kent Beck's observation that were coding to become infinitely fast, we wouldn't need to worry very much about reuse. The fast-on-their-feet scripting cultures of Amazon and Google lend some credence to this world view, it would seem…
Freedom of Choice
is What you Got
Freedom from Choice
is What you Want
--Devo, Freedom of Choice
Indeed, Swaine’s post triggered a number of memories. One was a tale I related during our OOPSLA XX retrospective, but forgot to post here of an epic OOPSLA IV paper airplane contest at the New Orleans Hyatt. The Hyatt chain used to like to distinguish its hotels with daring feats of architectural legerdemain in their central atria, and the building in New Orleans provided the ideal setting for this contest. This contest was ultimately won with a breathtaking twenty-nine story corkscrew spiral into a ground-floor fountain by a entry crafted by Bjorn Freeman-Benson. An audacious display of atrial flutter. Memories of this site came back to me during the Katrina coverage.
In the spirit of free association, that Freeman-Benson recollection also triggered another Proustian recollection of good food, Bjorn's Bacchanalian gout-fest at OOPSLA '98.
Ironically, I became aware of Swaine's piece through an utterly unwarranted pot shot taken by some unctuous coprophagic who evidently treats the internet as his personal scratching post. This sort of puerile ad hominem invective is the kind of thing that give 'blogging, and yes, even sarcasm itself, a bad name. A side effect of totally disposable email addresses and weblog accounts is that they offer malcontents like this one anonymous access to single-use sniper’s nests…
Count on Martin Fowler, that technosexual trendsetter at the tony House of Thoughtworks to stir up the season’s most colorful and provocative design dustups… …Okay, I’ll stop… …but here’ s the controversy…
Martin has of late fallen under the spell of Ruby, a dynamic postmodern scripting language billed as a pragmatic amalgam of Smalltalk and Java and what-have-you. Smalltalk’s soul in Java’s clothing, with a dash of Python. I have been hearing a lot of good things about Ruby.
Anyway, many proponents of Ruby, it would seem, espouse what they call Humane Interface design. A humane interface places a premium on programmer convenience, and may be quite a bit larger than the Minimal Interface necessary to expose an abstraction’s basic functionality. The humane approach provides a more ornate, more verbose vocabulary to the programmer, as opposed the smaller, more austere, more Spartan, ostensibly more simple minimalist interface. Joey deVilla offers a gonzo follow-up take on this controversy here.
Their poster child example is a method, "last" that returns the final element of a collection. In Ruby, (and Smalltalk, and …) a method to do just this is provided. Java interface designers are cast as the Spartans in this tale, providing only a basic getter. To retrieve the last element of a collection, something akin to a.get(a.size()-1) must be executed.
Is the Marie Antoinette vs. Wal-Mart? Loincloths? Baroque and rococo vs. Frank Lloyd Wright and the modernists?
At first blush, this would seem any easy call. My Smalltalk roots (among other things) are likely showing when I say I see no harm in a larger, more expressive vocabulary.
And there I might leave it, if this did not raise an even more interesting issue, which is: What if they are both right? How is that for equivocation?
Now the reader need not fear, for I still intend to cast my lot on the side of the humane, and not the stingy, though when the argument is cast in such terms, it is hard not to feel a tad manipulated, and after all, smaller can be simpler, I suppose... To be anti-humane is to be in favor of what? Euthanizing kittens?
Why can't we provide capable expressive, human-friendly abstraction that are themselves built around minimal cores?
The motivation for this is the need for what I call a Core or, better yet, a Nexus, that is a single, central, and yes, minimal subset of the public repertoire of an object through which all definitive, authoritative message traffic, both external and internal must pass.
In Smalltalk, programmers were traditionally rather casual about which methods were private, or fundamental, and which were written to ride atop this rock-bottom level vocabulary. Protocol organization helped to convey this to some degree, but such conventions as there were were frequently honored primarily in the breach.
Don’t get me wrong. I’m not arguing that these conventions be formalized and enforced (at least not yet; not here), rather, I’m arguing that this kind of "once and only once" is a guarantee that programmers want to ensure.
Why? So we can wrap the one place that gets and sets things, for instance. I want to know, for example, that any getter on a collection bottoms out at a single, definitive call to something like get().
So, indulge me for a minute. One way to do this might be…
Problem: you want to ensure that all references to an objects internal resources are made through a fixed, restricted set of methods.
Solution: refactor all the methods in this core, this nexus, into a separate component. Construct an entourage of wrappers (of various sorts) that employ the broader, more extensive vocabulary, and forward those in the minimal subset to this core; this nexus.
The use of a separate component guarantees that all the humane embellishments provided to the outside world must go through the minimal argot supplied by the core. This design also permits pluggable alternative implementations, such as, for instance, a sparse array implementation, to be plugged in in place of the standard cores.
Such as design is layered in the strict, traditional sense that many so-called layered designs are not. Like an onion.
Alternative designs involving inheritance using a private core with protected accessors are possible where efficiency concerns are at a premium, and runtime plug-in substitution seems unnecessary. Schemes employing interface inheritance are possible to envision too.
This was the defacto solution to this problem seen in a number of vintage Smalltalk classes. Indeed, such internal layering has been suggested as a “smell” that indicates that a new component need be culled from a class via refactoring.
So you can have a simple guts, and flashy, interchangeable skins. You can almost have your cake and eat it too. Marie Antoinette would be pleased. The filigree, the utility methods, are in the Decorators, while the core, the essence, is in the decorated cores.
That there be a nexus can be thought of as a design principle, its embodiment in recurring designs makes it a candidate for patternhood. Let’s see, we need two miracles for beatification, and two more for canonization…
There is more that a hint of Handle / Body here, among other things. A scoop of Class Adapter? A full dress treatment of this seat-of-the-pants, inchoate proto-pattern notion might address these issues.
The piper is paid, as with so many patterns, at Creation Time, Provisioning Time, when the structural edifice that drives the computation is constructed, when the web of objects is woven. But that is a tale for another post...
Here’s why I’m partial to the somewhat obscure word “nexus”, over “core”, for this intent. While the more familiar “core” conveys the centrality, the primacy in this intent, it doesn’t capture the dynamic, causal interconnectedness of this intent as precisely as does “nexus”. I’ve been looking and listening for a long time for a term that better gets across the idea that a method or object be at a definitive, authoritative chokepoint or bottleneck, at a pass at which functionality could be “headed-off”, and this might be it. And no, I haven’t read very much by Henry Miller. From M-W:
Etymology: Latin, from nectere to bind
- CONNECTION, LINK; also, a causal link
- a connected group or series
- CENTER, FOCUS