Take the 2-minute tour ×

Should today's patterns be seen as defects or missing features in Java and C++?

  • Subroutine was a design pattern for machine language in the 50s and 60s.
  • Object-Oriented Class was a design pattern for C in the 70s.
  • Visitors, Abstract Factories, Decorators, and Façades are design patterns for Java and C++ today.

    What will tomorrow's languages look like? What patterns will they have?

share|improve this question
Voting to close: Asks for extended discussion. It's a great question though. It also probably needs to be a wiki, since there's not one discrete answer and it's a discussion question that can't be objectively answered. –  George Stocker Oct 16 '09 at 16:58
This question shouldn't be closed; but it should be a community wiki. –  Jim G. Oct 16 '09 at 17:21
"Community wiki" does not mean "there's not one concrete answer and it's a discussion question that can't be objectively answered." It means "content that's communally owned and editable by just about anyone." –  Chuck Oct 16 '09 at 17:26
@Chuck: also, community wiki questions don't have a big influence on reputation scores. There's no expectation of a "correct" answer in a community wiki question. –  S.Lott Oct 16 '09 at 18:20
Seems to call for outright prognostication, does it not? SO better on a blog or some forum. –  dmckee Oct 17 '09 at 14:23
show 1 more comment

10 Answers

up vote 38 down vote accepted

Some canonized design patterns -- Adapter, Factory, Command, Visitor, etc -- are approximations of features which are baked into other languages. Off the top of my head:

  • Event-handlers in C# are baked-in versions of the observer pattern. Think about how you'd wire up events in C# if you had to roll your own observer each time.

  • Visitor pattern is a verbose approximation of multimethods, message forwarding, or a really weak form of pattern matching.

  • Command pattern wraps up a particular behavior so you can pass the object between methods, which more or less approximates first-class functions.

  • Strategy pattern allows you to dynamically insert a behavior into an object, so that at any time you can modify the object by swapping out one behavior with another. In the functional programming world, we call this function composition.

  • Abstract factory pattern accepts an argument and returns a factory as a result. In general, you can think of factories as basically wrappers around a function (more specifically, wrappers around a constructor). So, you pass arguments to a function and get a function as a result, making this pattern pretty analogous to currying.

  • Decorator pattern allows you to attach or remove behaviors to an object at runtime. In JavaScript, you can add or remove functions without explicitly implementing the decorator pattern thanks to the "prototype" OO model.

So, we have a bunch of design patterns which emulate features intrinsic to other languages. Feature envy doesn't necessarily indicate a weakness in the language -- it's the boilerplate code that you need to write over and over and over which indicates the language weakness.

share|improve this answer
I really like this answer. It suggests that some named patterns are already in humble everyday use. It makes me think, "OK, here's your special set of patterns for tomorrow's super language". –  Ewan Todd Oct 16 '09 at 17:58
"tomorrow's super language" cannot come from today's languages. It has to be rather different -- otherwise we'll just use today's languages with a few extensions. –  S.Lott Oct 16 '09 at 20:08
@S.Lott: "Tomorrows super language" will probably come around at the turn of the technological singularity and will, as I can certain imagine, render all design patterns obsolete ;) –  Juliet Oct 16 '09 at 20:23
I really like it too. The last sentence is probably the best possible answer to this question. It also never occurred to me that factory-factories are an incredibly verbose form of currying. –  Chuck Oct 16 '09 at 20:29
@Juliet: Nothing renders design patterns obsolete. Any time you repeat something, that's a pattern of design. It always happens in all disciplines, always. –  S.Lott Oct 17 '09 at 21:30
show 2 more comments

I wouldn't call them defects.

Higher order languages deal with concepts at a higher level than lower order languages. Think of it in construction terms.

You could build a building at the refinery level, milling lumber, smelting steel, and put together a building that way.

You could purchase boards and steel girders, and construct them into a building.

You could purchase pre-fabricated walls and trusses and construct them into a building.

You could purchase a building and just start with the interior.

Is constructing a building with boards and girders missing the prefabricated wall feature, or defective in some way?

share|improve this answer
+1 for the metaphors. Excellent answer. –  Robert Harvey Oct 16 '09 at 18:43
Often when talking about patterns you just are using the same design, but you have to code the whole thing yourself every time. The analogy with prefabricated stuff doesn't hold IMO ... that would be using a library (and there's nothing bad about it of course). –  6502 Jan 30 '11 at 16:43
My point was more about when patterns are baked into the language. When you don't have to write the observer pattern yourself from scratch for instance, it is sort of like using a prefabricated component in construction. It's not a perfect metaphor though, I will agree with you on that. –  Matthew Vines Feb 1 '11 at 20:05
Wonderful Answer...Thanks a lot !! –  Praveen Prajapati Oct 16 '13 at 15:56
add comment

Every single thing that you do three or more times in software designs forms a pattern.

Every repetition. Every repetition. Every repetition.

Some get canonized with cool names. These become Design Patterns. Conscious repetition.

Some are just "best practices" or "this has worked for me." These are design patterns without the clarity.

Some are just "things you usually do." These are design patterns without any conscious recognition that you're repeating yourself.

Design patterns have nothing to do with language weakness or incompleteness. They have everything to do with good ideas, consciously reused.

Today's design patterns are not the royal road to tomorrow's languages. The language paradigm does not advance through a series of "bug fixes to previous languages". If it did, we'd never have created Visual Basic.

And design patterns are a far larger and broader intellectual tool than a simplistic programming language feature set.

