Feature toggle architecture
Using abstraction and polymorphism in Swift
--
A feature toggle is a technique that attempts to provide an alternative to maintaining multiple source code branches, such that a feature can be tested even before it is completed and ready for release as well as A/B testing. Feature toggle is used to hide, enable or disable the feature during run time.
A few weeks ago my company decided to use Feature toggle to control features on production. As part of the iOS team I was tasked to integrate it, I did my homework and read some articles about the idea of it and common pitfalls as well as videos explaining the advantages and disadvantages of using it.
And this is the summary of it :
- Never reuse a toggle
- Short lifespan
- Name toggles well
- Architecture matters
Every one of these bullets is important and can have enough material to write a full article about, yet I want to focus on #4 Architecture.
When we think about using feature toggle we must remember that as great as a feature this is we still need to maintain it and make sure both scenarios (false flow and true flow) are working seamlessly and most importantly independently from one another.
A quick example of how features toggles are used in the most simple way:
Let’s assume we have a CarFleet class that controls the company cars, inside we have 2 methods: moveCarsToPosition and refuel, both have dependency for the feature toggle status, this is how it looks:
What you see in this gif is that both functions representing the false and true flows of the toggle are part of the class regardless the toggle state, and we want to avoid that.
Let’s break down what’s wrong here:
- CarFleet doesn’t care how cars are being moved and what fuel is being used. The only thing it cares about is that the cars would get to the customer and be fuelled.
- Using “if-else” everywhere will make your code less understandable and “pollute” the class.
- We can assume that “Toggles.Vehicle.carsCanFly” toggle we’ll be used in more than 1 file/class, hopefully, the toggle will be removed and the code embedded in the source-code, at that point we want to quickly and safely delete every occurrence of the toggle, going inside each file and removing them is time-consuming and unnecessary.
We should aim for abstracting the toggles completely from our code and break any dependency on them.
One way of abstracting is using Protocols (a.k.a Interfaces), let’s use POP (protocol-oriented programming) to achieve that goal.
When we combine protocols together with “where Self: x” we make sure only x has a default implementation, as well as access to all the public parameters and methods.
Make sure to properly document each computed variables and methods as shown in the example, this will ensure anyone after you know why this toggle is there and what each flow returns. This will ensure fewer mistakes and misunderstanding whether for future you or a developer after you.
Remember your name is attached to the top of the file, what and how you write is your personal identification as a developer.
How does CarFleet look after the abstraction:
Simple, readable and understandable that’s how your code should look like especially when using toggles but not only.
More about readability:
Lets see a full flow diagram represented in code
What are we seeing here?
- CarFleet has no idea it is affected by a feature toggle — Abstraction ✅
- We have a dedicated abstract class to handle everything related to feature toggle for CarFleet, plus all the “if-else”s are under one roof — Scalability ✅
- We have 2 files representing the Enabled logic and Disabled logic for this toggle, meaning all we need to do in order to delete the toggle is delete the file and follow the functions hierarchy until you get to the class (CarFleet) — Easy Toggle deletion ✅
With these 3 bullets, you can rest assure that you have combined abstraction and polymorphism in your architecture.