Skip to content

Commit a76cee4

Browse files
introducing-php-lib-featuretoggle.md
1 parent f193684 commit a76cee4

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
title: "Introducing PHP Lib Featuretoggle"
3+
date: 2021-11-25T23:15:57+01:00
4+
draft: true
5+
tags: ["php", "library", "feature-toggle", "laminas", "symfony"]
6+
---
7+
Lately I've been developing a library I call "lib-featuretoggle" in my spare time after experiencing the hassle that
8+
implementing feature toggles can be.
9+
10+
# Motivation
11+
12+
If you are working on a larger scale project like I do at CHECK24 right now you will come to a point where you want to
13+
develop new features and test them against your production system without releasing them to your customer base. You
14+
might want to test it with just a portion of your customer base, just internal users or give users the option to
15+
opt-in for your new fancy feature - all are valid and quite common.
16+
17+
These are referred as `feature toggle` and are binary decisions a user or the system on that user's behave makes if
18+
a feature path is available or not.
19+
20+
Implementing each concrete feature toggle can be a tedious task if you have to write your infrastructure from scratch
21+
and will probably be not very easy to extend to support one of those other use cases I mentioned earlier.
22+
23+
# Solution: use `lib-featuretoggle`
24+
So I set out to create something in my spare time that might be used in our product sometime which meant it had to
25+
be usable via some kind of `dependency injection` and be easily extended with some kind of adapter.
26+
For our product we use `laminas` (previously known as Zend Framework) but for reasons both other products at CHECK24 and for my
27+
private projects prefer `symfony` therefore my new library has to support at least those DI solutions.
28+
29+
I started with a generic feature toggle class that contains a condition and a name for identification. While in my
30+
first naive implementation both condition and key where found on the same class I quickly realized I wanted to be
31+
able to create more complex strategies like "allow our internal users (by IP) to activate a feature toggle while they
32+
are logged in". So I moved conditions into their own, separate and furthermost important recursive structure while
33+
keeping the key on the original feature toggle class.
34+
35+
## Retiring feature toggles on launch day
36+
37+
The next hurdle I wanted to tackle with ease was the situation you easily come across after your feature lands in
38+
the wild after exhaustive testing behind a feature toggle: you have to remove it.
39+
There are several reasons you don't want to release a feature and remove every trace of a feature toggle in the same
40+
process but better wait a bit to let the user test your new feature through and through. I think the most important
41+
one is the flexibility to rollback without reverting your code but the list also includes the chance you remove your
42+
feature toggle and there is still code referencing your feature toggle. Therefore, you want to have some kind of
43+
logic in your feature toggle to return always your new default state no matter what logic your feature toggle
44+
previously had.
45+
46+
To tackle this the library uses several layers:
47+
1. FeatureToggleManager
48+
2. FeatureToggleRepository
49+
3. FeatureToggle
50+
4. Conditions
51+
52+
Every layer in that hierarchy has an 1:m relationship to the next layer below it with a First-In-First-Out (FiFo)
53+
solution regarding the `FeatureToggleRepository`. You will have two repositories in your application: the first one
54+
contains a list of all recent feature toggles, but they will always return their default state. The second
55+
repository might use some more advanced ways (like looking up every feature toggle in a database) and to evaluate your
56+
feature based on that result toggle's state, but as FiFo wins the static assignment from first repository will be used.

0 commit comments

Comments
 (0)