Design patterns: signs of languages’ weaknesses?

Progress in programming languages

Had the “Design Patterns” movement been popular in 1960, its goal would have been to train programmers to recognize situations in which the “subroutine” pattern was applicable, and to implement it habitually when necessary. While this would have been a great improvement over not using subroutines at all, it would have been vastly inferior to what really happened, which was that the “subroutine” pattern was codified and embedded into subsequent languages.

Identification of patterns is an important driver of progress in programming languages. As in all programming, the idea is to notice when the same solution is appearing repeatedly in different contexts and to understand the commonalities. This is admirable and valuable. The problem with the “Design Patterns” movement is the use to which the patterns are put afterward: programmers are trained to identify and apply the patterns when possible. Instead, the patterns should be used as signposts to the failures of the programming language. As in all programming, the identification of commonalities should be followed by an abstraction step in which the common parts are merged into a single solution.

Multiple implementations of the same idea are almost always a mistake in programming. The correct place to implement a common solution to a recurring design problem is in the programming language, if that is possible.

The stance of the “Design Patterns” movement seems to be that it is somehow inevitable that programmers will need to implement Visitors, Abstract Factories, Decorators, and Façades. But these are no more inevitable than the need to implement Subroutine Calls or Object-Oriented Classes in the source language. These patterns should be seen as defects or missing features in Java and C++. The best response to identification of these patterns is to ask what defects in those languages cause the patterns to be necessary, and how the languages might provide better support for solving these kinds of problems.

With Design Patterns as usually understood, you never stop thinking about the patterns after you find them. Every time you write a Subroutine Call, you must think about the way the registers are saved and the return value is communicated. Every time you build an Object-Oriented Class, you must think about the implementation of inheritance.

People say that it’s all right that Design Patterns teaches people to do this, because the world is full of programmers who are forced to use C++ and Java, and they need all the help they can get to work around the defects of those languages. If those people need help, that’s fine. The problem is with the philosophical stance of the movement. Helping hapless C++ and Java programmers is admirable, but it shouldn’t be the end goal. Instead of seeing the use of design patterns as valuable in itself, it should be widely recognized that each design pattern is an expression of the failure of the source language.

If the Design Patterns movement had been popular in the 1980’s, we wouldn’t even have C++ or Java; we would still be implementing Object-Oriented Classes in C with structs, and the argument would go that since programmers were forced to use C anyway, we should at least help them as much as possible. But the way to provide as much help as possible was not to train people to habitually implement Object-Oriented Classes when necessary; it was to develop languages like C++ and Java that had this pattern built in, so that programmers could concentrate on using OOP style instead of on implementing it.

Summary

Patterns are signs of weakness in programming languages.

When we identify and document one, that should not be the end of the story. Rather, we should have the long-term goal of trying to understand how to improve the language so that the pattern becomes invisible or unnecessary.

—Mark Dominus

[ Thanks to Garrett Rooney for pointing out some minor errors that I have since corrected. - MJD ]

[ Addendum 20061003: There is a followup article to this one, replying to a response by Ralph Johnson, one of the authors of the "Design Patterns" book. This link URL is correct, but Johnson's website will refuse it if you come from here. ]

Pages: 1 2 3 4

7 Comments

thleFebruary 10th, 2007 at 1:16 pm

What a long post!
I have not yet read all of the words in this post but I think I know what you want to say.
OO programming has been evolved a lot since its beginning.
Programmers have received a lot from language support. Things usually not perfect when it’s first created. People always try to improve the programming language.

Back to 80’s, the “Internet” concept has not yet popular, most applications just as simple as a simple app that runs on one machine. We did not have “Enterprise Application” that day. So, app is just about 3-5 lines of code, we don’t need Code Reuse.
But the life is not that simple, the demand on bigger applications has increased while Internet becomes more popular. As a consequence, app contains thousands line of code. Now we need Code Reuse, and that’s where Design Patterns starts its life.
When the demand for code reuse increases, programming languages has to change. In C, C++, we don’t have concept of Collection class, Event, …In more modern languages, e.g Java, vb6, we have those concepts. We even have some built-in design patterns in the language such as Iterator in Java. In recent language changes, we have more built-in patterns, e.g ASP.NET has MVC.

It’s obvious that languages and technologies always change in order to improve its weakness. So, is it necessary to say something is a sign of languages weakness? :-)

thleFebruary 10th, 2007 at 3:02 pm

When we identify and document one, that should not be the end of the story. Rather, we should have the long-term goal of trying to understand how to improve the language so that the pattern becomes invisible or unnecessary.

Even if we have a super good language, I am sure that we will still have patterns, as patterns are exprience reuse. it’s something like ” Hey, you want to sth efficiently, do it like me. I did it that way and … it works.”

Buu NguyenFebruary 10th, 2007 at 3:38 pm

What a long post! I have not yet read all of the words in this post but I think I know what you want to say

In case you are not aware, this post is not written by me, it is written by Mark Dominus at http://blog.plover.com/prog/design-patterns.html :-). I find this post very interesting thus I include the verbatim post here.

Back to your comments, while I can see where you are coming from with your arguments, I do not agree with many of them.

Back to 80’s, the “Internet” concept has not yet popular, most applications just as simple as a simple app that runs on one machine. We did not have “Enterprise Application” that day. So, app is just about 3-5 lines of code, we don’t need Code Reuse.