share|improve this answer
OK, but did you answer his question? –  Robert Harvey Oct 16 '09 at 18:42
I thought I did, but I edited my answer to pound my point home even more heavily. –  S.Lott Oct 16 '09 at 20:06
I think this is an excellent point. It seems it's more a case of many of better known - mostly GoF - patterns being superfluous in other languages. –  luke_randall Jun 28 '11 at 13:08
add comment

No, they are not missing features or defects of the languages. But the languages should provide a means for writing the code for a useful pattern easier rather than difficult. That's where the features that are provided by the language can either be a boon or a hindrance.

share|improve this answer
add comment

I think Ewan brings up a fascinating point. Take his "subroutine" example. In early programming languages, the idea of passing parameters to a subroutine and returning a result was something that you had to explicitly code. In modern languages, it's built in. Or to take another example: If/then/else is built into most if not all modern languages. But back in my assembler days, I had to write code to accomplish that. Not a lot, of course, but still, you had to actually write the jump or goto statement to go around the else block. And the fact that you had to write these things yourself meant that different programmers would do it in slightly different ways, and there was the endless temptation to be clever and do it a little differently in this program to make it more efficient or gain some other supposed advantage.

The most recent example that comes to mind is iterators. You have to hand-write them in C++ and early versions of Java, but they're built in to Java 5. This is arguably syntactic sugar, you're just as well to simply create iterator functions. Personally I think it's a nice feature. Does it radically improve my productivity? No.

Is there something that we are doing all the time that should logically be built into the language to standardize and simplify it? A fascinating question. I don't suppose that anyone will seriously claim that even their favorite language is perfect and absolutely no improvement is possible. But what will the direction of the next language be?

Surely some features that have been added to languages are useless extra baggage. In my humble opinion, Java enum's do way more than is necessary, they add a bunch of baggage for no good reason. I'm sure others will disagree and say that they find them incredibly useful.

I don't have a conclusion. I just agree that it's a fascinating question.

share|improve this answer
I have to credit the linked article for the original thought. Your point about syntactic sugar made me think about the distinction between different kinds of language improvements. On the one hand are those that would merely make it easier to create structures that we are already able to put together, albeit laboriously, using functions and classes. On the other hand are the truly brilliant innovations, on the scale of the subroutine or if-else blocks, that mark a fundamental shift in the programming landscape. –  Ewan Todd Oct 16 '09 at 18:14
I'd disagree slightly in that I'd be hard pressed to think of a programming construct that could not be achieved with sufficient effort. You could write a subroutine or an if/else or do object-oriented programming in assembler, it's just hard. So it's not hard-but-possible versus impossible, but it may be hard-but-practical versus way-too-much-work. But I don't think that was your key point, rather you are talking about the difference between "cute" and "brilliant". Right? –  Jay Oct 19 '09 at 13:15
add comment

I think some design patterns do represent language weaknesses and new languages incorporate existing patterns into first class citizens. An example of a new language taking existing design patterns in other languages (dependency injection, immutability, etc.) and incorporating them as first class language level features is NOOP from Google.

share|improve this answer
add comment

I am wondering how much you can cram into a language before it gets too "large."

I like the language I am working with to be small enough to hold in my head all at once. Patterns such as DI have to do with structural concerns; should that be a part of the language?

How much hand-holding in the language does a developer really need?

In the case of Code Contracts (requires, ensures), it is nice when that is a first-class part of the language, but it is not required. It can still be part of a library.

share|improve this answer
An argument can be made that the language should be as small and orthogonal as possible, and its library be usefully large. In other words, offload as much as possible into the library instead of cluttering the language with lots of rarely-used esoteric syntax and special cases. –  David R Tribble Oct 16 '09 at 17:17
Is it harder to remember a larger language, or a smaller language plus additional patterns? –  David Thornley Oct 16 '09 at 18:56
It's easier to have in the language those core things that have "universal application", and have in libraries those things that are needed in specific situations. You can always look up the patterns in a reference, but the everyday things that you need in a language should be committed to memory. –  Robert Harvey Oct 16 '09 at 19:56
So generally you can be more productive in smaller (but complete) languages. –  Robert Harvey Oct 16 '09 at 20:04
add comment

I've read somewhere something like "the more patterns you have, the less powerful your language is" and I find this definition very nice.

The reason is IMO clear: if you see a repeated pattern (or you have to use it) it means that it's a sort of copy'n paste at a logical level. Of course it's not as bad as copy'n paste of statements, but it's still redundancy. I'm still repeating myself again and again.

The more the language is expressive and the more you should be able to capture and factor this redundancy out by transforming it in reuse instead of reimplementation, and the reuse will be easier to read and understand in the source code.

Every time you find yourself doing the same thing once again (including e.g. "ok... let's implement an abstract factory here") it means that's something that should have been expressed at an higher level.

Of course sometimes you can try to capture the essence of something, but the reuse may be uglier to read than the reimplementation (I'm thinking for example to some parts of C++ "high-level" stuff in <algorithm>). This is IMO a clear sign that the language is not expressive enough.

share|improve this answer
add comment

Frameworks that facilitate the use of certain patterns in languages do exist, so they're more of a choice rather than a must. There are patterns that for a certain project, you might just not need, so incorporating a lot of them as primary language features would only impose restrictions rather than facilitate productive work.

share|improve this answer
add comment

each language is an arbitrary set of design patterns with syntax as the notation for the chosen patterns. for the unchosen patterns, you have to meddle within the constraints of the syntax to express them. most of the languages does not allow its syntax to change much to assimilate higher level patterns.

a language that can do that limitlessly would be one without a rigid syntax. (or in another way, one that allows to seamlessly assimilate any high level pattern). see metalinguistic abstraction

the one that comes to my mind is scheme/lisp.

share|improve this answer
add comment

Your Answer


