Design patterns: an introduction

Posted on July 30, 2011

0


It has taken me a while to wrap my head around design patterns.

I read four books recently, including “Design patterns” by the Gang of Four (referred to as “Design Patterns”, “Design Patterns for Dummies” by Steve Holzner, “C# Design Patterns” by Judith Bisshop and “ActionScript 3.0 Design Patterns” by William Sanders and Chandima Camarantunge.

“Design Patterns” by the Gang of Four is the must have book for reference. If you are in doubt, or confused, go back to that one. “Design Patterns for Dummies” is the must have book to start with. I read them parallel and switched from one to the other to check accuracy on “..dummies” and decipher the meanings of cryptic writings in “Design Patterns”.

I am not an Design Pattern expert

I am a coder, a programmer and a software designer. I have written several frameworks for my own use, allowing me to re-use specific tricks and solutions I implemented before, while avoiding Copy & Paste.

One of the main flaws in most of my frameworks was the lack of clean coding and a proper understanding of standards. Either due to lack of experience or due to lack of time.

Refactoring, Clean Code and Distribution of Responsibility

From over 15 years of programming experience my main tools to get to stable and solid code (as you will find in this post) are (and have become) Refactoring, Clean Code and Distribution of Responsibility.

Why this series on Design Patterns?

As I am working on two new Open Sourced frameworks, which are both completely rewritten revisions of older versions, Design Patterns and a proper understanding of Design Patterns have become increasingly important to me, to avoid stupid solutions and to allow others to get a better grip and a better point of entry on what I have done.

In a series of articles in FlashWorks I will explore the main Design Patterns as described in “Design Patterns” from a practical point of view: “I want this, what pattern is most suited?”

These articles are part of my own learning process to start mastering the Design Patterns which are there and which are most useful for my own use. Either to avoid or use them properly where they fit.

Why I warn so much “against” Design Patterns

As I have encountered several people in the past who claimed that Design Patterns were the start and beginning of all bliss in awesome coding, I give you a lot of warnings in this post, related to that point of view, as I have seen the bad side (and sometimes very bad coding) of that single minded attitude in projects I cleaned up: after the original team had abandoned it for whatever reasons (including lay-offs due to company restructurings).

Why Design Patterns are hard to begin with

I personally found three main reasons:

  1. First encounter of patterns? Cryptic writings – Design patterns are (refactored) abstractions of recurring themes. The goal is to open that description as much as possible, so that the use is not limited to one single case. If we would apply that to a glass of water, the glass could become: “a container for fluids, made of several possible materials” – as we do not want to limit to a glass alone – “shaped to be held in a human hand” – as it is for human use – “for which one of the uses” – as we can use a glass also for other purposes – “is to move fluids from the container to the mouth”
  2. Contradictions,  white noise and limited views – Any writing on design patterns should be concise, clear and as open minded as possible. There are many ways to implement a design pattern, without breaking it. It is possible the writer of a book on design patterns focuses only on a few of those, lacks deeper experience, was battling the deadline or is a very linear thinker (all leading to limited views).  And there are many ways to misunderstand a design pattern (leading to contradictions). Anything that makes stuff even more complicated and that creates more work to decipher the real intents of the examples (white noise) is not helping but driving you further away from your goal.
  3. Hard to map with reality – When you are coding, you write code. You are solving several problems using methods, objects and specific tricks you know from your past. While your code is going somewhere, it is probably not following the rules of any design pattern. When you read design patterns it is hard to twist your minde around and find out which one applies and which one should apply.

Refactoring, code organization and design patterns

When you read “Design Patterns”, one of the things mentioned in the introduction is that: design patterns are an emerging result of your coding. This is very important to understand.

Design Patterns are – and should – never be a starting point.

Why design patterns should never be a starting point

  1. The type of your solutions change during a project – Where you start with Assumption “A”, this might change to Assumption “B” as your understanding grows and end up in Assumption “C” when you release the application. Where “A” is best to be done in a State pattern, “B” is best done with a Proxy and a Simple Factory, while the final solution, “C”, has discarded both State and Simple Factory (because both ended up being “anti patterns”: making things only more complicated) and relies complete on a Mediator with a mix of Factories and using Composition (as in using Composition instead of Inheritance) and a simple State Machine (which is not a State Pattern).
  2. Choosing the wrong Patterns can be your downfall – Brief: do not try to ram a round peg through a square hole. Each pattern is for a very specific approach to a very specific problem. Choosing the wrong pattern leads to code-overhead as you try to solve a problem with a tool that is made for something else.
  3. Code should be as short and simple as possible – More important than boasting about your use of design patterns is how clear your code is. The more lines you need to solve a problem, the more red flags should be raised in your mind that you might be heading in the wrong direction.

Why organizing your code and refactoring are your real friends

If the type of your solutions change during your project and Design Patterns can work against you, what can you rely on?

I found two important friends in coding:

  1. Organizing your code in a “Meta Pattern” – Which is –  in my case – based on the principle of Distribution of Responsibility and the promotion and demotion of code. In this meta-pattern I have (for instance): Managers, Handlers and Parsers, which are organized purely on what they do and what I want them to do. For instance: Handlers handle stuff, but do not make decisions. Parsers are very specific Handlers with a very specific role: to parse data from one format or structure to another. Managers are like Handlers, but smart. Managers run the show and make all the decisions. When refactoring I constantly move code from one place to another, until I feel that each Class is doing exactly what it is intended to do.
    The Meta-pattern is agnostic to any design pattern and completely open to any choice and any change in the choice of a design pattern. Its main goal is to help me clean up my code in constant runs: by using clearly defined places to put my stuff and find that stuff back.
  2. Refactoring – Refactoring is another word for: “cleaning up- and restructuring your code project and making stuff more simple to understand and better to read”. There are several books on/related to Refactoring and two books I recommend are: “Refactoring: improving the design of existing code” by Martin Fowler and co. and “Clean Code” by Robert C. Martin and co. Bottom line: Do not be afraid to regularly (completely) revise your code base. Especially when your coding tools assist you in that. Most current tools (like Visual Studio and those based on and plugged into Eclipse) do. They show you what you break and where you broke it and help you rename and fix stuff in a matter of minutes by feedback and proper mapping of your code.
Bottom line:
  1. Code should be clear – Clear namings, clear responsibilities, clear what is going on, clear what is needed, clear what comes out, clear what it does not.
  2. Code should be clean – No dead code, no repetition, no fuzzy or distracting naming conventions like: “m_SomeVariable” and: “aSomething” which you find in Java for instance, no getters and setters where you do not need them. No useless comments: “because you boss told you that you have to comment stuff”
  3. Code should be organized – Clear placement, clear purpose, clear (class) structure. Simple to find back, consistent conventions.
  4. Refactoring is your best friend – When refactoring, your are constantly moving stuff around and cleaning stuff up to achieve a Clear, Clean and Organized code base. By doing this you (can) achieve several very useful “byproducts”:
    1. Re-useable code – As code is cleaned up, restructured and extracted (read the books) it becomes more and more re-useable
    2. Reduction of vulnerabilities – As you refactor, clarify and clean up your code, your code becomes more and more “unbreakable” as you go. Where most “dirty code” has five or more places where one specific thing can go wrong (due to repetition of code and messy procedures) refactored code has one or two, which are usually very simple to fix.
    3. Easier to restructure – Messy and un-refactored code has a lot of entanglements of dependencies. When you change “A”, “B” and “C” will probably break. In most cases, that is why change is something you rather do not. In your refactoring process, breaking your code – with the purpose to reduce those dependencies- is part of your (daily) routine. You will find that the cleaner your code becomes, the more agile you will become. Re-routing a process from “A” to “B” will not increase the mess and the headaches, but lead to even better and cleaner code.
  5. Design Patterns are an emerging result, not a purpose – As you refactor and clean up your code, more and Code Patterns will start to emerge: repeating patterns in several places in your code. In some cases, these will look very much like the 23 as mentioned in “Design Patterns”. In most cases they will not. Fear not: when Code Patterns emerge –
    1. Smile! You are on the Right Path – The design patterns in “Design Patterns” are only 23 out of several hundreds. And none are a holy truth or “The Only Way”.
    2. You should refactor more – To clean those emerging Code Patterns until they tell their story of structure and approach loud and clear each time you encounter them in your code.

Why should you study Design Patterns?

I believe studying Design Patterns – WITH CLEAN CODE THROUGH REFACTORING AS YOUR MAIN FOCUS – help you become a better coder.

  1. Existing solutions for recurring issues – The existing Design Patterns show you which recurring issues have been identified in code project and how they have been addressed. Once you start understanding the issue they try to solve and how they solve that issue, they become your friends. Either to avoid them like hell, or to implement them in an early stage as they offer the best structure you can find.
  2. Avoiding stupid mistakes – If you use Design Patterns without understanding them properly, you will create a mess and achieve the inverse of what you should strive fore: clean code.

If you don’t get it, don’t use it (yet)

In general, if you don’t get it, don’t use it (yet). It will work against you. With design patterns this is even more the case.

How to get to that understanding fast?

  1. Read – Read all references you can find
  2. Understand – Make drawings, reflect the stuff you read on the work you do
  3. Refactor – Refactoring your code (cleaning up) is the best way. Force yourself to think and work in certain ways. It is how design patterns are discovered.

What Design Patterns do not deliver

In contrary to popular belief, Design Patterns (as the primary focus and driver) do not deliver:
  1. Better code (NOT) – As it is easy to misunderstand Design Patterns, it is easy to apply them at the wrong place. The result of this is in most cases messy code.
  2. Better project structures (NOT) – Design Patterns are close-up (micro) solutions. They show you a very specific solution for a very specific problem. None of the books I know on Design Patterns show you how to build and organize an entire project with 30 to 500 separate classes.
  3. A project that can be understood by others (NOT) – When design patterns are implemented by messy coders, the result is messy code and a messy project.

Here is why:

  1. Lack of understanding – Most coders do not understand Design Patterns.
  2. Limited understanding – Most coders who do understand Design Patterns only have a limited understanding of design patterns, based on a previous (set of) project(s).
  3. Wrong understanding – As most coders learn by doing, the first implementations and understanding of Design Patterns “because we have to” will be wrong.

When you do Design Patterns, but do not clean up

In the past five years I have been fixing other peoples code in projects that went wrong. These were the things I found:

  1. Messy code – Like: a real complete mess. Duplications of code, vulnerabilities leading to cascades of failures as time progressed and things changed, working night shifts to meet deadlines, rewriting entire blocks of code out of endless failures to make the existing mess work properly and loss of valuable time.
  2. Wrong interpretation of design patterns – Leading to even more mess than working entirely without any design patterns.
  3. Wrong design patterns in the wrong place – You can force round pegs into square holes, but something will get damaged. In code, wrong design patterns in the wrong place leads to code overhead and obfuscation of purpose. Where you might have been able to solve the issue with 5 lines of code, the compulsive use of “a design pattern” or – even worse – “Design pattern X, Y and Z” can lead to 3 or more classes and 20 to 150 added lines of code.

Why I keep hammering on Refactoring and Clean Code

In the past 14 months I have been working on a big Flex project for a big scientific publisher, involving a team of 15 to 20 people. The base architecture and the base classes driving that application and used by others as stepping stones were designed and written by me. The demands on both back and front end led to a design where a lot of rules were “broken” to avoid overload on the Servers as each request from Client to Server involved queries on over 200 million records, with over 30 possible combinations per record (leading to over 6 billion possible combinations to be queried per request).

  1. Clean code and Clear Structure is more important than anything else – If your code is messy, nobody understands what is going on. If your most important actions are performed in some obscure classes hidden in obscure packages in your structure and mixed with other activities for other parts, nobody will be able to find them or what is going on where. If nobody understands what is going on, the mess will only become bigger
  2. Cleaning up code on regular basis is more important than anything else – Regardless of what your design process is and how awesome your architecture looks on paper, there will always be coders in your team who have limited experience and limited understanding of what you are trying to achieve. Leading to additional mess in your code, by doing stuff in places they should not work.
  3. Design Patterns emerge – I can not keep repeating this enough. Especially because I have met people who hammer on the use of Design Patterns as a starting point in the design (because they read the book, believe in the holiness of it, or are used to work in that specific way). Design Patterns emerge. Period.
  4. Change occurs, so which Design Patterns is best to solve a problem changes too – As the solution itself might change as time progresses. Where State Pattern might be good at first sight, Mediator might be the only way forward to keep it simple and sane. Or vice versa.

What is next?

In the next blogs I will look at several design patterns, using a specific approach to try and make sense out of them:
  1. Scope – What do each cover? What not?
  2. Use – When to use them? What for?
  3. Clarification – What makes that pattern that pattern? When does it stop to be that pattern?
  4. Differences and similarities – What patterns solve similar issues, what makes them different and what are the benefits of each chosen solution?
  5. Smarter approach – Some patterns can be coded in a different way than most if not all code examples show, adding more flexibility and reducing code and dependencies
I assume you read and refer to two books at least: “Design Patterns” and “Design Patterns for Dummies” to fill in the gaps I leave open and keep your independence, as others already wrote about it and I might make mistakes in my understanding at this time.
Advertisements
Posted in: Design patterns