Feature Flags Patterns and Applications

The purpose of a feature flag, or known as a feature toggle, is to add code to an existing system without modifying its current behavior. If a feature flag is added to a system and the system breaks while the feature flag is turned off, it was not done properly. The end goal of a feature flag is to provide a low risk way to introduce new code to a production environment to let select users test the new feature, and for the feature to be easily deployed. The term mainstream feature will apply to a feature flag that is now turned on for all users. A feature that has the possibility of being turned off again is not considered a mainstream feature at that point. A more in depth look can be found on Martin Fowler’s site Martin Fowler’s Feature Toggle

Style sheet change Pattern (MVC)

In the MVC world, the controller is responsible for gathering and presenting a model to the view. This should include the results of any feature flags. In ASP.Net MVC, you can modify the model, or you can use a ViewBag, it is up to personal preference as both are acceptable. For CSS that is embedded in static files, you may need to create a new static file and use the feature flag to determine if you want to add the stylessheet as a page resource. Do not attempt to bundle the new style sheet, as if you have more than one feature in the system, you will have too many combinations of bundled and minified code to make this happen. Future web technologies, like WebRTC will make additional files no longer be a extra network request.

Controller Code

[code language=”csharp”]
public class HomeController : Controller
{
public ActionResult StyleSheet()
{
var feature = new US1234StyleSheetChange(HttpContext.User.Identity);

ViewBag.US1234StyleSheetChange = feature.Enabled();

return View();
}
}
[/code]

View File
[code language=”csharp”]
@section stylesheets{
<style>
@if (ViewBag.US1234StyleSheetChange)
{
<text>
.ok-button{
background-color: green;
weight:bold;
}
</text>
}
else
{
<text>
background-color: yellow;
color: red;
</text>
}
</style>
}

@if (ViewBag.US1234StyleSheetChange)
{
@*we couldn’t make all the changes with style sheets alone*@
<button id="go" class="ok-button confirm">Ok</button>
}
else
{
<button id="go" class="ok-button">Ok</button>
}
[/code]

Javascript Pattern

In the previous Stylesheet Pattern, we saw that it was easy to add to the view any changes to the stylesheet. In the below example, you can see we wrap the entire jQuery event around the same feature flag variable. In the case of minified or bundled javascript, it would be best to leave it out of the bundled files until it makes it as a mainstream feature.

[code language=”javascript”]
<script>
$(function () {
@if (ViewBag.US1234StyleSheetChange)
{
<text>
$(".confirm").click(function () {
var userAction = confirm("Are you sure you want to continue");
});
</text>
}

});
</script>
[/code]

Code only feature change

In the case of a code only change wrapped in a feature flag, a simple if statement suffices in most cases.
[code language=”csharp”]
public class HomeController : Controller
{
public ActionResult Index()
{
var feature = new US1234TitleChange(HttpContext.User.Identity);

if (feature.Enabled())
{
ViewBag.Title = "Home Page Changed for US1234";
return View();
}

ViewBag.Title = "Home Page";
return View();
}
}
[/code]
In extreme cases where code clarity may be results in a more unmanageable feature, you can break the feature into a private function and split the code path at the beginning of the function as shown below.
[code language=”csharp”]
public class HomeController : Controller
{
public ActionResult Index()
{
var feature = new US1234TitleChange(HttpContext.User.Identity);

if (feature.Enabled())
{
return US1234TitleChange();
}

//Additional changes made here should be made in the US1234TitleChange
//until it is a mainstream feature
ViewBag.Title = "Home Page";
return View();
}
/// <summary>
/// Please replace Index() with this function once the feature is mainstream
/// </summary>
/// <returns></returns>
private ActionResult US1234TitleChange()
{
ViewBag.Title = "Home Page Changed for US1234";
return View();
}
}
[/code]

SQL – Stored procedure pattern (Selects)

Some frameworks do not do well with additional columns returning. If you have one of those, you can apply the below pattern to make sure the new column does not come back from the select statement.

