Dear System Developer. I have seen the agony and frustration in your face. The every day context switching and inability to concentrate on one task at the time. Many years ago I felt it myself, back when I also did programming. As project manager I want to help you. But, in order to achieve our common goal, you need to help me back. I need you to help the tester and myself create specifications that make tasks small and independent. Only then we can achieve our common goal of a continuous single flow of valuable features delivered to the customer. No more headaches.
In this blog article I would like to discuss the concept of flow in software development by sharing my experiences from a current assignment. I want to show you how our inability to define small, independent, functional requirements ends up with headaches and stress. Even though the concept of feedback loops is a central part of this, I will hand it to my good friend and colleague Rune Larsen to explain more about Knowing your feedback loop.
When you finish reading this article I want you to ask yourself this question: Can we deliver more and better if we slow down and do one thing at a time (per developer)?
Driving along the highway we often come over situations where we have to hit the breaks. It could be road maintainance. It could be an accident. What happens if this occurs during rush hour? If you´re not sure, you can google “Queueing theory”. We can relate the traffic situation to our project environment where a development team will only be able to handle so many features at a time, before they start queueing up on the board. The number of incoming and ongoing tasks are exceeding the capacity of the team (too many cars, too little road capacity). Suddenly you´re invited to two or three meetings – every day – because you need to clarify these issues. Everything is depending on everything… #contextswitching #fail #headaches
The reason we often end up with multiple tasks is because we in our society can´t stand the thought of not being productive. There is an established truth that productivity can be measured by the amount of time put into one task (even today I hear of stories about project managers reporting progress by documenting how many hours have been consumed according to plan. wtf?). People idling, doing nothing, is considered wasting time.
I have the power to hold new tasks at a distance, but only if we find a way to finish our previous feature and delivering them as a whole, Tom J. Bang.
Functional specifications – only valuable from the users point of view
First of all we need to specify our requirements from an end users point of view. For two reasons; a) business value can only be measured through experienced customer value and b) it´s the best way we to make sure we actually build what we specified (and nothing more).
In my current project we are building IT-support for selling and operating long haul flights from Oslo to New York and Bangkok. Let´s say we want to offer our customers the opportunity to buy a premium seat (being more comfortable than the standard seat):
As a customer
I want to book a better seat
So I get a more comfortable journey
When we break it down to what we want to implement, we describe acceptance criteria as more detailed specifications. This is done by tester and developer in co-operation (read: this is our goal, but not everyone is comfortable with this way of working)
Multi-tier systems full of dependencies
Our technical environment consists of many separate systems with a specific responsibility (pricing, booking process, back office, shipping data between systems etc). So when we break a functional requirement down to smaller acceptance criterias we still need to make changes to a minimum of three systems.
I present this functional requirement to my team and ask: – How can we implement this in independent and small steps – acceptance criteria by acceptance criteria? The response is often: – (Enterprise bus:) We are waiting for interface changes from back office. (portal:) We have to wait for interface changes from the enterprise data bus.
This is how we would specify one acceptance criteria for user story described above:
Given end user has chosen a long haul flight <origin> to <destination> with a 787 plane
When end user books a <ticket type> with <seat type>
Then the flight should cost <expected price> and seat should be placed in cabin <expected cabin>
My question is: Why can´t we sit down together, figure out the interface together and then implement it together? That way we can avoid the context switching and rework because some one assumed that it was OK for the other system to receive such a parameter in such a way.
I think the main problem here is that we fear sitting together with the other teams, because they might see weaknesses on our side of the system, System Developer.
The fear of missing something on the way
In order to reduce lead time we need to make the task or deliverable smaller so we can present it to the user or decision maker faster, and then again get quicker feedback so we can make adjustments and move on. This is hard to do if we can´t accept an approach where we deliver thin vertical slices of functionality, and use the feedback to learn and improve when we continue implementing new slices.
Even though it seems reasonable to build each software layer (UI, services, data, …) independently when we want to build common services, we end up trying to solve several problems at once.
In our next release we will reverse our specification process, and start by having developer and tester together define some test cases:
|| origin || destination || seat type || ticket type || expected price || expected cabin ||
| OSL | JFK | Premium | Restricted | 1000NOK | C cabin |
The best way to miss out on something is actually to avoid real feedback. Real feedback meaning putting your code or features to the test, by observing how the system or end user reacts to it. As they say: “The devil is in the detail” and “Assumption is the mother of all f… ups”
It is very clear to me that once we start of by sitting together and creating the first test cases and examples – that runs from the user interface, down through system interfaces and back up to the user again – we will be able to find ways of implementing independent slices of functionality. That will enable us to get real feedback earlier, learn faster and design the system as we work our way through the requirements. But when we stumble into an obstacle on our way, we must not be tempted to put aside the task and start a new while waiting. Then it´s better to simplify the acceptance criteria in order to deliver something valuable, before starting a new task.
When traffic increases, slow down in order to hold a sustainable pace in a single piece flow. No more unnecessary contexts witching, multiple meetings per day or headaches caused by stress.
Dear System Developer and tester; Can we work together to make this work?
I really like the article, the way it is written and the topic that you address. We certainly _can_ do more by reducing the amount of work we do at one time. Or, we are able to deliver less with the right quality. I often wonder why many organizations end up in the way you describe here. As for the part of dividing work into tiers, and not functional slices, maybe we are stuck in ancient schools of though on how we are productive? People before us have believed in division of labour (Adam Smith and more) as a way to become more effective. Specialists do what they are trained to do and pass the work on in the value chain. I do not know whether this is within our nature in how we organize(hunters, farmers, caretakers, etc), or whether we are stuck in the mindset of others, but I do think it requires constant awareness and a good lump of persuasion skill to avoid this pitfall. I would also like to know how you think incentives effect this issue. Both economical and social ones
For those of you interested in real life evidence of queuing theories, check out what the Swedish have done (only in Norwegian): http://www.tu.no/motor/2012/03/29/slik-unngar-svenskene-ko
Reblogged this on tomjohannesbang and commented:
I have completed an example of how we specify functional requirements, fixed som typos and added a clearer summary of my learnings.
Thanks to Jakub Holy (@HolyJak), Kent Beck (@KentBeck), Pål Ruud (@ruudud) and Rune Larsen (@runeball) for excellent feedback!
Good article. We’re currently discussing this in our team as well. This autumn we’re a big team aiming on solving several activities. It might be a good idea, and it might not.
I very much agree on giving team members the feeling of flow. Both in protecting against noise (give me an M – give me an E – give me an E – T – I – N – G) and creating a good creative atmosphere so that one can work for more than 20 mins without distractions.
My team is a key player in realizing not only our own refactoring plans, but also many development plans from other teams. If we do not participate in their planning processes, we risk getting ending up with bad arcitecture. If we do, we fuck up our own flow.
Another issue we’re looking into now is team size versus parallell tasks/projects. Are we able (and how?) to solve one prototyping process that require team member a,b,c,d together with one software upgrade process that require team member d,e,f,g and one last smaller, third task that require member a,b,g.
My point is that delivering one thin horizontal slice *might* fit a smaller team better than a large team. I feel that a rapid prototyping process is more dynamic, focused, more product oriented and better off on few heads.
Since I represent a large organization where not every division/ department are syncronized on their requests, we also need to spend time bouncing, coordinating and advising on dependencies, arcitecture and the births of projects that evidently will land in our backlog.
My colleagues in my team are extremely fine people. I’m pretty sure we’ll work it out. But I’m also pretty sure our take isn’t the best way to create flow. And that we will not end in any agile bible for best practice.
For me one of the most important things is that we need to be extremely aware of the reasons for doing parallell tasks at one time. And that parallellity is bad for business, and cost a lot of time. Which means lots of money.
Great article Tom! I do agree with you that the best way to implement a new feature is to start small and implement it all the way through vertically. I think the main problem people have with working like this is fear. The fear of the design not supporting all the use cases and the fear of starting to small will result in a major refactoring of the code later. So instead of focusing on getting one single feature done, we end up spending a lot of time trying to get the design right for all possible future use cases – “get it right the first time”. But without an iterative approach (or to long iterations) we are missing out on all the valuable feedback. From my own experience you will never get it right the first time no matter how long you spend on the inital design, but it improves after you learn more about the problems you are trying to solve. So I would say we should slow down and do one thing at a time.