“One comment I saw in a news group just after patterns started to become more popular was someone claiming that in a particular program they tried to use all 23 GoF patterns. They said they had failed, because they were only able to use 20. They hoped the client would call them again to come back again so maybe they could squeeze in the other 3.
Trying to use all the patterns is a bad thing, because you will end up with synthetic designs—speculative designs that have flexibility that no one needs. These days software is too complex. We can’t afford to speculate what else it should do. We need to really focus on what it needs.” – Erich Gamma [1]
When people starts learning design patterns, they try to use patterns everywhere. They try to use patterns anyway, it does not matter whether a pattern is required or not. They think that the more patterns are used, the better is the design. The outcome is a code with unnecessary complexity. [2]
Rather that calling “using patterns”, we can call this “abusing patterns”. It is an abuse when people try to fit patterns in Hello World
program.
Let’s focus on an example. The problem is the classic one: Write a program that will print Hello World on standard output.
A beginner in programming will write a code like this (well, it’s in Java):
System.out.println("hello world");
This code seems too simple. Can we use some patterns in it? Let’s see …
First we define two interfaces Subject
and Observer
to add Observer.
public interface Subject { public void attach(Observer observer); public void detach(Observer observer); public void notifyObservers(); } public interface Observer { public void update(Subject subject); }
Then we define two classes HelloWorldSubject
and HelloWorldObserver
that implements them.
public class HelloWorldSubject implements Subject { private ArrayList<Observer> observers; private String str; public HelloWorldSubject() { super(); observers = new ArrayList<Observer>(); } public void attach(Observer observer) { observers.add(observer); } public void detach(Observer observer) { observers.remove(observer); } public void notifyObservers() { Iterator<Observer> iter = observers.iterator(); while (iter.hasNext()) { Observer observer = iter.next(); observer.update(this); } } public String getStr() { return str; } public void setStr(String str) { this.str = str; notifyObservers(); } } public class HelloWorldObserver implements Observer { public void update(Subject subject) { HelloWorldSubject sub = (HelloWorldSubject)subject; System.out.println(sub.getStr()); } }
Then we add a Command.
public interface Command { void execute(); } public class HelloWorldCommand implements Command { private HelloWorldSubject subject; public HelloWorldCommand(Subject subject) { super(); this.subject = (HelloWorldSubject)subject; } public void execute() { subject.setStr("hello world"); } }
Then we add an Abstract Factory.
public interface AbstractFactory { public Subject createSubject(); public Observer createObserver(); public Command createCommand(Subject subject); } public class HelloWorldFactory implements AbstractFactory { public Subject createSubject() { return new HelloWorldSubject(); } public Observer createObserver() { return new HelloWorldObserver(); } public Command createCommand(Subject subject) { return new HelloWorldCommand(subject); } }
And finally a Singleton.
public class FactoryMakerSingleton { private static FactoryMakerSingleton instance = null; private AbstractFactory factory; private FactoryMakerSingleton() { factory = new HelloWorldFactory(); } public static synchronized FactoryMakerSingleton getInstance() { if (instance == null) { instance = new FactoryMakerSingleton(); } return instance; } public AbstractFactory getFactory() { return factory; } }
And the main class at last.
public class AbuseDesignPatterns { public static void main(String[] args) { AbstractFactory factory = FactoryMakerSingleton.getInstance().getFactory(); Subject subject = factory.createSubject(); subject.attach(factory.createObserver()); Command command = factory.createCommand(subject); command.execute(); } }
And the output is: Hello World
Wow, we have managed to use four patterns in Hello World
program. (Well, there is an Iterator too, but we have used built-in Java iterator which is natural in Java). This must be a great design. So where is the problem?
- The code is too complex for a hello world program.
- It contains the flexibility that we will never need.
- The time spent in designing and implementing is a total waste.
- There is a class explosion.
- It violates the KISS principle. [3]
- This does not serve the purpose of the problem. The purpose was to learn how to print on standard output and this code is far far away from that.
Summary: Use patterns where they are natural, do not try to use them anyway. Design Patterns is a great tool to build great software. Use them wisely, do not abuse them.
The code can be downloaded from here. Any feedback is welcome. And if anyone can manage to use more patterns in hello world then that will be great.
References:
[1] How to Use Design Patterns.
[2] Chapter 13: Patterns in the Real World from Head First Design Patterns.
[3] KISS Principle.
Seems you are getting hard time to KISS 😉
Anyway.. brilliant post.. though a bit tough but read till end!
খাইছে!
Great article. I was googling abuse of design patterns and found this article. I inherited some tangled code to maintain (co-worker quit), and everyone I work with deals with an older, non-object-oriented system. It was hard to explain to them why my job is much more difficult. I think I will just forward them this link. Thanks!
Reblogged this on DNB.
Pingback: 겸손한 개발자 | eastdg
Pingback: KISS (Keep it simple, stupid) y Patrones de Diseño | Pensando bajo la lluvia
задрот!
wow i start with this one but 3 days i never get complied 😦
just want to remember this post, i will start with the basic java. i hope can understand and get what the writer want to share
Clarification: This post is not about Java, it’s about Design Patterns which is not specific to Java. Java is used here simply as an implementation language.
por algo empiezo a lo basico en java y entender y analizar y seguir la sitanxis de cada linea del codigo.
Bad design here:
private ArrayList observers;
class should be used, List or Collection are good candidates.
🙂
http://calumgrant.net/patterns/
Hello World of design patterns… Might be interesting to people stumbling here…
Hi there,
I see you are hosted on wordpress.com .. how come you were able to customise the Twenty Ten theme to add, for example, the next and previous links to your posts … ?
Could you please help me here …
Thanks
That was a long time ago. But as far as I can remember, I did nothing special. Just the default theme and customization options that wordpress provides itself.
Hi there very cool blog!! Guy .. Beautiful .. Superb .. I will bookmark your web site and take the feeds also¡KI’m happy to search out a lot of helpful information right here in the submit, we need develop more strategies on this regard, thanks for sharing. . . . . .
cheap cialis pill
Pingback: [译] 如何”优雅”的用设计模式来写一个Hello World. – Snow Star
How do you know this works without unit tests and integration tests? You should mock System.out for the integration test.
Also, you were extremely lucky that you didn’t need an Adapter somewhere to make, say, the HelloWorldCommand implement a ‘run” method instead of an execute method.
I found this post when was seeking info about the Observer pattern…
Dude, you’re cool developer, really cool!
Pingback: “Less Code” Print Design – FANARO
Pingback: The Abuse of Design Patterns in writing a Hello World Program > Seekalgo