|Syntactic Confectionery Delight|
The only point I want to nitpick here is complexity. A large program becomes complex for one reason. Fredrick Brooks (of the infamous Mythical Man Month) termed Natural Complexity and Accidental Complexity. A friend of mine worked for a month at a place that needed some new features added to their program. The program is 10,000 lines, all in one file, and completely incomprehensable. This is one kind of complexity that doesn't need to exist. Further, the code had no apparent structure. It was peicemeal. No relationships between parts could be discerned, and in fact, it was hard to identify anything as being a part, seperate from the rest. And fittingly, this is the reputation Perl has.
I don't advocate making programs more complex than they need to be, which is to say, they shouldn't be more complex than the problem they are meant to solve warrents. Patterns are meant to structure large programs - not small ones. Out of context, they look, well, dumb. This makes it hard to write examples and even harder to imagine what the example would look like in its native habitat. I have a copy of "Lions' Commentary on UNIX 6th Edition", ISBN 1-57398-013-7. This book rocks. It is half explanation, half source code listing (mostly C, very little assembly through in). The commentary on the code was done by a college professor for a class, and it points out idea behind the code, structure, how things were built, how the parts fit together - picking on things that students are likely to someday have benefited from learning. Patterns. Having structure to the code doesn't make it complex - quite the opposite. It makes it interesting and valuable and long lasting. Look - we're still using Unix, even though it had to fit into 128k on a PDP-11!
My advice to people writing small one-off scripts and quick hacks is to ignore the whole patterns thing just like you ignore objects. The tool doesn't fit the job. And trying to make it will just warp the job - as you say, adding complexity. However, at the first hint that the code is starting to outgrow what little structure it has, future programmers doomed to work on the project will thank you if you start early trying to fit the code to some higher level idioms. You use low level idioms, why not higher level ones?
Oh yeah. I forgot. Perl does that for you. Look. There are two kinds of programming tools in the world. 4GLs and things designed to make you not have to think about design or logic, and refactoring browsers and other things designed to augment the abilities of a human as they design. ASP fits the first category, along with dozens of failed graphical-builder tools. lint, yacc, c-tags, that postscript hack that makes a poster of the Linux kernel sources, Purify, Rational Rose and other UML or Use-Case modeling tools fit the second category. Things in the first category tend not to be any help at all to an expert - in fact, they are associated with amatures. Things in the latter category are associated with skilled professionals, who are highly effective at their job. These tools have stood the test of time and repeatedly proven themselves. Rather than trying to do a job for the programmer or make a job vanish, they augment what human can do. Think of humans augmented with computers rather than humans replaced with computers, if you want a mnenomic.
To say that Perl has high level design built in so you don't have to think about it is to cast Perl as a member of the former group. I don't like that very much. To say that Perl is a language more than capable of accomodating the technical needs of design in a large project when skilled professionals employ the right tools - that I like. Does Perl do the job of thinking for you, or does it expand what you're capable of? Do design issues not exist in Perl like they do in Java, or do they exist more readily as Perl increases programmer productivity, allowing them to build more quickly? When you go to the book store, do you read just the Perl books, or do you wander over and actually peek into these computer sciency rags?
Remember, at one time, no one would touch objects, and they were the fetish of a few colleges, never seen outside. It wasn't until the 1980's - 20 years after their invention - did they get foothold in global conciousness. Before that, no serious language would ever consider a lambda closure feature - people don't need that to do business reports in RPG or COBOL! Both of these things slowly seeped out. Lack of closure bit Java on the butt - inner classes are a horrible kludge, but absolutely needed the way Java makes you define objects of a certain class to be used as callbacks. Closures make code shorter, and to someone wise in their ways, more readable - they do great things to reduce the scope of variables, breaking the code down into obviously seperate, cleanly divided parts. Stupid CS stuff, trying to make our lives more complex! Tell yourself that patterns really aren't anything new, just a better way to learn objects - and I mean really learn objects - C++ shops have struggled something awful the last 15 years - objects didn't click into place for their programmers except for a very special few. None of the prophacies of objects making code reusable, modular, resistant to change came true for the ordinary man because they didn't grasp the single driving concept. They didn't have that "ahh" moment. Scheme and Lisp programmers never had any problem - they had "Structure and Interpretation of Computer Programs" to learn from. After an entire generation of doing it wrong, we have a generation of object programmers doing it right. So, to put it another way, the Perl global mindset is still stuck in last generations misused, misunderstood, ineffective object usage. If you need me, I'll be in the Java section.
Whoops, I got pretty far afield here. I always do that. I meant to offer perspective on your comment on complexity - the rest has little or nothing to do with your note. Otherwise, I agree. I've focued on patterns that apply to Perl and Perl programmers, not direct Perl translations of C++ patterns - on perldesignpatterns.com. Patterns shouldn't be mindless sprinkled about - normal code should stay normal code, to paraphrase Larry Wall's "perl should stay perl". In a large system, you need glue between the normal code or you have an endless procession of code. Like a patent, a pattern should be interesting and non-obvious - otherwise, people won't want to read them. Most people don't like to be told the obvious. It is insulting. And so on. There are very good reasons why an iterator needs to be something more than a foreach statement - you're exposing the internals of one object to another object through a predefined interface. Returning an array is okey sometimes, but the internal datastructure may not jive with that. perldesignpatterns.com's example of an iterator - or one of the examples - exposes the contents of a network of objects. Rather than building a massive array, the natural recurssion is exposed through the interface. Tieing and overloading are also very powerful - Perl shouldn't lose its expressiveness because of other idioms - but sometimes the idiom of using an interface and objects packs more of a punch than that of an array. Sometimes. In large programs.