CategorySoftware Architecture

Immutable Builder Pattern

This time we’ll talk about the Immutable Builder Pattern, but with a twist: the resulting instance has to be immutable.

From time to time I need to move away from the routine, just to avoid getting bored. Also, taking short breaks might help viewing things under a different perspective. Anyways, while working on Statifier I felt the need to get back to the roots and dive a little bit into the Design Patterns World ™ .

Straight from Wikipedia:

“the intent of the Builder design pattern is to separate the construction of a complex object from its representation”

This pattern is indeed extremely useful when you have to create an instance of a complex class, eg. with a long list of properties that have to be initialized.

It can be confused sometimes with the Factory pattern, but there’s a very important difference: Factories can be used to create an object instance based on some rules and return an interface. The result will be any concrete implementation of that interface, but consumers won’t (and don’t need to ) know which one.

Builders instead know how to create a single, specific class and the result is exactly an instance of that class.

And why should I be using the Builder if it can create just one thing? Well maybe because the creation is complex and requires several steps. Maybe you cannot just do something like builder.Build(param1, param2…..) , but you need a more structured approach.

The Wikipedia page has already some good examples of how the pattern can be implemented so I won’t talk much about that. 

But what is immutability anyway? Why do I need it?

At its core, immutability is a simple, very important concept: don’t let anyone from the outside update the internal state of your objects. That’s it.

Coding-wise, it translates basically into classes with no setters at all. All the properties will be initialized in the cTor, along with all the dependencies.

And why should I use it? Here’s an excellent article by Martin Fowler (yeah I love quoting him). Take your time, I’ll wait.

Ok so now let’s get back to out Builder. Here’s a sample implementation:

Few points to note:

  1. Vehicle cTor is private. Only the Builder can create an instance, and this is the main reason why the Builder class is declare inside the Vehicle class.
  2. all properties on Vehicle are get-only. Internal state cannot be changed, immutability is ensured. Good luck changing them.
  3. every call to Build() creates a new instance of Vehicle. This is again made to ensure immutability but comes with a twist: you have to be more careful if you want to reuse an instance of the builder to create more vehicles. You’ve been warned.

Unit, integration, end-to-end tests: do I need all of them?

Yes. I mean, don’t even think about it. You’ll need all of them, probably in different measures, but there is no “we shipped to production without tests”.

Tests are the first rampart separating you from madness and failure.
Why madness? Try to do even a small refactoring after you’ve deployed your app. Without automatic tests you’ll have to manually probe the entire system (or systems if you’re on microservices).

Why failure ? Simple, just think on the long run. Maintenance will quickly become a hell and adding new features will soon bring you to the infamous “it’s better if we re-build this from scratch”.

So! Where should we start? From the pyramid!

the test pyramid

The test pyramid. Image taken directly from Martin Fowler’s article. Thanks, Martin.

Starting from the bottom, you’ll begin with writing the unit tests. “Unit” here means that you’re testing a single small atomic piece of your system, a class, a function, whatever. You won’t connect to any external resource (eg. database, remote services) and you’ll be mocking all the dependencies. 
So, ideally you’ll be checking that under specific circumstances a method is throwing an exception or the cTor is populating the class properties or the result of a computation is a specific value giving a controlled input.
Also, unit tests have to be extremely fast, in the order of milliseconds, giving you a very quick and generic feedback of your system.

Next is the “Service” layer or, more commonly, “Integration”. This is where things start to get interesting. Integration tests check that two or more pieces fit correctly and the cogs are oiled and greased.  So stuff like your Persistence layer, access to the database, ability to create or update data and so on. They might take more time than  unit tests and probably will be in a lesser number, but their value is extremely high.

Then we have the “UI” or “end-to-end” tests. Here we’re making sure that the whole system is working, inspecting from the outside, with little to none knowledge of the inner mechanism. You’ll be checking that your API routes are returning the right HTTP statuses, setting the proper headers and eating the right content types.

In the end it’s all a matter of perception. The point of view is moving from the inside of the system, the developer perspective, to the outside: the consumer perspective.

There are of course other typologies of tests, acceptance, smoke, functional and so on. But if you begin adding the coverage using this pyramid you’ll save an awful lot of headaches and keep your system maintainable and expandable.

Feature Gating part 3 : how can we check the gates?

In this article we’ll explore few ways to check if the feature gates are opened or not. This is the third episode of our series about Feature Gating, last time we discussed about the optimal persistence method for the flags.

The first approach is a static config object injected as dependency in the class cTor:

It’s simple, easy to implement and does the job. The configuration object can be instantiated in the composition root reading data from whatever is your persistence layer  and you’re done.

Drawbacks? It’ static. That means you cannot vary your flags based on custom conditions (eg. logged user, time, geolocation).

So what can we do? Something like this:

Replacing the configuration object with a specific service will do the job. This is probably the most common situation and personally I’m quite a fan. The only drawback is the infamous tech debt: very soon the code will be filled with if/else statements. Should we leave them? Remove them? If yes, when? We will discuss in another article a simple strategy for that.

Speaking about strategy, it’s a very interesting pattern that we can exploit:

The idea is to encapsulate the new and the old logic in two classes (lines 10 and 11) and generate a third one which will use the previous featureService to pick the right instance. Finally all you have to do is to inject that class in the consumer and you’re done.  

Next time: this is nice, but is really useful? What do we really get using Feature Gating?

Feature Gating part 2 : how can we store the flags?

In the first article of this series we discussed the general concept behind Feature Gating, now we will talk a little about how we can store the flags.

A very naive approach is using a simple file per environment. You can serialize your flags in any way you want, json, xml, ini… then all you have to do is reading this configuration during the application startup and you’re done. 
It’s a very simple method and works very well for small applications and prototypes. Of course you have to remember to deploy the configuration every time something changes. Also you’ll have to implement some sort of flags hot-reloading in the application, otherwise the only option is restarting it (or if you’re under IIS, waiting for app pool recycling).
I said “one file per environment” because I’m pretty sure you have different configurations on DEV, UAT and production. Maybe you want all your flags to be on on DEV and only a small subset on production. Whatever suits your needs.

The next obvious step is persisting the flags in the application database. You can start with a simple table with the flag name and the boolean value.
Later on it will be possible to extend the system by creating relationships to the other tables according to your specific business logic. For example you might want to link flags to user profiles/permissions to allow only subsets of user accessing the features. 
This approach gives more flexibility during deployment, although you still need the hot-reloading. Also, linking the flags table to others might create unnecessary clutter and prevent splitting the monolith.

Let’s move forward to another approach: a key/value storage. Redis can be a very good candidate but here’s a list, just in case. 
Using this kind of databases you have few nice advantages: first of all you can decouple the feature gating from your application using a microservice.
Also, it would be possible to easily store different types of data not just boolean flags. Suppose for example that you want a feature to be enabled only for users in Canada and Japan. A solution could be storing the country codes in the flag value instead of true/false.

The last step is using a third party service. That means you’ll have to write the integration but most of the times there will be libraries already. Just make sure to pick a product with good documentation and decent user base.
Of course you won’t have anymore control over your data and in the worst case you might have to “bend” a little the system to accommodate your application needs. It’s something that happens every time an external solution is used: might cover 90% of the functionalities you need…but that 10% could require a lot of refactoring on your side.

In the next article I’ll show some design patterns you can use in your code to check the feature gates. Stay tuned!

© 2018 Davide Guida

Theme by Anders NorenUp ↑