Features Over Artifacts

Artifactitis

Engineers have a natural tendency to focus on artifacts - classes, layers, deployable services and the like. This can be problematic when trying to slice requirements for delivery, all the way from the task up to the feature level. In this article I'll concentrate on issues with marking features as done while still thinking primarily of artifacts.

I've seen this recently where a feature which spans a number of microservces was split into stories - let's say one for each service. A not unreasonable view is that the story should be marked as done when that service change reaches production.

However, the service changes have some interdependencies. Given that the service changes don't all make it to production at the same time, then some stories would be blocked until their dependencies also made it to production. Now in one sense this is perfectly true: if the service can't be released until its dependencies have also been released then clearly it's unreleasable. But in another sense all the work - all the potential business value, all the coding, and probably even any infrastructure work required for physical deployment - is ready for delivery. If we are using these stories to track progress or burndowns then this information is lost.

The problem here is treating the artifact (the new or updated service) as the deliverable, whereas it's more useful to say that it's the feature that needs to go live. The artifacts are just a means of delivering the feature.

Features As Deliverables

So instead let's make the feature first class trackable items in our development workflow. In our imaginary kanban our stories fly (or crawl) across the board. But we can have another kanban at the feature level.

Note that the columns here naturally fit deployment environments, or more generally, configurations. Naturally, green means that all the tests in that combination of feature and configuration passed; red means failure, either test failure or because the code hasn't reached that configuration yet (one could presumably refine this further if one wants to see those two failure states seperately).

BDD From End To End

Using Cucumber (or any other similar BDD framework) we can write sets of scenarios for each of these features and have the underlying step definitions do the right thing in each configuration.

Consider this simple scenario for sending invoices from a backend system to an external client:

Given an invoice is produced in the backend

When the invoice batch is loaded by the system

Then the invoice is delivered to the client

Let's assume the system above consists of a number of services.

Now for the Integration configuration this might involve mocking various services or using a certain subset, whereas for Production this would be the entire set of interdependent live services. And all the scenarios have to pass in a given configuration for that stage in the board to go green.