[code language=”sql”]
CREATE PROCEDURE [dbo].[usp_GetSalesVolume]
@param1 int = 0,
@param2 int
AS

if (Exists(Select 1 from FeatureFlags where id=4 and active=1))
begin
select ‘new data elements here’, @param1, @param2
return
end

SELECT @param1, @param2

RETURN 0
[/code]

Sql stored procedure (Updates)

In the case where logic changes for an update and the change has to occur in the stored procedure. You can add a new parameter that MUST have a default value set. Then break the code path into two and return or use an else statement. In this case a new table has been added, one the feature is a mainstream feature, the old table should be deleted along with the previous code.

[code language=”sql”]
CREATE PROCEDURE [dbo].[usp_UpdateSalesVolume]
@param1 int = 0,
@param2 int,
@param3 int =0 /*added per feature Goal Column */
AS
if (Exists(Select 1 from FeatureFlags where id=4 and active=1))
begin
update Goalsv2 Set [email protected], [email protected] where [email protected]
return
end
update Goals Set [email protected] where [email protected]
RETURN 0
[/code]

Bar Build

Bar Build – Part 1

There comes a point where you have enough parties and your friends leave enough drinks at your place that you must build a bar. Oh, this is easy, well, maybe not.

Step 1. Decide if you want a fridge in your bar or not. There are two types of fridges, expensive vent out the front commercial fridge, or the clear glass front fridges you have to leave two inches of clearance around. Go with the second option. We bought a nice Frigidare mini fridge with a glass front that fits in very well.

Step 2. Buy base cabinets from a local home improvement store (you can build your own). Base cabinets are what your entire kitchen is made of and are different from wall cabinets because they are deeper and have a toe kick. They usually have built-in supports to hold a counter top. Once you have the fridge, add in the four inches (two on each side) to properly vent the fridge, or what is recommended in the fridge manual. Also make sure your bar is not too long, you are not opening a restaurant here.

Step 3. Build a 2×4 wall, including the studs being 16″ on center to help screw in the cabinets. Since base cabinets are mounted to a wall in a kitchen to keep them from coming apart or moving, you should do the same. This also gives you an area to put the actual bar top where you put your food or drinks. The base cabinets are around 34″ tall, with a countertop. No one wants to lean up on a kitchen counter with their elbows, it feels horrible. Normal bar height is 42″ excluding the bar moulding. REMEMBER, 2×4″ are 1 1/2 ” x 3 1/2″, don’t mess up and be off by 1/2″ in your calculations. You will have 1 1/2″ for the bottom 2×4, and another 1 1/2″ for the top 2×4. Most bars use two layers of 3/4 plywood, so subtract 1 1/2″ (3/4″ X 2) for the plywood for the 42″ height.

Bar Wall

Screwing the cabinets to the base of the wall. Use shims so you don’t pull the plywood apart.

IMG_20140825_194842Cabinets screwed to 2x4 Wall

Step 4. Add in some paneling. No one wants to see those 2×4 or the back of those cabinets. Spend the extra few dollars and get some nice sanded or baltic birtch plywood. 1/4″ will work just fine if put the 2×4″ 16″ on center unless someone kicks your bar. If someone kicks your bar, you would have issues with 3/4 plywood too, you just spent more.

IMG_20140830_185906
Construction Adhesive to attach a panel to hide the 2×4 wall.

 

1/8 plywood on cabinet end
Apply a sheet of 1/8 plywood, then trip to the cabinet.
Bar Build
Same for all sides, micro-pin nailer so I didn’t have to clamp it.
Fluted molding, cut on 45 and on top of a 3" trip piece.
Fluted molding, cut on 45 and on top of a 3″ trip piece.
IMG_20140919_181959
Fluted molding, dry fit.

 

Added more trim with glue and a pin nailer, corbels to better support weight on the bar.
Added more trim with glue and a pin nailer, corbels to better support weight on the bar.

 

Next up, the countertop, paint and bar moulding.