107

I've started reading the design pattern book by the GoF. Some patterns seem very similar with only minor conceptual differences.

Do you think out of the many patterns some are unnecessary in a dynamic language like Python (e.g. because they are substituted by a dynamic feature)?

yannis
  • 39,547
  • 40
  • 183
  • 216
Gere
  • 2,191
  • 2
  • 17
  • 21
  • 2
    Kind of an interesting question, since it implies that language choice can effectively substitute for code constructs. – joshin4colours Jul 24 '12 at 21:11
  • 3
    Not an answer, but relevant - I thought the GoF design patterns were as relevant for some general principles that can be distilled out of them as for the specific patterns. I don't mean the idea of a pattern (though that's certainly significant), but more the permission to use classes in certain ways that violate naive OOP principles. For example, there's plenty of patterns where "the shape" quite clearly does not "draw itself", or at least delegates some aspect of the job to some other object. I think that lesson is important in any language that supports OOP. –  Jul 29 '12 at 19:19
  • Very interesting question. I wish I could +5 instead of +1. – MathAttack Aug 02 '12 at 11:27
  • 1
    Glance aslo at [Are Design Patterns Missing Language Features](http://c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatures) and [Design Patterns Are Missing Language Features](http://c2.com/cgi/wiki?DesignPatternsAreMissingLanguageFeatures) over at c2. Its not even a 'dynamic language' issue. The simplest example is the iterator pattern which is trivial in python, perl (and even Java - not dynamic). –  Oct 17 '12 at 14:30

8 Answers8

101

Peter Norvig demonstrates that 16 out of the 23 design patterns found in the GOF book are invisible or simpler in dynamic languages (he focuses on Lisp and Dylan).

Since you mentioned Python, there is a nice presentation by Alex Martelli about the topic. Also related with Python, there is a nice blog post demonstrating six design patterns in idiomatic Python.

I also keep a github repository with implementations (by other people) of the most common design patterns in Python.

Wildcard
  • 544
  • 3
  • 14
sakisk
  • 3,377
  • 2
  • 24
  • 24
  • Great! That would be a spot on answer :) I wished everyone had grasped the question that clearly. – Gere Jul 25 '12 at 08:55
  • 2
    According to Norvig, 2 of the 16 (Interpreter and Iterator) are "either invisible or simpler" due to macros (which Python doesn't have). – mjs Jul 29 '12 at 21:19
  • 1
    its not clear to me that all these patterns aren't need because lisp is dynamic but rather because of other features such as being a strong functional language – jk. Oct 10 '12 at 14:20
  • @mjs Iterators are a builtin feature of Python. – sakisk Oct 15 '13 at 10:03
  • 1
    @faif Norvig's paper was written in 1996, before Python had iterators. (It seems they arrived in version 2.1 http://www.python.org/dev/peps/pep-0234/.) – mjs Oct 15 '13 at 11:02
  • 1
    This great answer can be even slightly improved by changing the somewhat meaningless link captions *demonstrates*, *presentation* and *repository* - they are far better then *here*, but, you know... :-) – Wolf Jan 08 '15 at 11:47
64

No design patterns are necessary. In any language.

I tend to come across a lot of code written by people who read up on design patterns and then think they should use them all over the place. The result is that the actual code gets buried under tons of interfaces, wrappers and layers and is pretty hard to read. That's a wrong approach to design patterns.

Design patterns exist so that you have a repertoire of useful idioms handy when you come across a problem. But you should never apply any pattern before you identify the problem. Keep It Simple Stupid should always be the superior governing principle.

