Skip to content

adriancoman/gatekeeper-feature-flag-sample

Repository files navigation

Feature Flags - Increase the Frequency, Stability and Confidence in Your Releases

This is the code showed during my presentation about Feature Flags.

Archaic Feature Flags

The most "archaic" way of using a feature flag, comment or uncomment the code to get the expected result.

fun getCardToDisplay() {
    // var isVodaCampaign = true // uncomment to test
    val isVodaCampaign = false
    val cardToDisplay = if (isVodaCampaign) {
        PromoCard(
            text = R.string.voda_title,
            imageUrl = VODA_IMG,
            ctaText = R.string.voda_cta
        )
    } else {
        null
    }
}

Basic Feature Flag

A basic example of a feature flag, where we keep the string and the remote config in the ViewModel.

fun getCardToDisplay() {
    val cardToDisplay = if (remoteCampaignFlag == "voda_campaign_2021") {
        PromoCard(
            text = R.string.voda_title,
            imageUrl = VODA_IMG,
            ctaText = R.string.voda_cta
        )
    } else {
        null
    }
}

Feature Flag Extracted From VM

Extracted the logic from the ViewModel to a separate class that handles the remote value and the possible scenarios. The construction the card is still done in the ViewModel.

fun getCardToDisplay() {
    val cardToDisplay = when (gatekeeper.getCampaign()) {
        AvailableCampaigns.VODA -> {
            PromoCard(
                text = R.string.voda_title,
                imageUrl = VODA_IMG,
                ctaText = R.string.voda_cta
            )
        }
        AvailableCampaigns.INFOGRAPHIC -> {
            PromoCard(
                text = R.string.infographic_title,
                imageUrl = INFOG_IMG,
                ctaText = R.string.infographic_cta
            )
        }
        else -> {
            null
        }
    }
}

Feature Flags Using Sockets & Flow

Example using Flow while getting the config from a remote host using sockets so you have real time enabling or disabling of feature flags.

fun getCardToDisplay() {
    viewModelScope.launch {
        gatekeeper.getCampaignFlow().collect { campaign ->
            getCampaignCard(campaign)?.let { cardToDisplay ->
                ...
            }
        }
    }
}

Inverson of Control

Using Inversion of Control so that you keep the ViewModel as clean as possible. Gatekeeper decides what to show.

fun getCardToDisplay() {
    displayedCard?.getCard()?.let { cardToDisplay ->
        viewModelScope.launch {
            _activeCampaign.emit(cardToDisplay)
        }
    }
}

Releases

No releases published

Packages

No packages published

Languages