Talking about Design Patterns
Today I want to talk about Design Patterns. I know, there is a lot of texts about this topic around there, but unfortunately, is a topic ignored by colleges and isn’t a thing that we are used to see in development courses.
It is unknown for most developers or at least we don’t use it daily, and if i’m being honest, 291 days ago, so didn’t I.
I will give you a simple story, where we can easily see how design patterns are useful.
Let suppose we have a client, and he ask us to do a code to calculate a parking bill. For starting it simple, let suppose we just have to calculate the hourly price, 5 dollars.
You would say that is quite simple, right? Maybe we would came up with something like this:
Okay, this would work. But let suppose now our client ask us for a new feature. Trying to increase their audience, the parking lot wants to calculate the bill in a dynamic way, they want to differentiate the prices based on how many hours the car has been parked. We should now calculate the value: hourly for the first twelve hours then a daily price for the first fifteen days and finally a monthly price.
Continuing our old version we can easily came up with this:
Before any comments, let suppose our client wants now support for other vehicles types, trucks. The bill price now shouldn’t be based in the time the truck stayed, it will always be a daily price, but dynamically based on the trucks size.
I can bet now that you will spend some time thinking, and if you don't know anything about design patterns you will came up with something like this:
It is starting to get weird isn't ? But it works. The client liked and we have our daily coffee paid, everyone is happy :)
A couple months later, our client calls us, wanting for a new feature, he wants to open this system for other parking lots, in different cities, with different taxes, rules and prices.
How would you react when you open this old code and start to think about this new feature?
The code is huge!
We started our code in the simplest way, and this is perfect! But, as the time passed we coded without thinking in how this would scale in future.
The code has a couple bad smells and this blocks it from being easily scaled. What might happen when we have new kind of vehicle? Like bikes? This would lead us to an even more giant code. If the bike calculation for a day is the same, for example, we would also start to create duplicate code, which will result in maintenance issues and every one of those problems that all developers had someday.
Besides that, the code is inflicting the “open-closed principle” and the “single responsibility principle”.
Why exactly does ParkingBill class have to know how to calculate a bill for every kind of vehicle?
Design Patterns :)
I like to think that design patterns are mostly like "cake recipes". They are solutions for problems. Solutions for problems with a mutual architecture, solutions that were already used and tested before in different scenarios.
In other words:
They are the patternization of the solution for a problem X, that you must use whenever it is possible.
There is a lot of different patterns and they can be splitted in three different kinds based on what problem they solve: creational patterns, for the patterns that help us in instantiation of classes and objects, structural patterns helping us to realize relationships between entities in a simpler way and behaviour patterns helping us with the communication between objects.
I will assume from here that you already know a little bit about S.O.L.I.D principles, if you don't, take a look here.
Also, remember that this principles are not patterns, they are recommendations for achieving a good code.
Like said before, our huge code has two main infractions:
Single responsibility principle
The first SOLID principle, it defines that every responsibility in a program should have your own class.
In a tweet:
“A class should have one, and only one, reason to change”
Changing how we calculate the trucks values should not interfere in the car price calculator, they do not have the same responsibility.
The O from SOLID, defines that a software entity should be open extension and closed modification.
Our entity parking bill calculator should not be modified when we add or remove a feature like BikeCalculator.
With those in mind and having a quick look in the patterns listed here, we can find this pattern:
It works with algorithms that can be encapsulated and used in a interchangeable way. This patterns are mainly focused on the "open-closed principle".
Which would be useful if we decide to transform the ParkingBill in a product and sell to different parking lots with different rules for calculating the price, wouldn't ?
Implemented, this patterns has this structure:
Client class calls a doSomething() method, that is implemented by the encapsulated classes.
How this would look in the parking problem?
And every time we want a new kind of calculator we only need to implement the “calculator” interface, a simple class, with a method called “price”.
If we want to add the TruckCalculator:
We can keep adding new logic for Hour, Monthly, Bikes or even OVNIS without touching a finger in other code. Furthermore, our ParkingBill service can now be used for any kind of parking lot. They can use his own rules to define what Calculator should be used for each scenario.
Maybe you are now curious about how we should create the calculator instance, but that is a creational pattern problem and I’m afraid that we have to discuss it in an next talk.
This is my first story ever here on Medium so I really hope that you have enjoyed it.
- Guerra, Eduardo. 2014. Design Patterns com Java.
- Metz, Sandi. 2012. Practical Object-Oriented Design in Ruby: An Agile Primer.
- Source Making. 2018. Retrieve from https://sourcemaking.com/design_patterns