It also helps to think of design patterns as a concept to think about the problem rather than specific boilerplate code to write. And about much of the boilerplate as workaround to Java lacking free functions and standard function objects that you use in most other languages that have them (like Python, C#, C++ etc).

I might say that I have a visitor pattern, but in any language with first class functions it will be just a function taking a function. Instead of factory class I usually have just a factory function. I might say I have an interface, but then it's just a couple of methods marked with comments, because there wouldn't be any other implementation (of course in python an interface is always just comments, because it's duck-typed). I still speak of the code as using the pattern, because it's a useful way to think about it, but don't actually type in all the stuff until I really need it.

So learn all the patterns as concepts. And forget the specific implementations. The implementation varies, and should vary, in the real world, even just in Java.

Jan Hudec
  • 18,250
  • 1
  • 39
  • 62
  • 29
    Your opening statement is oversimplifying to the extreme. It is true that patterns have their cost, so shouldn't be used blindly, just for the sake of it. But in the right place, they can be a great help. And yes, they are language specific - *some* patterns are unnecessary in *some* languages because the language itself supports a better approach. But that is still pretty far from your opening claim. – Péter Török Jul 24 '12 at 08:39
  • Strictly speaking I didn't ask which patterns are necessary, but instead which are unnecessary, which is a logical difference. There is a difference between "you never need pattern A" and "you never need all of the pattern". Moreover, patterns provide ideas and a vocabulary. Before knowing patterns I refactored code a few times, and if I had known pattern before, I would have had my final idea earlier. So I wouldn't discredit knowledge about patterns. – Gere Jul 24 '12 at 08:41
  • 2
    Btw Visitor is not entirely replaced by higher order functions - it is a solution to implement double dispatch in a language which doesn't natively support it (such as C# and C++). (And it should indeed be used very sparingly - I consider it one of the most arcane and costly patterns whose usage is IMHO so hard to justify that I myself have never used it up to now.) – Péter Török Jul 24 '12 at 08:44
  • 14
    Well, you never *need* a pattern. What you need is to *solve a problem*. If you don't know any pattern for it, you can still solve it, it will take more thinking and you may come up with a solution that matches some pattern or one that does not. Knowing the patterns just makes it easier. – Jan Hudec Jul 24 '12 at 09:18
  • 4
    @Gerenuk: Yes, but the point is, that the patterns are not language-specific, they are for your head. You often find that some pattern is realized much more easily and using different tools in python, but the same concept usually exists. – Jan Hudec Jul 24 '12 at 09:23
  • 4
    @PéterTörök: Visitor is not replaced by anything. The point is the same concept might be implemented using different tools in different cases, but I still consider it the same pattern. – Jan Hudec Jul 24 '12 at 09:25
  • @Jan: Sure. That's a true sidenote, but you are answering questions that haven't been asked. Nowhere I mention that I plan to construct a program of patterns only. I'm basically asking which pattern I can forget safely. – Gere Jul 24 '12 at 10:31
  • 2
    Well, you never *need* patterns in the sense that you never *need* screwdrivers etc. for assembling furniture. Yeah, in theory you can get by without these - with much more effort, time and pain. So in practice no serious professional would leave such tools out of his/her toolbox. – Péter Török Jul 24 '12 at 11:34
  • loops are also not necessary in any language. nor routines. – Stefano Borini Jul 24 '12 at 14:22
  • @PéterTörök, the pattern still exists even if it's native to the language. It just means it's easier to implement the pattern – CaffGeek Jul 24 '12 at 21:45
  • The design pattern isn't for you - it's for the guy who is going to have to maintain your code. – Kirk Broadhurst Jul 30 '12 at 05:16
  • 1
    @KirkBroadhurst: Yes. But keeping it simple is even more. Using design patterns to come up with usual solution rather than obscure trick is good, but using design patterns literally usually leads to unnecessarily complex code and that rarely helps maintainability. – Jan Hudec Jul 30 '12 at 07:02
  • @JanHudec I agree and I'm not a fan of implementing design patterns, but I do think that rigid implementation of design patterns might resolve problems like http://programmers.stackexchange.com/questions/158640/why-cant-the-it-industry-deliver-large-faultless-projects-quickly-as-in-other – Kirk Broadhurst Jul 30 '12 at 07:11
  • 2
    This. Design patterns for the sake of design patterns is something that shouldn't exist but is incredibly common. – orip Jul 30 '12 at 18:58
  • Yes, I will subscribe to your blog. – shoosh Jul 30 '12 at 23:32
16

Abstract factory pattern is unnecessary in duck-typed language such as Python, as it's practically built into the language.

vartec
  • 20,760
  • 1
  • 52
  • 98
  • 10
    well, you still need different factories. You just don't need the interface definition. – Stefano Borini Jul 24 '12 at 14:26
  • 1
    If you have a class, you have a factory already. Classes are first class objects and can be passed around everywhere and simply called to create an object (unlike Java). You don't need to create anything else. If you want something that is not the default constructor, just create a lambda/callable of some kind that wraps the constructor in some way. – spookylukey Dec 29 '17 at 10:41
15

The only one that comes to mind is the Singleton pattern.

Since Python doesn't force you to use classes for everything, you can just use a global data structure instead. That global data structure could be managed by an instance, but you do not have to control the instantiation of that class, you just create the instance on import and leave it at that.

Mostly, Singletons in python are replaced with a module. Modules in python are by their very nature Singletons; the python interpreter creates these once and once only.

All other patterns in Design Patters I've used in Python at one time or another, and you'll find examples of them throughout the Python standard library and in Python itself.

Martijn Pieters
  • 14,499
  • 10
  • 57
  • 58
  • 2
    Isn't that actually an anti-pattern these days? – Den Jul 24 '12 at 08:00
  • 16
    The Singleton is [an antipattern](http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/). In all languages. It was created to solve several unrelated problem and is not a good match for either (note, that even Java has static members, that exist once per class, so you don't need an instance for that). – Jan Hudec Jul 24 '12 at 08:00
  • 1
    And in Python we never bothered with it as there never was a problem to solve. – Martijn Pieters Jul 24 '12 at 08:12
  • 2
    *"Python doesn't force you to use objects for everything"* Not true. It's just not obnoxious as in Java, but still, in Python everything is an object. Even module is an object. – vartec Jul 24 '12 at 10:37
  • @vartec: or it is a type. And functions can be just functions, you are not forced to use methods, part of a class. – Martijn Pieters Jul 24 '12 at 10:45
  • 1
    Functions are objects. Types are objects. Just because you don't have a lot of boilerplate as in Java, doesn't mean that Python is not full OOP. For example in Python you do `"a".upper()`, in other words you call **a method**, unlike in not OOP languages, where you'd do `strtoupper("a")` – vartec Jul 24 '12 at 10:51
  • @Martijn Pieters: perhaps you can list some other anti-patterns you do not use in your Python code to make your answer complete? – Den Jul 24 '12 at 10:55
  • 1
    @vartec: the counter example is len() :-P – Martijn Pieters Jul 24 '12 at 11:04
  • @Den: I thought we were focusing on the Gang of Four book *Design Patterns* here. If we go anti-patterns, we go off the rails as there are plenty of those. – Martijn Pieters Jul 24 '12 at 11:06
  • @vartec: In any case, clarified the answer by using the term 'class' instead of 'object'. – Martijn Pieters Jul 24 '12 at 11:07
  • @MartijnPieters: We are focusing on the Gang of Four *Design Patterns* book. And saying, that some things that it suggests were later found to be not so good ideas after all (singletons being the best known one, but there are probably few more). – Jan Hudec Jul 24 '12 at 12:15
  • @MartijnPieters How is `len` not an object?: `>>> len` `` – Casey Kuball Jul 24 '12 at 14:41
  • @Darthfett: the point is that `len()` is not a method or attribute on an instance, it is a function. Compare `"abc".length` (won't work) with `len("abc")`. – Martijn Pieters Jul 24 '12 at 14:43
  • @MartijnPieters I misinterpreted your comment as a response to his first post, my mistake. To continue the conversation, IIRC the `len` function on a string actually looks up a constant already cached on the object. On other objects, it calls a special method (`__len__`). It's more of an interface thing. :) – Casey Kuball Jul 24 '12 at 14:53
  • 3
    @Darthfett: I am well aware of how `len` works; [Guido made an explicit choice here](http://effbot.org/pyfaq/why-does-python-use-methods-for-some-functionality-e-g-list-index-but-functions-for-other-e-g-len-list.htm). My point is to show that Python is not a pure OOP language; it is a pragmatic language. I like it that way. – Martijn Pieters Jul 24 '12 at 14:58
  • The Singleton though, is explicitly cited in the Python manual, (unless they scrapped it recently) so I believe it's more of **a syntax-sugared pattern** that one that doesn't apply. – ZJR Jul 25 '12 at 00:10
  • @ZJR: The word 'singleton' in the python manual mostly refers to [tuples of length 1](http://docs.python.org/reference/expressions.html?highlight=singleton#expression-lists); the [FAQ does touch upon singletons in the context of design patterns briefly](http://docs.python.org/faq/programming.html?highlight=singleton#how-do-i-share-global-variables-across-modules), only to point out that modules are the way to go. – Martijn Pieters Jul 25 '12 at 09:53
  • @MartijnPieters: `len` is an object that acts on other objects. How is that _not_ OOP? It's just a different syntax, that's all, and you can use the same in your own classes by implementing the __call__ method. – André Paramés Jul 25 '12 at 10:24
  • @AndréParamés: In comparison to, say, Smalltalk, Python is not a pure OOP language. `len` is a built-in function, not an instance of a class. – Martijn Pieters Jul 25 '12 at 10:30
  • @MartijnPieters: But `len` *is* an instance of the `builtin_function_or_method` class. It even has methods, e.g. `len.__repr__()` or `len.__call__()` (and the latter is the one that is actually run when you can `len(obj)`). That it is implemented by the core seems an irrelevant detail to me. – André Paramés Jul 25 '12 at 11:15
  • No, the singleton is not an anti-pattern, implementing it with statics is. Singletons are useful and necessary everywhere, just make sure that when you create one, it gets exposed only to classes that want to use it and not to your entire code base (the problem with static). – Cedric Beust Jul 29 '12 at 19:24
  • @MartijnPieters, it seems to me that `len(obj)` vs `obj.len()` is merely a question of syntax. I don't think adopting one or the other changes how OO a language is. All you've changed is word order, not the semantics of the language. – Winston Ewert Jul 30 '12 at 04:49
  • @AndréParamés: To support Martijn Pieters argument on *Python is not pure OO language... it is a pragmatic language*. The truth is that functions in Python are *implemented* as object. However, it does not make it pure OO language. Pure OO languages does not allow you to define a plain old function that is not bound to any class. In my opinion, the languages should not remove functions only to be pure OO. Functions make a language more natural in many cases. Anyway, any object language implementation ends with structures plus code. – pepr Oct 12 '12 at 14:07
  • @pepr: the unbound functions in Python are just syntactic sugar. What you're really doing is creating an object with that name and adding a __call__method to it, which contains the actual code. When you call the "function", you're really calling its __call__() method. Example: `def myunboundfunc(): print "hello" myunboundfunc.__call__() #outputs "hello"` You can even replace that method: `myunboundfunc.__call__ = lambda: "frog" ; myunboundfunc() #returns "frog"` It's much like Smalltalk, which had "unbound" code blocks too (they were really their own objects, just like here). – André Paramés Oct 12 '12 at 17:44
  • @AndréParamés: Think about a user that is given a programming language and no details are given about how the compiler/interpreter is implemented. Then `def fn(args): ... return xyz` cannot be perceived as an object method call. Actually, everything related to syntax can be called syntactic sugar. In my opinion, defining the *unbound functions* in the OO world only shows the need for normal functions during programming, and the lack of those in pure OO languages. It's like scratching behind the ear putting the hand over the head. – pepr Oct 12 '12 at 19:16
  • @pepr: It's your prerogative to use the definitions you prefer, but that's not the common definition of syntactic sugar; rather, it's any construct that "can be removed from the language without any effect on what the language can do". For example, I can re-implement functions in Python using classes. I can't re-implement objects in Python. I also cannot agree that a language should be judged by how a novice programmer (in the language) perceives the syntax. I do agree that there's a need for something like unbound functions, and that's why Python *emulates* them. – André Paramés Oct 12 '12 at 23:21
  • @AndréParamés: I did not use the term *novice programmer*. Try to `def fn(x): return x+1` and then try to `print fn` and then `print fn.__call__`. Try also `import dis; dis.dis(fn)` and then `dis.dis(fn.__call__)`. Functions were part of Python earlier than objects were. OO programming can be done in the C language; however, it does not make it an OO language. Similarly, functions can be simulated in pure OO language, but it does not mean it makes it a hybrid language. A function is a simpler tool than class/object. Notice the `obj.method()` vs. the `def method(self)`. – pepr Oct 13 '12 at 11:01
  • @pepr: I know those examples, but they're irrelevant the firsts are just the result of `__repr__` and the disassembler is an irrelevant implementation detail of CPython, which doesn't affect Python-the-language. *Functions were part of Python earlier than objects were.* When was that? The first publicly available version of Python used objects extensively. Besides, yes, the language has changed, so what? *OO programming can be done in the C language; however, it does not make it an OO language.* But functions in Python *are* implemented as objects. They're instances of the FunctionType class. – André Paramés Oct 13 '12 at 15:22
  • @AndréParamés: I should have been more specific. Objects were used for the implementation, but user defined classes were added later than functions during development (Google New York's Technical Speaker Series. Guido van Rossum giving his Python presentation at the New York Google office on Wednesday, February 22nd 2006. http://video.google.com/videoplay?docid=-7758421725489622662). My view is that the OO language is a language that supports *syntax* for easier writing OO programs. Pure OO language does not support plain functions. It does not depend on its implementation. – pepr Oct 13 '12 at 20:56
8

Design patterns are for the programmer, not for the language. Programmers tend to use patterns that help them make sense of the problem at hand. No design pattern is strictly necessary, but it may be of use to help simplify what you're trying to do.

Python, and duck typing specifically, does provide an end around a lot of common patterns and practices, and a lot of the restrictions imposted by some patterns (privacy, immutability, etc) only hold to the extent that the programmer agrees not to break them. But still, they do work as long as the programmer plays along. A door is still a door, even if it's framed by imaginary walls.

Python is considered a "multi-paradigm" language; you can use whatever patterns you want. This is intentional. It provides for complex class hierarchies, for example, even though they're completely unnecessary and a bit artificial. But for some people that particular abstraction is helpful. Not because the problem demands it, but because the programmer does. So there you go.

tylerl
  • 4,850
  • 21
  • 32
  • That's certainly interesting. So which patterns in particular do you mean that one might forget about, because there are better ways in Python? – Gere Jul 24 '12 at 08:49
4

The original "Design Patterns" book documented and named some common idioms useful in imperative, object-oriented languages such as C++ and Smalltalk. But Smalltalk is a dynamically typed language, so it can't be strictly a matter of being dynamic.

However, the answer to your question is still "yes": some of these design patterns will be irrelevant to modern dynamically typed languages. More generally, there will be different design patterns in different languages, especially in different kinds of languages.

To reiterate: a "design pattern" is simply a name for a programming idiom: a common solution to a frequently encountered problem. Different languages require different idioms, because what is a problem for one language may be trivial for another. In this sense, design patterns tend to point out weaknesses in the languages they apply to.

So, you might look for other features which make modern dynamic languages (or ancient ones like Lisp) more powerful, rendering some of these classic design patterns irrelevant.

comingstorm
  • 2,727
  • 1
  • 13
  • 14
1

Design patterns are ways of solving particular problems. If a problem is not met, pattern of resolving it has no use.

People are trying to adapt design patterns everywhere as if it was a best practice to have design patterns in your project. That's other way around. You encounter a problem that can be solved with a factory pattern? Cool. Adapt it. Don't look up your code and try to find the right place to implement a singleton (or factory, or facade, or whatever ...).

Perhaps Python has its own design patterns not available for Java and .NET people (due to nature of these languages)?

Andrzej Bobak
  • 1,276
  • 1
  • 13
  • 21
1

I would say that patterns are always language dependent. That most python patterns look like those defined in GoF it's because of the OOP of Python, that being said OOP is not like OOP (no two languages define objects and their manipulation 100% alike).

So there's no doubt some patterns will not be applicable "as is", some might make no sense and there are some patterns that might be only be meaningful to Python.

To get back exactly at your question: Patterns are only necessary if you need them. You don't have to use them if there's no need for them (as Jan Hudec already said).

Furthermore, there are much more patterns than those mentioned in GoF. See in wikipedia other patterns

estani
  • 291
  • 1
  • 2
  • 7