9 ms·
A Quiet Defense of Patterns
- Retra 12y ago"This school of thought then claims that the patterns at their scale and above are not indeed patterns, because they have no use of patterns. This thinking is flawed in two ways. The glaring flaw is in the restrictive definition of patterns. The more subtle flaw is in not recognizing that they have patterns of their own at similar scales to the ones that were rejected. Abstraction is extremely powerful, but operating at higher levels of abstraction doesn't appear to imply higher productivity or reduced needs for patterns as a medium for sharing context." The reason we don't get a boost in productivity with higher abstraction is because (a) we have to build such abstractions out of a great number of smaller pieces, so that 'greater abstraction' means 'more work', and (b) it is just very difficult to map our mental models into reusable abstractions. Not very many people can do it well. Yes, every language has 'patterns', but we call those linguistic structure, syntax, or grammar. "Design patterns" refers to something else, (or if it doesn't, it is just a confusing domain-specific renaming of the above.) The problem with design patterns is that they are ostensibly solved problems, and thus people shouldn't be implementing them except pedagogically. Take arrays for instance. There is no "Array Design Pattern", and we don't ask people to implement arrays every time they want to employ them. We ask them to use existing array structure. Yes, you should understand how they work. You probably should implement them once or twice and know how to recognize them. But you do not say "Oh, just use the array pattern here. Start by rolling your own array, since our language doesn't have array syntax." We build arrays into the language so that they are easy to recognize and the pattern becomes a primitive tool. If you have to keep rolling your own, you'll never get past that. It will never become primitive, and you will stagnate. That is what those who object to design patterns object to: by thinking of them as elements of design -- the work of day-to-day programmers -- we won't provide linguistic abstractions that allow them to become primitive tools. We'll be stuck re-rolling our own arrays because people think that this is what programming is all about. Tedium.
- taeric 12y agoThis is really just an extension of the scotsman argument. For one, many people really do regularly relearn the benefits of arrays. To the point that maybe it should get more discussion. For two, not everything can be a linguistic structure/syntax/grammar. Often they are pretty good highlevel descriptions of what is intended. Implementation left to the reader. Which is ultimately the problem. Two implementations of the visitor pattern may have made different trade offs for what they are doing. Same for many other patterns. Singleton is often itself used as a tradeoff in terms of flexibility. Now, I fully agree that when used without thinking/acknowledging the tradeoffs, they lead to issues. They are not unique here. Consider actors. Arguably the vogue pattern for the popular crowd nowdays. Can you honestly tell me the vanilla actor is a solid win?
- Retra 12y ago>not everything can be a linguistic structure/syntax/grammar. Says who? Why should I believe this?
- taeric 12y agoSays experience. Tritely, why should I believe the contrary? I've certainly seen it tried enough. Yet to work. There is also the parallel to spoken languages. Where there are pretty good patterns of speach for making different points. Why haven't all of those been converted to simply an atomic linguistic structure.
- Retra 12y agoExperience would have told you that human flight was impossible just 110 years ago. The reason you should believe the contrary is because it is an open world, and there is not proof that you are correct. >There is also the parallel to spoken languages. Where there are pretty good patterns of speach for making different points. And programming is largely a domain specific task today, so you could have pretty good patterns for it. But anyway, that parallel expresses a better point: language is extensible. If you have something in another spoken language to express, you can certainly do it in any other language. You just can't maximize terseness everywhere, which is not what we're using to measure how good a language is. The measure for this is terseness in proportion to usage, which doesn't conflict that rule. Especially if you can control terseness dynamically.
- jacquesm 12y ago> Yes, every language has 'patterns', but we call those linguistic structure, syntax, or grammar. The higher level of linguistic structure, syntax or grammar is the 'idiom', and idioms are a small step below the 'pattern'. So I think there are differences there. Arrays are a datastructure, not a design pattern, but allocating an array, populating it, using it to recall its contents and finally destroying it could be called a pattern (or an idiom, if you prefer).
- Retra 12y agoIdioms are always language-specific. The word idiom essentially means "a peculiarity of language" or "a phrasing that wouldn't work elsewhere." But we're being vague here anyway, because 'pattern' is a vague word. Everything is a pattern. Data structures are a structured pattern of data. Whether you choose to implement something as an array or as a hash table is a "design pattern": a pattern invoked by a designer to solve a problem. You don't have to use a singleton pattern or a visitor pattern. You choose to as a consideration of your design. But you shouldn't have to roll your own code to make that design work, because we have a name for it and we know what you're talking about. It should be in a library or in the language. (Which, in my opinion, is a farcical distinction: languages and libraries should always be considered together at all levels, including in language design.)
- nkurz 12y agoIt's interesting to switch your example to "Hash Table" instead of "Array". C is the language I'm most familiar with, and lacks one as part of the core language. So in fact, C essentially does say "Oh, just use the (associative) array pattern here. Start by rolling your own..." Does this mean that a design pattern is not an absolute, but relative to a language? Or does it mean that there is no clear distinction between syntax and pattern? I don't think that being one excludes being the other. We build arrays into the language so that they are easy to recognize and the pattern becomes a primitive tool. If you have to keep rolling your own, you'll never get past that. It will never become primitive, and you will stagnate. That is what those who object to design patterns object to: by thinking of them as elements of design -- the work of day-to-day programmers -- we won't provide linguistic abstractions that allow them to become primitive tools. Rather than fearing that naming a concept will cause stagnation, I think the opposite: the failure to have a "shorthand" for a commonly used feature means it will continually be reinvented. Once named, the concept can be pushed down to syntax while remaining a design pattern. The surprise (to me) is that the gulf between being part of the language and being an easy to add library is so great. Why is there no standard hash table that gets used in C? Why is there such a difference between core and non-core? I don't know what it is, but don't think it's for lack of syntax.
- Retra 12y ago>Rather than fearing that naming a concept will cause stagnation, I think the opposite: the failure to have a "shorthand" for a commonly used feature means it will continually be reinvented. Once named, the concept can be pushed down to syntax while remaining a design pattern. This is exactly the problem with design patterns. Once you recognize a design pattern, you should abstract it away and just use it from a library. Sometimes that is very hard to do. (E.g., Model-View-Controller.) But just because it is hard doesn't mean it is impossible. That kind of activity is a prime measure of success in computer science. Of course, we have the internet, but we still don't write languages that expect to pull needed tools from the internet in a smart way. You have to manually look for a library and include it yourself. When you write some code, it isn't being compared against a database of online code with your IDE telling you "Hey, someone else wrote something like this and it runs way faster and uses less text, check it out maybe?"
- cessor 12y agoI felt that your comment speaks to me - I had a similar understanding a couple of years ago. In their book "Growing Object Oriented Software, Guided by Tests", Nat Pryce and Steve Freeman describe values and objects, *(Values in the sense of Value Objects in Evans' DDD) > The confusion is, that both concepts are implemented by the same language construct: Classes This made me think. In C# this statement is somewhat untrue, since you have structs that have value semantics (value equality). But why are there no other concepts within the language that help you from reinventing the pattern wheel? For example, I had seen the singleton pattern quite frequently in a codebase I worked on, with the label leaking into the class name. But why is it that you have to write: public class DatabaseConnectionSingleton { ... } and then deal with all the static stuff (i.e. x.Instance()) rather than public singleton DatabaseConnection { ... } Like this, you could easliy use standard stuff: new DatabaseConnection() and the runtime would simply return the same instance. This would keep people from reinventing the mechanism. Like IoC / DI built into your language... [1] http://www.amazon.co.uk/Growing-Object-Oriented-Software-Guided-Signature/dp/0321503627 http://www.amazon.co.uk/Growing-Object-Oriented-Software-Gui...
- dragonwriter 12y ago> Yes, every language has 'patterns', but we call those linguistic structure, syntax, or grammar. "Design patterns" refers to something else, (or if it doesn't, it is just a confusing domain-specific renaming of the above.) The problem with design patterns is that they are ostensibly solved problems, and thus people shouldn't be implementing them except pedagogically. Well, except that the whole reason for documentation of design pattern implementations is that, in the languages for which they are documented, they generally do not admit of a reusable library implementation because of limitations in the abstractions available in the language. That's why people (slightly inaccurately) say that certain languages (Lisps are frequently cited here) don't need design patterns -- the kinds of things documented as design patterns with implementation recipes for Java/C++-like languages can often be implemented in library code in lisps (to a certain extent this is also true of many dynamic OO languages, like Ruby, and sometimes in static functional languages, like Haskell), so the kind of recipe-style presentation and fill-in-the-blanks implementations seen in Java/C++ patterns just aren't applicable in some other languages. (Sure, you can address design patterns by building each one into the language individually, the way you discuss with arrays, and that will shift which patterns the language needs at the expense of a bigger base language. You get more bang for the buck building languages which are expressive enough to allow you to reusably implement a broad array of "patterns", so you instead of implementation recipes you just need libraries with API documentation.)
- Retra 12y agoI think part of this problem is that people want to invent compact, 'small' languages, and leave the rest to libraries. This kind of thinking is what makes it hard to move up, because it is just a variation on "our language is ASM, if you want fancy stuff, just write it as a library in ASM." Language design should be about saving the end programmer from having to do extra work, not minimizing your core language and deferring the savings for later. Of course, there is some push-and-pull here, because we want to make languages small so that they are comprehensible. So what we want are the smallest possible languages that can express a broad array of powerful abstractions with minimal effort. This is why I hate the "no language is the best" line of thought. (Which is similar to "ever language uses design patterns.") There is no theoretical reason why there can't be a best language. All we have is a history of languages that suck to look at. You can't infer that all possible languages suck at something from our short history of terribleness. It is 2015. What kind of languages will people be using in 4015? How about 14015? Are they going to be saying "It doesn't matter what language you use?"
- vog 12y agoIndeed, there are many "mechanic" patterns (e.g. Singleton) which are just documented workarounds for flaws in popular programming languages, more precisely in their type systems. However, this is only half of the story. There are also "real" patterns (e.g. Facade) which describe by what criteria you should structure your code in what circumstances. These can't be directly translated into a language feature, library or framework, as they still require human judgement on the details. One might disregard these patterns as "soft" or "too imprecise", but I think these are the real patterns. These helped me more than any of these mechanic patterns.
- Jare 12y agoIn my experience, design patterns encourage two big problems: - Deciding on a solution before having explored the problem. "I have a pattern for that." - They act as shared context only on the surface; all the details and subtleties of the pattern as an implemented artifact are rarely shared, and communication suffers. In practice, they tend to make the easy stuff easier, but the hard stuff harder.
- jacquesm 12y agoThat goes for any mis-applied tool. If you approach the world with your toolbox ready in hand and you refuse to adapt your tools to the problem then you get this mismatch. Tools were created to solve repetitive problems, if your problem is not one of those then you should improve your toolset, maybe come up with an entirely new tool or maybe you should adapt an existing one until it works better for your application.
- Jare 12y agoI agree, my point is that in practice, patterns encourage that kind of mis-application in many many programmers, and not just the bad ones. The reasons why they do are part of years-old and still unsolved debates. But I know what I saw: fresh off my love affair with the Lakos C++ book, I though GOF was the next cornerstone of OOP and a must read for everyone. Over the next few years, design debates and proposals where design patterns featured more and more prominently, started turning into bizarre minutiae and half-explored problem discussions. Again, simple and noncritical pieces of software seemed easier to describe and even develop, but the hard stuff became harder to manipulate, overabstracted, took longer to be truly finished (although it got to MVP state faster), and usually much less performant.
- programminggeek 12y agoProgrammers by and large don't seem to understand the power of language primarily as a communication tool and the lessons around communication we ought to understand. We think in solitary terms as if it is of primary importance how we write code individually instead of how we communicate with each other (and the machine). Patterns if done well give us a language to solve problems in sensible ways as teams. Instead, we worry about how patterns are named and argue over minutiae. We let things like "exceptions should only be used for exceptional behavior" distract us from effectively communicating with each other. Our industry sees things like FP, OOP, Design Patterns, etc. as an exercise in taxonomy when building software is an exercise in communication. It's like we are writing a novel, but we are more worried about the names and families of characters than the actual plot itself. That doesn't make for a good book and it doesn't make for good software.
- cessor 12y agoThe author suggests a common opinion on patterns, that I have seen violated a billion times: > Two people with a common set of patterns find it easier to communicate [...] than those without one. > [...] writing down our shared context lowers the barrier to entry. In my experience this is often not the case. Patterns come along with labels and the labels will be put everywhere in a codebase. Assumptions get made and replace discussions, leading to a diluted codebase. For example Repositories will become synonyms for "thing that does database access", and will then be reduced to stupid GetByID wrappers [1]. Even worse, some patterns make entry really hard. I used to work with C# and ASP.NET MVC. There, a view is the thing that contains markup, the thing controlling the input is the controller. Then I started using Flask and was utterly confused, since there the functions with the @app.route decorators, which are run on the server and then return markup rendered via jinja2 templates, are called view functions. In Django this is understanding is the same. I was really baffeled. I could not reapply my understanding of the patterns across these domains. This is just one explicit example that I wrote about in my blog [2], but I really made the general experience that patterns replace or inhibit discussions, rather than improving communication and understanding. [1] http://philcalcado.com/2010/12/23/how-to-write-a-repository/ http://philcalcado.com/2010/12/23/how-to-write-a-repository/ [2] http://www.cessor.de/on-patterns http://www.cessor.de/on-patterns
- ArneBab 12y ago> The critics may be right that it devalues the craft, but we would all do well to remember that the craft of software is a means, not an end. I don’t think that patterns devalue the craft. Also they helped me get a better understanding of what I do. For example in Python you can create a Singleton by simply accessing an instance which is instantiated directly in its module. The pattern is built-in and very easy to use, but I only started making heavy use of it when I learnt the Singleton pattern. It was then that I realized how much value this simple language feature provides. > “In a functional language…you end up programming in concepts that eliminate design patterns all together.” I saw lots of ad-hoc patterns which have to be understood to understand the code.
- praptak 12y agoI was a bit confused whether the author argues for patterns as Platonic idea, patterns as popularized by GoF or patterns as popularized by Christopher Alexander. The most vicious arguments I have read were about GoF not keeping the spirit of CA. One example is GoF being a sort of disconnected catalogue, while CAs patterns are supposed to generate the world. I don't see these referenced in this article.
- emsy 12y agoWould patterns exist if we had no name for them? In my opionion, definitely yes. So giving them a name doesn't change the nature of patterns. Problems arise when a, now named, pattern gets misused. The misuse is therefore always commited by the developer. The two main critic points I've read in the comments were: - Developers try to find a problem to use a pattern they know This error is mostly commited by people who learn the first time of patterns and are giddy to use them. I wonder if this was less likely to happen, had the GOF included a warning about this in their book. - Developers keep using the wrong terminology and this causes patterns to become squishy Just stick to the GOF terminology and your good to go. In my eyes, the patterns discussion is just an indicator for a greater "problem": Anyone can become a software developer. I won't elaborate on the positive aspects of this. But it's clear that areas with a higher entrance bar, like law or health, have a greater professionalism and, among other advantages, a standardized terminology.
- zamalek 12y agoTo me patterns have always been incredibly useful as a book of problems that have been solved, somewhat like a chess playbook. Would I ever implement them directly? Maybe, if they were directly appropriate. Often I find that my solutions are pattern inspired, "factory-like," "observer-like," "strategy-like" etc. Even more frequently my solutions are a hybrid of multiple patterns. That's where I see their value: they are extremely good blueprints. Like every tool, they are incredibly powerful if used correctly. They are most often misused, especially in the case of verbatim use.
- hawleyal 12y agoI disagree. Patterns are often just used as a way to work around the limitations of expression in a given langauge. Sure, they can be useful. But in the long run, they are not the goal, they are the unfortunate means to an end.