January, 2020

One year ago, in January 2019, Chris Coyier released the article The Great Divide. He shows that we are facing some challenges by introducing new disciplines and sub-disciplines to the field of software development.
What do you need to learn, to call yourself a frontend developer? What even is frontend-development?
The difference between "front of the frontend" (UX, UI-Design, a11y) and "back of the frontend" (programming) shows a divide in specializations - that is not without a cost.

A cost that needs to be addressed: with every spezialization comes the need for integration.
I would argue, that this is mostly overlooked and it creates one of the biggest problems in modern software development.

In this article, i will define the cost that comes with our specializaions and why we need to address it.
I will describe a systemic problem at the very core of how we work,
and show a solution to resolve this problem - something you can use today.

This is all in good spirit, as this article is about improvement and a positive outlook on what is possible.

I hope that you will, more often then not, find a way to discover that integrated teams can be much bigger than the sum of its parts.

System And Parts

A way to look at our situation, is through the lens of Systems Thinking.

Systems Thinking was pioneered by the work of Russell Ackoff. This is one of my favorite clips, where he talks about improvement. Something that you may see as fitting for this article.

I will use some of his words, for the following explanation.

We are dividing the system of software development into parts (specializations). The assumption is, that if we improve every part separately, the system as a whole will improve.
But this is very misleading.
A system is a whole, that can not be divided into independent parts.
The parts are all interconnected. Improving a part will not necessarily improve the system as a whole.
Most properties of a system will derive from the interaction of its parts - not from the parts taken separatly.

Example
When an architect designs a house, he can not design the rooms taken separately.
The rooms are all interconnected, and if he wants to make the bathroom bigger, he knows that this has an impact on other rooms and the structure of the house itself. For the best possible house, no room might be the best possible room.
Everything needs to be evaluated against the improvement of the whole.

This is directy reflected in how we develop the software itself.
We often act and think in silos, and our focus easily shifts from improving the software as a whole to improving specific elements we see as important.
UI-redesigns, performance optimizations and better code abstraction layers - there is always something we can make better.
At the end of the day it comes down to what we have done with our limited time, money and information.
If we only improve the parts without the focus on the improvement of the system as a whole, we will not only be wasting a lot of opportunities to deliver the best possible result to our customers, we will make the system worse.

Hidden Cost

Because all the parts are interconnected, every specialization we introduce will create the need to be integrated into the whole.
We assume that the right process (for example an agile framework) will bring everything together, but the truth is, that a process is limited to means of coordination. Integration on the other hand, is about a common ground, an overlap of different disciplines that can result in a shared language and artifact.
We need a good process, but it is not a substitute for integrative methods.

Modern software development is often associated with an iterative processes (visualized as cirles).
Any agile framwork will make use of one or multiple of those iteraive processes. In this case visualized by a think-make-check circle.
Here, the process is shown in two different ways. On the left, coordination with an emphasis on direction. Integration on the right side where different fields of specialization are shown as circles.

Think-Make-Check circle: coordination VS integration

On the right side, we see overlapping areas. They are a common ground, where we can find ways to share an understanding - to work together.
Without it, we are only able to throw our work over the fence for the next team to continue.

There is something called a "Developer Handoff".
After completion of his work, a designer will hand his work results over to the development team.
If he made a good job, the developers are able to understand enough to implement the neccecary code.
The work is clearly divided - but what is easily missed?
The nessecary interactions between designers and developers!
Even if the developers are able to implement the code, what about the shared understanding of the whole?
Why are the designs made that way? What about the developers who would love to give an opinion before the designs are finished?
Are those issues addressed in your team? If not, then there is the danger of destroying an environment where everyone has a chance to be engaged to deliver the best possible software.

For many companies, this is the default behaviour. It is the culture of our economy: the division of labor.
As a result, a strict process might be seen as overly benificial to your employee.
To be a worker in a process, your work is more easily measured and checked, to optimize for efficency.
It is a lot like working on an assembly line.
We are focused on doing things the right way.
This is the goal of coordination.

On the other hand, we have integration.
The goal of integation is, to do the right thing.
To create a common ground where we are able to work on a shared understanding of what we try to accomplish,
so that we can look at the result of our work, learn from our mistakes and gain insight about the next steps we need to take.
A team can be very efficent and finish a lot of features, but features do not guarantee an improvement.
Only if the software will be improved as a whole, a feature will add value.
This point is also explained by W. Edwards Deming:

"It is not enough to do your best; you must know what to do, and then do your best"

This is why we need coordination and integration. They are a complementary pair.
At the moment, we are very much devoted to do things right, even if we do the wrong thing.
Unfortunatly, this makes the wrong thing even wronger.
An agile process can help us, but it will not prevent us from slipping back into the old waterfall-behaviour.
Even in our sprint reviews, we can learn nothing about the values we added in the latest iteration.

Why Waterfall Will Catch Up

At the beginning, everyone is on board, we talk about our goals and about the software we want to build.
There are many creative and engaging techniques to enable our teams.
This is when the value of integrated teams is clearly visible.

work on a userstory-map

There comes a time, where we need to write some code.
With every sprint, the complexity grows and agility has its limits. At some point, the path is mostly set.
Maybe we should rebrand our agile projects to be more honest, so we don't raise false expectations.
"10-sprint agile then mostly waterfall"?

What happened? why is the complexity growing so fast?
Todo: Hier den Übergang zum nächsten Abschnitt etwas besser hinbekommen.

Duality

The following example describes a situation where we are hindered from having a meaningful conversation, because of a duality we see as a given.

You are in sprint 32.
Someone shows you a database schema.
Do we need field "x"?
You could say: it depends.
It depends on what?
It depends on the context

