Feature Toggles

What are Feature Toggles?

Feature toggles allow us to develop features that take a long time to build directly in the main development line (not needing branches, which may diverge) without showing half-baked functionality to the end user. While the feature is being built, it is invisible unless you turn on a feature toggle for the installation. Usually the developers working on the feature will first turn on the toggle on their own machines, and later it will be turned on in some CI environment. Once the feature is complete, the toggle is removed completely, to avoid cluttering the code.

Feature toggles are not a long-term mechanism for enabling/disabling features. (That should be done through the App Framework by enabling/disabling Apps and Extensions.) They are a quick, often-hacky short-term convenience for the developer.

See Martin Fowler's longer description here.

Setting up your dev environment

Create a file named feature_toggles.properties in your OpenMRS application data directory. (Alternately, you may set an environment variable called FEATURE_TOGGLE_PROPERTIES_FILE, and point this to whatever location you like, e.g. "/Users/djazayeri/feature_toggle.properties".)

In that file, put a line for each feature that you want to enable, like:

referenceapplication.personalRelationships=true

Writing code with toggled features

How to toggle a feature in your Java code

The App Framework module provides a FeatureToggleProperties bean. You can autowire this and use it like:

@Autowired FeatureToggleProperties toggles;
...
if (toggles.isFeatureEnabled("referenceapplication.personalRelationships")) { ... }

How to toggle a feature in your GSP pages

The App UI module makes the FeatureToggleProperties bean available as “featureToggles”, so you may write groovy snippets like this:

<% if (featureToggles.isFeatureEnabled("consult_note_confirm_diagnoses")) { %>
    <div class="actions">
        <label>
            <input type="checkbox" data-bind="checked: confirmed"/>
            ${ ui.message("emr.consult.confirmed") }
        </label>
    </div>
<% } %>

How to toggle a feature in your JavaScript

The UI Commons module lets you access the state of feature toggles from the emr.isFeatureEnabled function, like:

if (emr.isFeatureEnabled("navigatorQuestionCheckmarks")) {
        // mark the question as done at least one of the fields has a value, and all the expected fields have a value
        anyFieldHasValue && !expectedFieldMissingValue ? this.questionLi.addClass("done") :
              this.questionLi.removeClass("done");
}

Toggling features in testing/training/production

Once the feature is committed, and you’re ready to turn it on in some environments, you need to make various changes to https://github.com/openmrs/openmrs-distro-referenceapplication

These instructions refer to the PIH Mirebalais setup, not to the Reference Application. Someone needs to update this section...

  1. Set the default value of the toggle to false in puppet/hieradata/common.yaml
  2. Include the toggle in puppet/modules/openmrs/templates/feature_toggles.properties.erb
  3. Turn the feature on in one or more testing/training environments, e.g. puppet/hieradata/bamboo.yaml

After a feature is toggled on

“It’s very important to retire the toggles once the pending features have bedded down in production. This involves removing the definitions on the configuration file and all the code that uses them. Otherwise you will get a pile of toggles that nobody can remember how to use.” —http://martinfowler.com/bliki/FeatureToggle.html

Once a feature has been turned on, and run for a while with no errors, you need to remove:

  • its usages in code
  • its use in settings files