Almost every software developer will be challenged with designing a software system at some point during their professional career. After designing many of them it becomes obvious that despite different problem domains, many of these systems have something in common – it is easy to observe that they have similar structure and objectives and thus can be designed in a similar way.
Suppose you find yourself in a position of leading the implementation of a large project. How would you deal with designing it? Given that there have been countless systems implemented in the past, it is almost certain that somebody has already solved this problem for you (at least partially).
The first time I heard about design patterns was at workshops organized by Google. During my year in industry in a financial company, I was encouraged by senior developers to practice design patterns while designing a small-scale system. So, I bought myself the “Design Patterns Essentials” book and with both huge excitement and “now I am going to be professional” attitude, tried to fit the patterns into every possible design problem encountered. To my disappointment, after some time, I realized that some of the functionalities were so abstracted that no longer easy to understand, contradicting the widely known “make it simple” principle and leaving me baffled with a “I must have done something wrong in here…” thought.
In this post I would like to use the opportunity to share my experience with design patterns and discuss the way a junior developer can learn how to use them appropriately.
What are Design Patterns?
Design Patterns are generic, reusable solutions to the frequently occurring software design problems. They are usually categorized into various groups such as creational, structural or behavioural patterns, making it easier to choose the appropriate one for a particular problem. The most simple example is a singleton pattern that ensures the creation of only a single object of a class, providing a single point of access to it.
Suppose you have to implement a message based, sequential communication system between two nodes. In order to be able to follow the order of messages, each of them need to generate a unique sequence number by adding 1 to the previous one. Assuming that there is a sequence generator class, it is essential to make sure that there is only one object of that class, otherwise there is a risk of having multiple numbering sequences. So, in order to prevent this behaviour the constructor of the sequence generator class can be made private and the instantiation of the single object can be done within a static method of that class, managing the creation and access point to that object.
When to use design patterns?
I think apart from knowing when a particular design pattern can be used, it is crucial to be able to tell whether it should be used at all. It is very hard for junior developers to resist the temptation of using the patterns in every possible situation, ending up with a bunch of complex pattern classes instead of simple, straightforward code. This in fact, is not only a messy code, but the chaos at the structural level – much harder to correct. Even design pattern books, despite their aim to encourage people to use patterns, state, that developers should strive to keep the code simple and not to try to find a pattern to solve a design problem, when a clear and simpler solution can be used. The “You aren’t going to need it” principle of Extreme Programming can be applied to design patterns in the sense, that an additional feature should not be added just for the sake of applying a design pattern. Design Patterns are just another indispensable tool that can be used, but its the developer’s responsibility to use it appropriately.
The perfect example of when the use of pattern might be beneficial is refactoring. It provides an opportunity to analyse the existing code and provide the pattern that improves the structure of the code.
How to learn when to use (appropriate) design patterns?
Most junior developers will most possibly go for “code, code, code, make a mess, break something, feel the pain, fix it” approach. Learning on your own mistakes is great, however not very applicable for large-scale, long-term projects, as the misuse of patterns might cause many problems not only for the developer who used the pattern inappropriately, but for other team members as well. While working on the large-scale project it is best to ask a more senior developer for an advice, before applying the pattern.
In this post I presented my experience with design patterns and described the general problems that might arise while starting to work with them. I think it is very important for junior developers (like myself) to remember that being a professional developer does not mean using fancy tools whenever possible, rather choosing the best tool for the problem, which is called ‘simplicity’ in most cases.
Tony Bevis, “Java Design Pattern Essentials”, Abilityfirst, 2010
Elisabeth Robson, Bert Bates, Kathy Sierra, “Head First Design Patterns”,O’Reilly Media, 2004