Published on 2nd Jun 2021

Capt Compass E2 - Feature Flags

When it comes to hobby project having a feeling of progress is important, but how should we handle a feature that takes multiple tasks to finish? In this devlog I will show how I managed to tackle this problem for my own project.
It is normal to plan ahead before jumping into implementation, sometimes it means spliting up the work for several smaller tasks. So far I was avoiding this process, too much planning just takes away precious time from coding. Don't judge me, coding is more fun after all! :)
When creativity hits and reality is blurred during coding is an amazing feeling but when the gap between contribution gets bigger there is this wierd struggle to get back to the project and finish the started feature. I felt it myself too, going back to my project after a while would mean to read a lot of code before I can contribute again. On one of the sunday afternoons I was reading about merging PRs fast, and that is when it hit me that I am blocking myself from enjoying the progress feeling.
I still want to keep my master branch clean and always ready for release, but I had to solve the problem of merge half baked features fast. Keeping my development pipeline clean from unfinished feature would mean I can jump back to coding any time without a worry that unfinished work gets out of scope.
use flags
I started using local flags for my features, later on they can upgraded to be remote flags but currently there was no value setting up firebase feature flag. My implementation process follows the basic local solution but could be easily extended for a bigger team as well. This should have been a fairly good idea early on but usually you expect to be able to work on your own project.
To create flags we need to lift up the state from the application to global scope and make sure that every screen is able to request the flags and optionally even update them. I am going to use
's immutable data class solution to collect flags in a single place and adding features one by one with a default value.
 class Flags with _$Flags {
   const factory Flags({
     @Default(false) bool taskCategory,
   }) = _Flags;
In a team enviroment the flags could be parsed from a configuration file which could be pulled and refreshed with each release or allowing the flags to be overriden by a network response. For a smaller app it is enought to keep it local and don't worry too much about remote configs.
To connect the Flags instance and state management with each page a
has been created which holds a reference to the current flag instance and provided by the service locator. This might be a simple solution and does not reactively update each screen in the stack but it works as expected.
class FlagService {
   var flags = Flags();

// ...

Provider<FlagService>(create: (_) => FlagService()),
Each screen's state management request the flag service that provides the current flags instance.