Beauty Is in the Eye of the Beholder
Alex Papadimoulis discusses ugly code, where it comes from, how to avoid it, and how to get rid of it.
The content has been bookmarked!
There was an error bookmarking this content! Please retry.
Posted by Arnon Rotem-Gal-Oz on Jul 30, 2007
1. Design patterns are a form of complexity. As with all complexity, I'd rather see developers focus on simpler solutions before going straight to a complex recipe of design patterns.
2. If you find yourself frequently writing a bunch of boilerplate design pattern code to deal with a "recurring design problem", that's not good engineering-- it's a sign that your language is fundamentally broken.
Design patterns are very useful when we study how they work so we can create similar patterns. They are bad when we try to copy them directly. If one reads the Gang of Four, he will realize that the authors often give several examples of each pattern and they're all slightly different. One might also notice that there is a lot of talk about the OO concepts that lead to the patterns.
There is a reason why it's important to establish a clear separation between Alexander's Design Patterns and the GOF's Design Patterns: software engineering is nowhere near as advanced as building engineering is. We are still working on these nuts and bolts, and whenever a new software project starts, we still can't be sure it won't collapse under its own weight after just a year. To make a parallel: imagine a world where every time a new construction takes place (say, a bridge), the future of that bridge depends on the team of engineers and workers you choose to build it...
Dominus says that design patterns are a sign of a deficiency of a language for the purpose that the design pattern addresses. In other words, the Visitor pattern used in Java points to the fact that Java is deficient in terms of list processing: the `map` and `filter` constructs need to be emulated with lengthy OO incantations.
He is _not_ saying that the use of design patterns _as such_ is bad. He is saying they are a sign of a deficiency.
SOA All-In-One Guide: KPIs & Best Practices, ESB Report
18 agile and lean practices for effective software development governance
A practical guide to choosing the right agile tools
Improve Java Garbage Collection, Runtime Execution, and JVM visibility with Zing
Agile Practices to Improve Project Management Organization (PMO) Effectiveness
I find the GoF design patterns book very useful, especially the first section that cautions against common pitfalls such as overuse of inheritance. I think it should be read by anyone who's serious about building software. But I've also seen people go to lengths to force a pattern on a problem that didn't need it, adding needless complexity. I would rather arrive at the simplest design through continuous design and refactoring, then use the vocabulary the GoF book introduces to describe the solutions when applicable.
--mj
I think people have been way too fixed on the details of this book, when the whole picture is what it is important. This book displays how a design is made based on a problem identified. And promotes the identification of patterns in YOUR application. I don't think the GoF was ever intended as a recipe book, but more as a guided tour of the solution to a problem.
This whole talk about 'the use of patterns says the language is broken' is pointless.
For example, Ruby's standard APIs use the Visitor pattern extensively. It's not just because it is built in the libraries that it's not there. If you are going to build a text editor in Ruby, you probably will use the Flyweight pattern. It's not built in the standard APIs (I don't know, it's just an example), so Ruby sucks?
Sure, new languages incorporate into their APIs patterns that proved to be useful in the past. But as any design choice, it's a trade-off. Adopting one way to do things will always exclude other ways, which could fit better in some specific context. And then you'll have to work around it, and you'll probably create some kind of design pattern to do it. Then, your language is broken? Or maybe you'll want to create a new language to solve every single problem that your current language/libraries are not optimized for?
Design patterns are common solutions to recurring problems, a very good way to document knowledge, and a nice way to develop a high-level vocabulary. You can use it well or not, but it all depends on you, not on some black magic created by the GoF guys.
Totally agree with you. A language can't answer all your questions out of the box. Design patterns are way of doing things (better ways of doing things). They defined common problems and propose solutions for them. There will be new problems in the future, different problems. What happens then? I think languages give you the tools you are free to follow whatever road you choose..
Sure, the GoF patterns and others are here to stay. They are a sign of a maturing industry: it´s old enough and conscious enough to realize that solutions are recurring and that some solutions work better than others. On the class level the GoF patterns are a compilation of such successful solutions. Great!
But that does not mean, these patterns need to be adhered to slavishly. And it does not mean, they are the new building blocks to use to put together new applications. If you detect a situation of a certain kind, you certainly should check the GoF patterns for a solutions. But don´t start your next project by asking "What patterns should we glue together?"
Components are building blocks on a much needed higher level of abstraction than classes. GoF patterns are not.
-Ralf
Home: www.ralfw.de
Blog: weblogs.asp.net/ralfw
I guess I'm not sure what his point is. Is he saying that we should all drop developing in Java or C++ because they require patterns that Ruby might not?
Quote:
If you find yourself frequently writing a bunch of boilerplate design pattern code to deal with a "recurring design problem", that's not good engineering-- it's a sign that your language is fundamentally broken.
He's right that some design patterns are required because of a deficiency of the language, but what's the alternative???
I think the book is still useful - mostly. However, there is one pattern that has probably caused more harm than good, and that's the Singleton pattern. It is, in my book, an antipattern, because it leads to very tightly coupled code that is hard to test, at least in statically typed languages like Java and C#. Dependency Injection is a great alternative to Singleton that elminates Singleton's coupling and test unfriendliness.
I don't blame the GoF for including it - Testing, TDD and mocking was not on the agenda when the book was written. But people reading the book today should be aware of what patterns are obsoleted by more modern patterns (or design principles).
He's right that some design patterns are required because of a deficiency of the language, but what's the alternative???
Low level design patterns (e.g. those in GoF) can mostly be codified or melted away at relatively higher abstraction levels (and will be replaced with higher level design patterns). There are some commonly used alternatives and/or techniques for this kind elevation (even without droping the low level programming languages) such as:
* Supporting domain specific languages (DSL) in core language.
* Using frameworks, middlewares, and/or tools
* generic programming
* ...
The alternative is more expressive languages. Eventually we will drop development of Java and C++ applications. Hopefully the replacement language will be more expressive, something that obivates most of the GoF patterns. The questions are what is this next language and how soon can we make the transition? Personally, I'm tired of the Java handcuffs.
The alternative is more expressive languages. Eventually we will drop development of Java and C++ applications. Hopefully the replacement language will be more expressive, something that obivates most of the GoF patterns. The questions are what is this next language and how soon can we make the transition? Personally, I'm tired of the Java handcuffs.
There are many such languages already, even before the GoF book and the Java language. In fact, the issue of expressiveness of language vs design patterns isn't a new topic, but has been well known among functional programming (FP) folks for years. Even the GoF book itself published more than a decade ago (not recently and before Java) also pointed out (page 4) that design patterns are relative to the choosen language. For instance, the factory pattern is largely vanished in Ruby and FP languages and the visitor pattern is less needed in CLOS (much older than Java), the iterator is internal in FP, the ....
There are many discussions much objective than the exaggerated opinions in the cited articles. For instance, Matthias Felleisen pointed out in his "On the Expressive Power of Programming Languges" article published in 1991 (many years before GoF and Java):
* By studying a number of examples, we have come to the conclusion that programs in less expressive languages exhibit repeated occurrences of programming patterns, and that this pattern-oriented style is detrimental to the programming process.
* Based on these examples and others with a similar flavor, we have come to believe that the major negative consequence of a lack of expressiveness is the abundance of programming patterns to make up for the missing, non-expressible constructs.
* Programs in more expressive programming languages that use the additional facilities in a sensible manner contain fewer programming patterns than equivalent programs in less expressive languages.
However, all of these by no means suggest that expressiveness should always be the sole pursuance of a programming language. Rather, it should be one of many trade-off factors to be considered by language designers. Blindly increasing the expressiveness of a generic language to eliminate design patterns not only could sacrifice application runtime efficiency but also could undermine the language's intuitiveness, simplicity, legacy compatibility, and more importantly its application code maintainability.
For example, Ruby's standard APIs use the Visitor pattern extensively. It's not just because it is built in the libraries that it's not there. If you are going to build a text editor in Ruby, you probably will use the Flyweight pattern. It's not built in the standard APIs (I don't know, it's just an example), so Ruby sucks?
Ruby does make the factory pattern largely vanished and therefore consider to be more expressive than C++. The visitor pattern, although not completely being eliminated, is indeed less needed in certain languages (such as CLOS -- as GoF pointed out in page 4) and/or under the help of a framework on top of a language (e.g. Java) that supports reflection and dynamic proxy.
I believe like a lot of methodologies & technologies they get used and abused when they aren't the best solution for the problem.
This is the case with the GoF book in my opinion, I have seen on more than one occasion the liberal use of patterns in projects that blatantly don't need it, i.e.
the use of factories that creates instances of only one known type, the implementation of a the observer pattern when it has already been implemented by the framework (.Net events).
To me this shows that the average developer has 'evolved' and learnt that they should be using patterns but not really understanding there power - they believe that implementing patterns (everywhere) makes the software intrinsically better.
I say these Morts have evolved :)
This doesn't mean to me the GoF is no longer as important it just means our understanding of patterns is more mature.
The alternative is more expressive languages. Eventually we will drop development of Java and C++ applications. Hopefully the replacement language will be more expressive, something that obivates most of the GoF patterns. The questions are what is this next language and how soon can we make the transition? Personally, I'm tired of the Java handcuffs.
There are many such languages already, even before the GoF book and the Java language. In fact, the issue of expressiveness of language vs design patterns isn't a new topic, but has been well known among functional programming (FP) folks for years. Even the GoF book itself published more than a decade ago (not recently and before Java) also pointed out (page 4) that design patterns are relative to the choosen language. For instance, the factory pattern is largely vanished in Ruby and FP languages and the visitor pattern is less needed in CLOS (much older than Java), the iterator is internal in FP, the ....
There are many discussions much objective than the exaggerated opinions in the cited articles. For instance, Matthias Felleisen pointed out in his "On the Expressive Power of Programming Languges" article published in 1991 (many years before GoF and Java):
* By studying a number of examples, we have come to the conclusion that programs in less expressive languages exhibit repeated occurrences of programming patterns, and that this pattern-oriented style is detrimental to the programming process.
* Based on these examples and others with a similar flavor, we have come to believe that the major negative consequence of a lack of expressiveness is the abundance of programming patterns to make up for the missing, non-expressible constructs.
* Programs in more expressive programming languages that use the additional facilities in a sensible manner contain fewer programming patterns than equivalent programs in less expressive languages.
However, all of these by no means suggest that expressiveness should always be the sole pursuance of a programming language. Rather, it should be one of many trade-off factors to be considered by language designers. Blindly increasing the expressiveness of a generic language to eliminate design patterns not only could sacrifice application runtime efficiency but also could undermine the language's intuitiveness, simplicity, legacy compatibility, and more importantly its application code maintainability.
Couldn't have said it better.
for those who DO NOT GET objects. If you're starting to learn OOP than GoF is one book you should read. Complemented by a much more practical one which is Domain Driven Design (Evans), one for algorithms (Dasgupta will be more than fine) and now, with all this Amdahl stuff, one for concurrent programming (if going with java them see the book by Goetz et all) and you can start programming w/o doing too much harm to the industry :-).
However GoF has the biggest impact after you spend several years writing broken OO code :-D
Alex Papadimoulis discusses ugly code, where it comes from, how to avoid it, and how to get rid of it.
John Davies examines Visa’s architecture and shows how enterprises have architected complex integrations incorporating Hadoop, memcached, Ruby on Rails, and others to deliver innovative solutions.
Sean Comerford unveils ESPN.com’s architecture, what components are used and why, and the current changes the website goes through.
Are there repeated patterns of failure on Enterprise Agile Enablement efforts? Sanjiv and Arlen discuss Seven Deadly Sins to avoid when adopting Agile in an enterprise.
Erik Dörnenburg answers: What is Enterprise and Evolutionary Architecture?, discussing 4 issues: Turning strategy into execution, Ensuring conformance, Where do the architects sit? Buying or building?
Sean Cribbs explains what Map-Reduce and Riak are, why and how to use Map-Reduce with Riak, and how to convert SQL queries into their Map-Reduce equivalents.
Chris Richardson shows how he ported a relational database to three NoSQL data stores: Redis, Cassandra and MongoDB.
Jean Tabaka challenges the audience to reflect on what Agile practices they are employing, how they are using them, ending with the questions “Why have their organization chosen to go Agile?
14 comments
Watch Thread Reply