Be More Productive

Get the most from your processes now!

Strategy as Code

encoding the plan for reliable outcomes

The concept of “Services” provides a mental model to explore how business objectives are transformed from ideas to experience.

You might have guessed that we’re not talking about “micro-services” or “service-oriented architecture”. Clearly, the term “service” is a very much overloaded. We need to frame the word for our purposes. Put on your “Thinking in Systems” hat, and let’s explore the idea of Services as a means of encoding and expressing strategy through design.

The Story of Who, Why, How and What

Language is Code.

Strategy basically comes down to your plan to get there, where-ever there is; Outcomes and KPIs in the language of modern business.

Merriam-Webster’s version of “A careful plan or method : a clever stratagem” is very much along the lines of what we’re aiming for.

A strategy is … about how people throughout the organization should make decisions and allocate resources in order accomplish key objectives.

— Michael D. Watkins

Plans for implementing business outcomes rarely survive first contact with the enemy. What at first seemed clear becomes opaque. The correct progression of events becomes uncertain when confronted by the complexity of the actual situation. The once convincing words of the plan now seem ambiguous.

There is no greater impediment to the advancement of knowledge than the ambiguity of words.

— Thomas Reid

Successful implementation of a strategy depends on being able to communicate not just the goal, but the plan. Drying out ambiguity of intent is essential. If we had a system to describe the plan in a consistent way that was sufficiently clear to allow a team with appropriate competencies to execute against it, we could think of it in terms of Strategy as Code.

Usually when we talk about code, we mean machine interpretable languages, which have the great virtue of leaving very little room for ambiguity. The absence of ambiguity is what’s needed for an executable product.

Executable Programs

When we think of code languages from Pascal to Python, Java to Javascript, we can see the common elements of a small vocabulary of clearly defined keywords tightly bound by syntax rules, capable of authoring fully unambiguous statements. A computer knows how to interpret a program, but just one misplaced character can be more ambiguity that a computer can deal with.

def fibonacci_sequence(n):
    if n == 1:
        return [0]
    elif n == 2:
        return [0,1]
        x = fibonacci_sequence(n-1)
        # sum of the last two elements
        return x

The Fibonacci Sequence in Python by Recursion

Infrastructure as Code

IaC is about eliminating ambiguity in software system environment setup and configuration. It’s not a language, like Python, but is a practice that can be implemented in any number of different computer languages. Python is popular for this purpose, but you could just as well use GoLang or or even Bash. What’s important about IaC for our context here is is that you’re still using code to crush ambiguity.

Here’s statement in Ansible that ensures that caching is configured correctly on the target environment. Committing details like this to code instead of relying on the expertise of individuals has been a game changer for system administration. Authoring IaC is a different discipline than coding executable programs, but the principle of eliminating ambiguity is the same.

- name: Ensure Varnish config path exists.
    path: "{{ varnish_config_path }}"
    state: directory
    mode: 0755

- name: Copy Varnish configuration (sysvinit).
    src: varnish.j2
    dest: "{{ varnish_sysv_config_path }}/varnish"
    owner: root
    group: root
    mode: 0644
  when: >
    (ansible_os_family == 'RedHat' and 
      ansible_major_version|int < 7) or
    (ansible_os_family == 'Debian' 
       and ansible_release != "xenial")
  notify: restart varnish

IaC — an Ansible script fragment for Varnish configuration.

Gherkin test scenarios

To stretch your imagination a bit farther, think about Gherkin syntax for test scenario authoring. The syntax rules accommodate regular human language phrases intermixed with defined keywords. Unlike most computer languages, Gherkin doesn’t have to be in fully executable syntax to be useful. Syntactically deficient Gherkin pseudo-code can be invaluable in resolving ambiguity for mere humans. Sometimes that’s all that is needed.

With a bit of attention to syntax rules along with some domain specific feature support, Gherkin can polished into machine executable statements suitable for interpretation by cheap and reliable computers.

Feature: Google Homepage Search

Scenario: User sees the header
  Given I’m on the homepage
  Then I see the header

Scenario: User can search with “Google Search”
  Given I’m on the homepage
  When I type “random page” into the search field
  And I click the Google Search button
  Then I go to the random page search results

Scenario: User can search with “I’m Feeling Lucky”
  Given I’m on the homepage
  When I type “random page” into the search field
  And I click the I’m Feeling Lucky button
  Then I go to a random page

Scenarios for verification in Gherkin

Integration of spoken language with machine language syntax makes Gherkin eminently useful for drying out ambiguity. It is closest to the model we need to author unambiguous Service Specifications.

