Thursday, September 24, 2009

Design patterns, or why Java needs external crutches

In my last blog about architecture and design I promised to come back on the topic of design patterns. This term was coined in a famous book that proposed a catalogue of "Elements of Reusable Object-Oriented Software", and became a best-seller in the Java world (usually referred to as the "GoF" book, for "Gang of Four" authors). Feeling the golden ore, all editors quickly produced a whole line of similar books, where patterns were adapted to various domains and languages : for C##, for Ruby, ..., etc. I almost expected to see patterns books for assembly code and for Befunge, but these never came out !

So what about patterns for Perl ? To my knowledge, no major editor published any book on that topic, which is kind of surprising because one would think that there is some money to make. However, Phil Crow privately published Perlish patterns (cheeply available as e-book), which is really worth reading; Phil proposes the following explanation in his introduction :

Eventually, I came to understand that there were several reasons why patterns were never as enthusiastically embraced in our community as they were in others. Some of the patterns just apply new names to common techniques. Some are represented in Perl's core, so we don't think much about using them, at least in their normal forms. Some apply better to languages which focus on object orientation.

I very much agree with this analysis. The original GoF book was refreshing to read, but when programming in Perl I never think in terms of those patterns, because the standard language features plus some common CPAN modules answer most of my needs for structuring my programs, even when assembling large bodies of functionality.

The fact that Java is so verbose, and that everything has to be an object, results in code that is often spread among lots and lots of classes. So to condense that information, it is no surprise that Java programmers need other abstractions like "patterns", so that they can think in terms of larger units. For the same reason, they also need sophisticated tools like Eclipse for navigating through the class hierarchy, and they need costly tools like Rational Rose to see and design the big picture, and generate code skeletons. I'm always surprised to hear such tools presented as strenghts of the Java world, while to me they are just necessary consequences of the way Java code is layed out.

In standard Perl, we have hashrefs and arrayrefs, we have closures, multiple inheritance, namespace manipulation primitives, dynamic classes and dynamic methods, functional grep, map and other List::MoreUtils goodness; we can assemble those into dispatch tables, delegation structures, function and method templates and factories ... enough patterns to fill a whole life !

Monday, September 21, 2009

hit by operator precedence and right associativity

While studying a bug, I wrote the following test program :

use strict;
use warnings;
use Data::Dumper;
my $bool = 1;
my %h;
$bool ? $h{true} = 't' : $h{false} = 'f';
print Dumper(\%h);

The ternary expression starting with $bool was supposed to be a concise way to write a conditional, but the result was a disaster. Can you guess the output ?

Here it is : $VAR1 = { 'true' => 'f' };

This really seems totally insane : something is assigned to the 'true' slot of the hash, but the value comes from what was supposed to be in the 'false' slot !

OK, the ternary expression above is wrong, because the '?:' operator has higher precedence than '=', so one should really write

$bool ? ($h{true} = 't') : ($h{false} = 'f');

But how comes that perl issues no error, no warning, and happily produces a very strange result ? It seems that both sides of the conditional are executed simultaneously, and collapse in a mysterious way.

I tried running the script through B::Deparse to understand how it was parsed, but the output was exactly like the original source, so it really seems to be legal Perl !

It really took me a while until the 'aha' moment that made me realize that because of right-associativity, and because conditional expressions can be lvalues, and because "Unlike in C, the scalar assignment operator produces a valid lvalue" (perlop dixit), this was parsed as

($bool ? ($h{true} = 't') : $h{false}) = 'f';

So the $bool test chooses an lvalue between $h{true} and $h{false}, and it doesn't matter that this lvalue is first assigned a 't', because later the main assignment puts a 'f' into it.

Obvious, isn't it ?

Saturday, September 19, 2009

Learning architecture and design

Matt Trout asks about how people learned what they know about architecture and design.

As far as I am concerned, I've always been more or less interested in that subject, but only started to study it more seriously about ten years ago, when I left the academic research world and started writing real software instead of writing papers about software.

So where to go when one is interested in design ? One source of information is books. My sources are quite similar to the ones cited in Matt's article. Currently I'm reading Beautiful Architecture (actually I bought it at YAPC::EU::09), which I enjoy very much because the articles are of high quality and cover a vast territory. The previous book in that series Beautiful Code is also worth reading, although a bit less interesting in my taste. Of course I also read a couple of books about design patterns ... but I'll blog another time about those.

Despite the fact that they seem to sell well, books on design are are not numerous ... probably because they are so hard to write ! I mean, writing a regular technical book is hard; producing good designs is hard; so writing a good book that highlights the design process is necessarily even harder. Actually, books mentioned above are never an organized discourse starting at A and ending at Z; what they do is supply a catalog in which the reader can grab interesting ideas, and that's probably the best any book on design can do.

Which brings us to the point : books on design are nice, they open your mind, but that's seldom the place where you really learn. Design is acquired by practice, using or reading other people's designs, and then doing your own through trial and error. It reminds me of my counterpoint courses : although there are a few recipes, it's only after having studied a dozen Bach fugues and having painfully written two or three in the same style that one really understands what it means to design a fugue.

So I enjoy browsing through technical manuals and APIs of many components, even if I'll never use them. For example, it's quite instructive to study the difference between the object models of Microsoft Word and Microsoft Excel, two products in the same family, but with huge differences in design. Word is an infamous amalgamation of fuzzy concepts (anybody ever understood how automatic numbering works ?), while Excel is a beautiful join of many powerful features into a single orderly framework.

Here is a list of some designs that I considered particularly inspiring:

  • the NeXT operating system and programming environment had a nice language (Objective-C) and a beautiful OO architecture, with a generic notion of object inspector for editing object properties ... really a joy to use and program. Too bad all of this disappeared for lack of market penetration.
  • when Netscape first proposed to integrate Javascript into Web pages so that they could become dynamic, I had a "wow" moment : this opened so many possibilities ! Besides, the documentation was extremely well-written (many years after, it's still a useful reference, especially the chapters on how to exploit prototype-based inheritance).
  • in the same vein, I had another "wow" moment one or two years later when Internet Explorer first came with the notion of manipulating the DOM through scripting (initial versions of Javascript in Netscape could not do that). Again, this opened a whole new world, and the API was quite clean and very well documented (not respecting standards is another story). By the way, at that time the MSDN library site was really cool, with support for keyboard arrow command while navigating through the documentation tree --- later on they moved to .NET technology, and were no longer able to support keyboard navigation !
  • the Apache architecture is amazingly well-thought for extensibility, with its clean separation of each phase in the request lifecycle, and the possibility to to insert hooks in each of those phases. Actually I didn't study Apache directly, but only through mod_perl, which exposes almost everything of the Apache API to Perl programming, and is another piece of amazing design. I must say, however, that mod_perl has a peculiar way of doing OO, through a kind of home-made mixing of packages into common namespaces, which for the time was quite clever but took me some time to understand. I guess this would all be written with "roles" if redesigned in modern Perl.
  • several important CPAN modules would be worth discussing here, but that would bring us too far ... maybe later in another blog entry. Let me just state that every time I came to discover another module of Andy Wardley, I felt a sense of beauty : to me, Template Toolkit, AppConfig, Pod::POM