
By Ramas Grikštas, Back-End Engineer in the Core Services team at Kilo Health
Design patterns are typical solutions to the most common problems in software design. They help you tackle problems faster and allow you to communicate with other developers more easily. Plenty of us already use this approach, and it’s about time you started, too.
So, how and when should you use design patterns? And even more important – how can you learn them quicker?
Refactoring Guru has concisely summarized what exactly design patterns are:
“Design patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can customize to solve a particular design problem in your code.”
Imagine you need to build different objects by variable value.
We can write “if, else” statements and solve them one by one, but this approach that is commonly used in procedural programming wouldn’t be the most effective in Object Oriented Programming (OOP). This is not how someone using OOP would solve the problem at hand.
But before we explore how to use design patterns, let’s check out the benefits they have.
Design patterns have plenty of benefits because they help to:
Let’s get back to the issue at hand. You need to build different objects by variable value. What we need to do right now is to try to understand the problem and start to search for the solution using design patterns.
First, create different objects that implement the same interface by variable value. For instance:
To find the solution, you will need to use the resources available to you online. The best places I found to read about existing design patterns are:
For this problem, you don’t need to reinvent the bicycle – Object Oriented Programming has an answer to this problem. I also guarantee that design patterns will have an answer to 90% of the problems you’ve faced before.
So, in this case, the correct answer is to use a Factory design pattern. It is a creational design pattern that determines how to create an object’s mechanisms.
So, now you have defined a clear problem, and you have a solution for it. What’s left is to customize and implement it into your code.
If you don’t understand how this pattern works, don’t worry. Try to read about it a few times, but instead of trying to copy examples, figure out how it really works. Next time you face a similar problem, you will remember this pattern and find a solution faster.
Once you learn these patterns, you can use them in any programming language such as PHP, JAVA, PYTHON, C#, RUBY, GOLANG, etc.
It might take a slightly different approach to adapt them to different programming languages, but you can always find examples online on how to do that correctly.
Bad example:
<?php
declare(strict_types=1);
// Bad approach - procedural programming way
class Reader
{
public function read(string $fileExt, string $path): array
{
if ($fileExt === "csv") {
// Csv reading logic
return [];
}
if ($fileExt === "json") {
// Json reading logic
return [];
}
throw new Exception("Reader not found.");
}
}
$fileContentFromCsvFile = (new Reader())->read('csv', 'file_path');
$fileContentFromJsonFile = (new Reader())->read('json', 'file_path');
Good example:
<?php
declare(strict_types=1);
// Good approach - factory design pattern
interface ReaderInterface
{
public function read(string $path): array;
public function isEligible(string $extension): bool;
}
abstract class Reader implements ReaderInterface
{
public function isEligible(string $extension): bool
{
return $extension === $this->getName();
}
abstract public function getName(): string;
}
class CsvReader extends Reader
{
private const NAME = 'csv';
public function read(string $path): array {}
public function getName(): string
{
return self::NAME;
}
}
class JsonReader extends Reader
{
private const NAME = 'json';
public function read(string $path): array {}
public function getName(): string
{
return self::NAME;
}
}
class ReaderFactory
{
public function __construct(private Collection $readersCollection) {}
public function build(string $extension): ReaderInterface
{
foreach ($this->readersCollection as $reader) {
if ($reader->isEligible($extension)) {
return $reader;
}
}
throw new \LogicException('Reader not found!');
}
}
// Usage: you can bind collection through service providers
$readersCollection = new Collection([
new CsvReader,
new JsonReader,
]);
$fileContent = (new ReaderFactory($readersCollection))->build('csv')->read('file_path');
There are three main types of design patterns you will encounter in your work as a software engineer. These are:
Yes, I know that it might seem like a lot, but I’m glad to announce that you don’t need to try to memorize them all at once. They will come to you with your work experience and how much time you spent analyzing them. Also, I can guarantee that not all patterns will be needed for your projects.
When I started to learn these patterns, they looked quite hard. But once you deep-dive into the problem and find a solution, the only thing you need is to just try to figure out how this pattern works and how it solves your problem.
If you manage to implement it to your code once, next time, you will remember how this pattern solves this exact problem.
The second thing is to try and learn only the most common design patterns. Leave the rest for later.
How to learn these patterns faster?
Most important of all – try not only to read about the patterns but also to apply them to practice. Create your own project and situation where you would need to use this pattern. It will be like a small practice before really using it.
Let’s make life easier for you. I’ve compiled a design patterns list, which I use very often. These patterns are the most common in the PHP programming language, and I think they will help you on your learning journey.
As you already know, there are 3 main types of patterns: creational, structural, and behavioral. Each of them holds several key design patterns you might find useful.
Creational patterns:
Structural patterns:
Behavioral patterns:
More:
So, we know that design patterns bring us a lot of benefits. But they also bring more complexity. When you have learned a new design pattern, don’t run to implement this in all places because not every place needs to use them.
Try to always find at least one reason why this pattern will help you scale your code in the future. If you found at least one reason, go and implement it.
Sometimes when you don’t see that in the future, you don’t need to touch your code anymore – for instance, to implement a new feature related to this code. In that case, there is no reason to implement a design pattern because it won’t bring you any benefits.
There is no point in implementing a design pattern unless you know that this pattern will give a good performance to your code later on.
Design patterns aren’t hard to learn, but like with everything, it takes time and energy.
Actually, it’s harder not to learn them but to apply them in everyday life. Don’t push yourself if you don’t understand them from the first time you touch them.
The understanding will come with time. The only suggestion here is not to apply them to your real projects first – instead, create a test project where you can test your knowledge.
Read more books, watch videos about clean code, and later, you will have a deeper understanding of how to write more scalable, reusable, and flexible code.
Here are a couple of recommendations I think you’ll find valuable:
What books would you recommend for someone who is just starting out?
One of the first experiences Romy Carlson had after she joined Kilo Health was flying out to Lithuania, going to the National Opera and Ballet Theater, and listening to an orchestra during an event presenting the future of health. While…
Hiring processes can be draining. With all the stressful stages, it feels like one big interrogation. As much as we love crime documentaries on Netflix, we try to take a different approach and make the experience as smooth as possible….
Kilo Health became Europe’s second fastest-growing company twice already. At first, Deloitte ranked us among the tech leaders in Central Europe, and then the Financial Times named us the runner-up in Europe. Growth is at our core, and we got…