Your answer could be: Yes, we need field "x" because it is required for the user registration process and for...
This is an answer someone might expect, but to be able to give it, a developer needs to know all the scenarios that need field "x" and this information might not be easily found, as it got complected into the structure.

the divide

Design and Testing will describe the software in terms of scenarios (seen on the left).
On the right side, developers will describe the software in terms of an executable software construct.

This is the duality. On one hand, we have a scenario based thinking that lets us define in a very human way how things should work. This is in fact how we -as humans- try to make sense of the word that surrounds us.
Like: "the user is able to register by providing the needed information".

On the other hand, we write software, because we need something that is machine-executable. We add methods, classes, components, ..., to our software construct, so that it is capable of running our scenario. "we need to implement a new service, the form-component needs to include field x, ..."

drifting apart

This is the divide at the very core of how we work.
A duality that is hidden, and deeply ingrained in every iterative process.

From a developer perspective, this duality creates a world of problems. Here are my top 4.

1. complecting scenarios

After adding functionality to the same part of our construct, we might fail to reason about it.
What scenarios have shaped this component?
Why is this if/else here?
If we are not able to reason about our code, how can we make confident changes?
Complecting scenarios will result in complexity.

2. enabling unwanted scenarios

When we implement a new feature, we add new functionality to parts of our construct - but what unwanted scenarios we have we accidently enabled, too? can we test this?
Bob Martin tells me that i need "negative tests" - but it is not that easy.

3. change in mindset

We want to increase the power of our software.
The wish is, that the software will be so well constructed, that it would be easy to enable possible future scenarios, or even possible future projects.
We focus on our powerful software - and less on the needs of our users.

4. programmer convenience

The constructs have attributes of themselfes, as we like to think about elegant abstractions or the latest version of framework x.
Without the focus on the software as a whole, we see all the promoted benefits of adding framework x - and only some of the drawbacks. Before i quote every part of the talk Simple Made Easy by Rich Hickey, please go ahead and watch it.

I would argue that developers suffer the most from the consequences of this divide.
But those problems are somehow self-inflicted. Developers need to find ways to assess the construct based on the artifacts.

At the end, everbody needs to pay the consequences.
From my point of view, this duality is one of the biggest problems in modern software development.
Maybe we need another crisis for this to change. Maybe the growing success of the no-code movement will teach us.

Luckily, this article is about improvement and a positive outlook, and i promised a practical solution for this problem.
It is not a silver bullet, but i hope i can demostrate that there is a choice.

What would happen if we change the system?
To a system, where this duality can be resolved?
In this system, a scenario will be an common artifact in designing, development and testing.
It is about resolving a duality at the very core of how we work.
To make a change that brings us together.

Experiment

At this point, it all comes down to an experiment.
What will happen if the scenarios we want to enable are directly reflected in our code?
What will happen if the scenarios can be added/removed in a modular way?

For this experiment, we will develop a simple image slider.
Our team has agreed on a couple of requirements.

  • only one slide (the current slide) is shown
  • The user is able to slide to the left and right.
  • The slider can rotate in both directions.
  • The slider will have a play function and slides after x ms.
  • The slider can be paused at any time.
  • Bulletpoints can be used to jump to a specific slide.
  • If the user changes slides manually, the slider will pause.
  • The slider will start to play automatically

Designers have scetched some first designs, and included input from the developers.
They have found some technical requirements and edge-cases that need to be reflected in the UI as well.

  • The slides are loaded asyncrounously. (show a spinner ?)
  • If there is only one slide, the slider has no functionality (show no buttons ?)

The developers started coding and this is the scaffolding of the discussed scenarios in code:

(scenario) => { const items = scenario(loadItems, [url]).value; if(items) { const index = scenario(showCurrentSlide, [items]).value; if(items.length > 1) { scenario(jumpToSlide, [items.length]); const leftRight = scenario(slideLeftRight, [index, items.length]); if(leftRight) { scenario(rotate, [index, items.length]); const isPlaying = scenario(playPause, [3000]).value; if(isPlaying) { scenario(pauseOnIndexChange); } scenario(autoplay); } } } };

If you want to go into the details - here is the complete code.
Uncomment a scenario and see what happens.
There is a lot to unpack how the modular scenario system is constructed.
Most ideas came from Behavioral Programming. I implemented this as a react-hook with no 3rd party dependencies.

The scaffolding is needed for a simple reason: hierarchy.
Some scenarios only make sense, if other scenarios are enabled or in a specific state.
For example, we do not need the scenario "jumpToSlide", if there is only one slide.

lets look at the problems i have listed before

1. complecting scenarios

This demonstrates that we are able to address our code, based on the scenarios we want to enable.
And there in front of you, is a great starting point to answer the big question: Is the software enabling scenarios it is supposed to enable?
TODO: look at specific scenarios and show difference between complecting and modularity.

2. enabling unwanted scenarios

TODO: show that the inter-Object nature of scenarios will make it easyer to prevent unwanted scenarios (show intra-object img)

Todo: 3 and 4, only time will tell.




TODO:

What are the benefits?

  • Änderungen durchführen, ohne die einzelheiten der anderen Scenarien kennen zu müssen.
  • Auf append-only Artikel verweisen
  • Konversations-Möglichkeiten mit Designern und Testern verdeutlichen.
  • Auf die Top 4 Dev-Probleme eingehen die ich vorher beschrieben habe.
  • Wie die Testbarkeit gefördert wird.

Next

  • Verweis auf einen weiteren Artikel, der zeigen soll, wie der Code funktioniert.
  • Verweis auf einen weiteren Artikel, der