In this series of articles I talk about all the new and fancy stuff I learned about during my Student Job at Commsquare

This article tackles a quite important topic in software design: Design Patterns.

 

I will briefly go through some of the patterns that I used and make some notes on the dangers in using patterns.

You might want to read part 0: Introduction before reading this article.

What I already knew about it

Design Patterns were perceived by me as follows: “Some guy thought about how to solve a very specific problem and tried to generalize it and gave his solution a fancy name.”
I knew that it might be useful to know different design patterns (by name) so that, when someone mentions that he used it, you know what the hell he is talking about.

Patterns I had already heard of: Singleton, Factory method, Observer, Publisher-Subscriber.

My goal is just to describe what I learned about patterns in general. Not about going into detail of every pattern. Although, some patterns will be tackled in more detail than others.

A bit more about Patterns in general

The idea of patterns in engineering is not unique to software development.

A design pattern in architecture and computer science is a formal way of documenting a solution to a design problem in a particular field of expertise. The idea was introduced by the architect Christopher Alexander in the field of architecture[1] and has been adapted for various other disciplines, including computer science.[2] An organized collection of design patterns that relate to a particular field is called a pattern language.

From Wikipedia

So Mr. Christopher came up with the terms patterns in 1977. Since then of course the topic has been studied very deeply. And in 1994 a book called ‘Design Patterns’ was published by The “Gang of Four” which is still a standard work today.
In short: A general solution to a very specific problem

Why I came in contact with it

While designing the application I figured that it would to be interesting to look into the topic more deeply.  Also I noticed that in the DAP architecture some design patterns were used. More specific: Command, Factory Method

Design Patterns I eventually used

Builder Pattern
The main purpose is to construct complex objects. But what I also noticed is that it makes your code very readable.

Readability

new Message(“uncle_ben@agalaxyfarfaraway.uni”,”May the force be with you”,”always”);

Here you don’t really know what is what and you will have to lookup what is on what position.

new MessageBuilder()
.to(“uncle_ben@agalaxyfarfaraway.uni”)
.subject(“May the force be with you”)
.content(“always”)
.build();

Complexity


new ComplexObject(42,69,”fsdfdfd”,666,0.0,true,.....)

Here you can already forget readability and it is just crazy to make constructors with lets say 15 arguments. You can get rid of the duty of having to create different constructors and encapsulate the creation of objects even more.

For extra information I’d like to refer to this Wikipedia article

Observer Pattern
A way to notify objects that are interested in the occurrence of some event. It separates the responsibility of  notifying (Check for new events)  and acting (reacting to events).

Observer is already in the standard Java libraries.

More info

Command Pattern
A way of encapsulating some actions. For example a specific call of a method.

For example

public interface Command{
    public void execute();
}

public class ForceJumpCommand implements Command{
    public ForceJumpCommand(ForceCarrier fc){
        this.fc = fc;
    }

    public void execute(){
        fc.forcejump();
    }
}

public class MoveCommand implements Command{
    public MoveCommand(ForceCarrier fc){
        this.fc = fc;
    }
    public void execute(){
        fc.moveForward();
    }
}

At first you might not understand why this might be advantageous. I’ll give you two reasons

Reason 1: You can pass the command around, postponing execution. The executor doesn’t have to bother about what will happen or how to execute it. This is what is called ‘encapsulation’ . It just needs to invoke ‘execute()’.

Reason 2: Because you can pass them around, you can put them into a queue.
For example when during a game:

You quickly press move, jump, jump. Then the game could execute those command one by one.

For a very good explanation you should definitly take a look at this video of PatternCraft

Visitor Pattern
I came into contact with the visitor pattern when trying to find a better way of doing this:

if(cmd instanceof MoveCommand){
 ..
 }else if(cmd instanceof JumpCommand){
 ..}

The answer that I got was given here, more specific – you guessed it – the visitor pattern.

Making it look something like this:

//interfaces
public interface Command{
    public void execute();
    public void accept(CommandVisitor v);
}

public interface CommandVisitor{
    public void visit(MoveCommand cmd);
    public void visit(JumpCommand cmd);
}

//concrete implementations
public class Printer implements CommandVisitor{
    public void visit(MoveCommand cmd){

    System.out.println(“Move Command”);

    }
    public void visit(JumpCommand cmd){

        System.out.println(“Jump Command”);
    }
}

public class MoveCommand implements Command{
    public void execute(){
    ….
    }

    public void accept(CommandVisitor v){

        v.visit(this); // this is equivalent with v.visit((MoveCommand) this)     because of dynamic type in java

    }
}
//Usage:

new MoveCommand().accept(new CommandVisitor());
//output: “Move Command”

This works better than using instanceof. It can choose the right method in constant time (more or less) compared to the linear time with if..else..

Problems with this design:
If you add a new command. You must also edit the visitor.  So there is still a lot of changes  to do there.  Also you are in a heap of trouble when you cannot edit the visitor source.

I’m still searching for a better design, so feel free to post a comment below. Important note: it doesn’t have to be Object-Oriented (just to make sure that you don’t think that I believe that whenever something is OO, it is always better than non-OO)

Someone suggested something with immutable hashmaps. I can see how that might work, but I’m unable to think of a good example.

The danger of using design patterns

One thing I learned is that there is a very important danger in studying patterns. That is, that it might actually make things worse.

Consider the following situation:

During a nice day you suddenly decide that you want to learn everything about design patterns. So you buy all the books you can find and you struggle your way through all of them.

After you finished your last book, you consider yourself an expert in design patterns and you believe that you are now also an expert in practical software design.  So in your next problem, after studying the it, you start thinking about what patterns you might use.

This is where you lost focus on solving the problem.

Solving the problem, that is , coming up with any working solution, is the most important part (half) of software design . The next part is optimizing, refactoring and other fancy stuff. (In my next article I will go deeper into that)
It is at this point (after solving the problem) you should start trying to give names to parts of your design. Like recognizing structures that have a lot of similarities with a certain pattern, and then investigate whether you should apply the pattern to the design. It is surprising (is it?) that many of the things you come up with, have already a fancy name. But actually it is not that surprising, because it has been given a name because the ‘pattern’ emerges in a lot of designs.

I can summarize that whole paragraph in one sentence:

Don’t apply your design to design patterns, instead apply design patterns to your design where appropriate.

It is for example just a waste of time that during the first steps of the design process you would argue about whether to use a Builder pattern , Factory or other patterns.
You should just be satisfied with the fact that ‘some objects are going to be created’. Choosing how, is something for later.

Conclusion

I’m very glad that I took some decent steps into the world of Design Patterns. But I’m also very glad that I’m aware of the dangers in using them. I’m sure I’ll be using some of patterns described in this article in the near future. It was really nice, when explaining my design to the other software engineers that I could just say: “I use Builder” here.
So to conclude the conclusion: Yeah, I think some patterns are pretty neat, but beware!

Next part: Agile Programming & Test Driven Development  (in production)

Advertisements