44

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?

Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
Ewan Todd
  • 7,315
  • 26
  • 33

12 Answers12

53

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.

Community
  • 1
  • 1
Juliet
  • 80,494
  • 45
  • 196
  • 228
  • 1
    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
  • 3
    "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
  • 2
    @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
  • 2
    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
  • 1
    @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
  • @S.Lott The mark of a good language is to have things that need to be done often be very simple to state. Consider a compression algorithm - a file compressed with the perfect algorithm has no patterns; it's all information. – Brilliand Jan 27 '14 at 23:45
18

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
  • 27,253
  • 7
  • 76
  • 97
  • 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
  • 1
    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 01 '11 at 20:05
12

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
  • 384,516
  • 81
  • 508
  • 779
2

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.

David R Tribble
  • 11,918
  • 5
  • 42
  • 52
2

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
  • 26,876
  • 10
  • 61
  • 112
  • 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
2

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.

6502
  • 112,025
  • 15
  • 165
  • 265
1

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
  • 159,146
  • 25
  • 197
  • 199
1

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
  • 178,213
  • 47
  • 333
  • 501
  • 1
    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
  • 1
    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
0

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
  • 37,065
  • 18
  • 127
  • 179
0

Design patterns are not weakness in languages. They provide design solutions to recurring problems.

Since many things have been evolving over time, I think Enterprise Integration Patterns are going to be popular.

If different enterprise application have to communicate, these patterns provides best solutions.

  1. Integration Styles document different ways applications can be integrated, providing a historical account of integration technologies. All subsequent patterns follow the Messaging style.
  2. Channel Patterns describe how messages are transported across a Message Channel. These patterns are implemented by most commercial and open source messaging systems.
  3. Message Construction Patterns describe the intent, form and content of the messages that travel across the messaging system. The base pattern for this section is the Message pattern.
  4. Routing Patterns discuss how messages are routed from a sender to the correct receiver. Message routing patterns consume a message from one channel and republish it message, usually without modification, to another channel based on a set of conditions. The patterns presented in this section are specializations of the Message Router pattern.
  5. Transformation Patterns change the content of a message, for example to accommodate different data formats used by the sending and the receiving system. Data may have to be added, taken away or existing data may have to be rearranged. The base pattern for this section is the Message Translator.
  6. Endpoint Patterns describe how messaging system clients produce or consume messages.
  7. System Management Patterns describe the tools to keep a complex message-based system running, including dealing with error conditions, performance bottlenecks and changes in the participating systems.
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
0

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.

alvin
  • 1,176
  • 8
  • 15
0

To answer the question "What patterns will they have?":

Java haves the Singleton pattern which is implemented in Kotlin with the object keyword

I don't know if patterns are weakness of languages, but for me it's one of Kotlins strengths that it makes the use of Singletons easy.