|
| 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