Picking your pattern

Spartner
Spartner
Published in
7 min readOct 16, 2018

We’ve all heard of design patterns. It became a hot topic again in the PHP development world the last couple of years. The idea actually originated way back in the seventies already. It grew again in the mid nineties when the Gang of Four released their book detailing 23 design patterns.

So today I would like to talk to you about how we, at Maatwebsite, pick and apply design patterns for our software solutions. Because, even though it’s cool and trendy to use design patterns, it’s not always needed. It also happens very often that a pattern is used wrong; only making the code more complex.

[…] even though it’s cool and trendy to use design patterns, it’s not always needed.

What is a design pattern?

In short; a design pattern can be used to solve a problem in your code.

You reach a point during the development when you are faced with a complex problem to solve. You need to introduce behaviour based on certain set of conditions or you want to perform an interchangeable set of tasks.

That is when a design pattern might come in handy. It provides you with means to solve these situations because somebody already thought of this problem. These problems were solved and proven to work by a design pattern.

Popular design patterns

There are quite a few design patterns out there. Some are very obscure and others are very well known because they are used in popular frameworks like Laravel and Symfony.

Let’s zoom in on a few.

Factory and strategy

These are the most used patterns by our developers. Whenever we’re dealing with a bunch of similar classes that can share the same interface but have different business logic, we can use a factory and apply polymorphism and the strategy pattern to create code that can scale.

For example; we have a ERP system where we are dealing with different kinds of customer values. These can be types like an address, currency, dates, radio buttons and file uploads. To display these we use a Factory to build a class that implements a Presentable interface. We do not have to worry in the view which kind of logic to execute, we will get a collection of Presentables to iterate. This is basic polymorphism.

Sample inheritance

So, the (business) logic might be different for an Address field versus a FileUpload field in how to display it. But they are all doing the same in the end. That is why we can utilise the interface and the factory design pattern!

We can take it a step further as well. If we want to also edit these values, we can introduce a new interface and have a different Factory build them for us.

This is how the inheritance could look:

Now we only need to have a factory that makes the correct type of class:

  • PresenterFactory
  • EditorFactory

Each of these factories have a single method: make() that receives a value to either present or edit:

<?php

namespace
App\ERP\Customer\Values;

class PresenterFactory
{
/**
*
@param Value $value
*
*
@return Presentable
*/
public function make(Value $value): Presentable
{
// Decide based on the type of value which
// presentable we need to return
}
}

We can even improve on this by adding a factory for which factory to include depending whether the page is editable or not.

Singleton

This is one that is used so often that you hardly realise it’s a design pattern. Many frameworks, like Laravel, use these for their core components.

The idea is that you would use this pattern for classes you’d only want to instantiate once throughout the life cycle of your request. Think of database or API connections.

It is very easy to apply this for our Laravel projects. When your register the bindings in your Service Provider you can actually choose to bind it as a singleton. Laravel’s container will then take care for you to only instantiate the class once and after that always returning the same instance:

/**
* Register any application services.
*
*
@return void
*/
public function register()
{
$this->app->singleton(
ThirdPartyApi::class,
function(Application $app) {
return new ThirdPartyApi(env('THIRD_PARTY_API_KEY'));
}
);
}

Adapter

In many of our projects we connect with third party APIs. These provide us with data in their own format. However this format does not match with our database. We need some way to make them compatible? Like sticking a square stick into a round hole. We can transform the results within an Adapter class.

Let’s say we have an IMDB API where we can search for movies. However they return a JSON array of movies that we can’t use directly in our code. We need to transform this result.

To start, we define an interface to search for movies, this tells us that we always want to work with an array of Movie objects:

<?php

namespace
App\API;

interface MovieSearch
{
/**
*
@param int $year
*
*
@return Movie[]
*/
public function fetchMoviesByYear(int $year): array;
}

We then implement this interface in our specific IMDB adapter:

<?php

namespace
App\API;

class ImdbMovieSearch implements MovieSearch
{
/**
*
@var ImdbApi
*/
private $imdbApi;

/**
*
@param ImdbApi $imdbApi
*/
public function __construct(ImdbApi $imdbApi)
{
$this->imdbApi = $imdbApi;
}

/**
*
@param int $year
*
*
@return Movie[]
*/
public function fetchMoviesByYear(int $year): array
{
$return = [];

// For example purposes. You could do the
// decoding in the API class as well.
$moviesAsJson = $this->imdbApi->getMoviesByYear($year);
$moviesAsArray = json_decode($moviesAsJson);

foreach ($moviesAsArray as $movie) {
$return[] = new Movie($movie['title'], $movie['year']);
}

return $return;
}
}

Now we have created an adapter class that wraps the original IMDB API and makes sure we always return a result the application can work with. If we need to connect to other movie APIs. We just create a new adapter conforming to the same interface and swap them out.

Composite

This is not a pattern we use very often but it can be useful for the right goals. Using the composite pattern makes it possible to use the same interface for both a group of classes (composite) as a single class (atomic). Now, that’s a very dry definition. Let’s look at an example.

We probably all had to deal with designing a solution for webshop discounts. Depending on the type of shop these can be very simple but what if your client wants discounts like:

  • 10% off for students
  • 100 euro off on purchases over 500 euros
  • When you purchase a Samsung Galaxy S10 on the launch day you get 15% off on all it’s accessories.

We are dealing here with increasingly complex discount strategies which can also be combined or not, depending on the client’s wishes. To implement this in your project you could resort to the composite design pattern. With the above example in our minds, this is how it can be solved:

The heart of this is the interface. You want to define a single way to calculate the actual total of an order.

<?php

namespace
App\Discount;

interface PricingStrategy
{
/**
*
@param Order $order
*
*
@return float
*/
public function getTotal(Order $order): float;
}

You can then create the different discount options in your code as seen in the diagram below:

These classes will calculate the order’s total based on their knowledge. They either apply a student discount, or they apply a discount on the accessories. As you can see they contain constants to be able to change their behaviour but only that of their own.

If we now want to calculate the total of the order we can introduce the composite that applies the strategy we need. If the shop has multiple promotions running at the same time they might not want to stack all discounts. In quieter times that might not be a problem. So we create to different strategies including their base class:

The base class contains multiple strategies that abide to the PricingStrategy interface. But depending on the actual calculation that takes place we either stack them (ApplyAllDiscountsStrategy) or only pick the cheapest one (ApplyCheapestOneDiscount).

The full class diagram would then look like this:

(Re)sources

This was just the tip of the iceberg. There are many more patterns out there. I encourage you to read more about them. These are a few of my favourite resources:

  • ‘Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development’ by Craig Lairman (Amazon). This is a great book with lots of practical information on how to design software using the Gang of Four’s design patterns. Including an introduction into Iterative Development.
  • ‘Head First: Design Patterns’ by Eric Freeman et al (Amazon). A fun book with real world examples (ducks, pizza’s) that clearly explains the most widely used design patterns and even a few more obscure ones.
  • https://sourcemaking.com/design_patterns

Written by Frank Peters, Lead Developer at Maatwebsite

--

--

Spartner
Spartner

As Laravel experts, Spartner creates market leading digital innovations as web-based applications to extend your operations. +31 (0)43-8516958 Spartner.software