This is not entirely true. Complex applications which run across multiple machines (mainframes and interactive terminals) was not hard to be found in the 70’s. Enterprise applications (ERP for example) written in COBOL (created in 1959) also existed long before the 80’s and consisted of milions of LOCs. And code reuse, contrary to your thinking, was the hope of very early programmers (information about one of the oldest user groups about code reuse can be found at http://en.wikipedia.org/wiki/SHARE_%28computing%29)

In C, C++, we don’t have concept of Collection class, Event

Note that even in the Java language, we do not have these concepts as well. In fact, Collections and Events exist at the library or framework level, NOT at the language level. On the other hand, I agree that the concept of event and delegate exist in a .NET language like C# or VB.NET.

We even have some built-in design patterns in the language such as Iterator in Java

Not true, Java does not have iterator pattern built into the language, it only exists at the library level. However, in languages like Ruby and Python, Iterator is not necessary since closure can address the same need, or C# 2.0 with the foreach and yield keywords is kind of making the iterator pattern blended into the language level (although they are in fact just syntatic sugar and do not exist at the CIL level)

It’s obvious that languages and technologies always change in order to improve its weakness. So, is it necessary to say something is a sign of languages weakness… Even if we have a super good language, I am sure that we will still have patterns, as patterns are exprience reuse. it’s something like ” Hey, you want to sth efficiently, do it like me. I did it that way and … it works.”

Good point! I totally agree with this. Patterns will always be there simply because there is no such thing as a perfect language. Any language, at any level of abstraction, will have patterns associated with it, even if we can code by UML (or even voice :-)). After all, every pattern has a context, and the language itself is part of that context.

Phong BuiFebruary 10th, 2007 at 5:09 pm

At the first time I wrote a singleton class I had the question in my mind that was why doesn’t Java support a way to define a singleton class easier. It would be nice if I need only one keyword to mark a class as a singleton one. I wouldn’t need to handle of creating only one instance or safe-threading. When applying Template pattern to my framework, I recognized that Java seems to be biased this pattern since it has abstract classes.
Those things came and there was something appeared to me that design patterns are well-known chess-positions. Software development is a chessboard and programming languages support fundamental things (i.e move, capture, checkmate, etc…). Those things help programmers play on this chessboard. Let’s say if programming languages had supported resolution for each particular chess-position the player would have proceed only one step to solve the game (instead of doing a number of steps) when it is falling to a predefined chess position.
Stop the chess game above and back to software development, it would be nice if programming languages could enrich them by building-in some well-know design patterns. So I prefer addressing this way rather than calling “languages’ weaknesses” although both result almost same?
We could somehow count the number of chess-positions so far but I cannot count it up to next 5, 10 years or even next 5 minutes since we’re living in a very innovational world. Deep Blue machine was built-in more than 2 million chess-positions but nobody correctly say that’s enough and all for now.

Tai has pointed out some interesting information regarding to design patterns. However, I bet the design pattern is more than code reuse. Design patterns solve design problems. Code reuse is one of design problems.

I almost agree with Buu what you’ve commented on Tai’s notes here. However, for me a programming language is not only syntax but also library. Behind syntax are built-in libraries. Fully separating library from a programming language isn’t somewhat precise.

thleFebruary 11th, 2007 at 6:50 am

I was just want to point out that the increase demand on code reuse, and speedy developed apps; and the languages & technologies has evolved a lot for that demand.
As I said, I did not read thru the post, and did not notice all the details. The post wanted to claim the languages, not the libraries.
Let’s separate C# from Base Classes Library and use it alone, that will create another Microsoft or Sun.

Another point, OO programing rules the game now. Wanted to claim the language, let’s claim OO programing first.
I dont subject to something that will beat OO programing. If there is another better, I will use it. Let’s wait, who knows! :-)

Buu NguyenFebruary 11th, 2007 at 7:15 pm

You have a very interesting comparison, anh Phong; however, I am not quite sure I understand what you aim at by this comparison. Do you want to say that because there are so many chess positions that there should be no limit to the number of patterns? (If this is what you mean then there is at least one flaw: the number of chess positions is finite, while the number of patterns is not.) If not, can you elaborate your argument further?

I bet the design pattern is more than code reuse. Design patterns solve design problems. Code reuse is one of design problems.

I agree. Design pattern is meant to create high-quality design. Depending on the architectural constraints of a particular project, a high-quality design usually mean performance, extensibility, maintainability, reusability, reliability, usability and so on.

However, for me a programming language is not only syntax but also library. Behind syntax are built-in libraries. Fully separating library from a programming language isn’t somewhat precise.

Depending on the topic that we are discussing about, it may or may not be necessary to distinguish the semantics of a programming language from its built-in libraries. For this particular topic (design patterns are signs of programming languages’ weaknesses), it’s worth making the separation.

Buu NguyenFebruary 11th, 2007 at 11:57 pm

…point out that the increase demand on code reuse, and speedy developed apps; and the languages & technologies has evolved a lot for that demand.

That’s true, programming languages and technolgies evolve to help us develop more complex software in less time and reusability is one of the objectives

Let’s separate C# from Base Classes Library and use it alone, that will create another Microsoft or Sun.

Hmm, what do you mean? :-)

I dont subject to something that will beat OO programing. If there is another better, I will use it. Let’s wait, who knows

I guess I’ll elaborate this a bit when discussing about C# 3.0 :-)

Leave a comment

Your comment