User Stories and the illusion of explanatory depth

Because Gherkin is used as the language of requirements acceptance criteria, it is almost always found in the context of user story narrative format statements:

  As a [role]
  I want [feature]
  So that [benefit]

The Humble User Story

This narrative format is decidedly not an executable syntax. It is not intended for machine interpretation, but instead has human intelligence as its only audience. This is as it should be. It would be hard to overstate how important this narrative format has been in software development; its generality is a virtue.

It’s a common mistake to think of narrative format stories as “system requirements”. There is no way to actually resolve these narrative statements in the way actual code can be resolved into machine interpretable statements. Narrative format stories are better understood as bookmarks to conversations about the intent of the work. There are plenty of options for generating verifiable statements of requirements, so there’s no need to put all that burden on the humble user story.

Used in the appropriate context, the generality of narrative format is just what is needed; it reinforces shared understanding, invoking prior discussions and bringing previous debate to mind when we revisit a story. Stories prime the pump for humans when reviewing the work.

Used in the wrong context, as a proxy for actual requirements, the result tends toward increasing uncertainty about what is intended, rather than reducing it, by implying that there is an understanding of what will be the object of verification, when no such understanding actually exists. This is a psychological phenomenon known as the illusion of explanatory depth, where a topic is presented in a context and format that invokes a sense of certainty unwarranted by the supporting information.

What is important to our conversation here is to emphasize the importance of recognizing when we are speaking in useful generalities, and when speaking in generalities is only making it harder to see what’s needed. Where specifics are called for, generalities won’t do.

In practice, value streaming and process engineering rarely gets past the realm of generalities. Like narrative user stories, if the goal is simply to get everyone on the same page, this is not a problem, so long as you don’t expect that the model somehow informs how the plan can actually be executed.

The trouble here is that visual models are very susceptible to invoking the illusion of explanatory depth, where the dynamic, open, networked complexity of the actual problem space is simply wished away by a convincing generality, well presented.

If what we’re after is a model with sufficient clarity of intent that a team with the relevant competencies can execute against it, then we’ll be needing something more than a general narrative. It’s not rocket science. Essentially, all that is needed is to constrain the solution to the point where different people can arrive at a similar understand of the options for how the plan might actually be executed.

Strategy as Code

Thinking in Services by Majid Iqbal

The language needed to realize Strategy as Code, like other languages, will be comprised of a limited vocabulary of succinctly defined keywords, as well as a syntax to bind the expressions so that ambiguity of purpose is largely eliminated.

Like Gherkin, SaC syntax needs to accomodate normal human language phrases, so that we can make unambiguous statements of how business objectives are transformed from ideas to experience: the Language of Services.

“The biggest issue on software teams is making sure everyone understands what everyone else is doing.”

— Martin Fowler

Before we resort to yet-more meetings to sort out misunderstandings, we owe it to ourselves, and to the people who are paying the bill, to organize the work in such a way, so far as possible, that it is self evident what needs to be done, and thus easier to see if work in progress is on track or not.

Organizing work along natural boundaries is an essential attribute of services. Communicating those and related constraints that define a service in an unambiguous was is the objective of strategy as code.

To help unpack that, in the next section, Service Specifications, develops the concept of what we mean by service.


Thinking in Systems  by Donella Meadows
Thinking In Services: Encoding and Expressing Strategy through Design  by Majid Iqbal
Relevance Lost — The Rise and Fall of Management Accounting  by H. Thomas Johnson and Robert Kaplan

The Python Language — created by  by Guido van Rossum
Narrative User Stories — created by  by Dan North
Gherkin Syntax — created by  by Aslak Hellesøy, Joseph Wilk, Matt Wynne, Gregory Hnatiuk, Mike Sassak

The Illusion of Explanatory Depth  by Leonid Rozenblit and Frank Keil

Fibonacci code example
Infrastructure as Code example
Gherkin test scenario code example

Photo Credits

unsplash-logo Markus Spiske — "Hacker binary attack code. Made with Canon 5d Mark III and analog vintage lens, Leica APO Macro Elmarit-R 2.8 100mm"

Michael Godeck

Let's agree to define productivity in terms of throughput. We can debate the meaning of productivity in terms of additional measurements of the business value of delivered work, but as Eliyahu Goldratt pointed out in his critique of the Balanced Scorecard, there is a virtue in simplicity. Throughput doesn’t answer all our questions about business value, but it is a sufficient metric for the context of evaluating the relationship of practices with productivity.