views:

941

answers:

9

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?

+1  A: 

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.

Asaph
+7  A: 

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.

S.Lott
OK, but did you answer his question?
Robert Harvey
I thought I did, but I edited my answer to pound my point home even more heavily.
S.Lott
+13  A: 

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?

Matthew Vines
+1 for the metaphors. Excellent answer.
Robert Harvey
A: 

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.

Robert Harvey
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.
Loadmaster
Is it harder to remember a larger language, or a smaller language plus additional patterns?
David Thornley
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
So generally you can be more productive in smaller (but complete) languages.
Robert Harvey
A: 

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.

luvieere
+1  A: 

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.

Loadmaster
+22  A: 

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.

Juliet
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
"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
@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
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
@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
+1, yet another brilliant answer by Juliet..
CaptainCasey
+1  A: 

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.

Jay
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
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