Analysis and Synthesis in Software Production

A dry stone wall

I’ve been thinking about some unproductive discussions I’ve had recently about software production methodologies, discussions where we’ve seemed to be talking across each other, rather than settling on a clear statement of our differences. In cases like this, it’s often the case that we agree on the structure of our arguments, but that there is a fundamental difference in our assumptions or values.

I’ve also been thinking about (apparent) dichotomies, inspired in part by Stephen Jay Gould’s fascinating book, Time’s Arrow, Time’s Cycle: myth and metaphor in the discovery of geological time. In this book he investigates two concepts of time have shaped the science of geology. I write ‘apparent’ in parentheses, as it becomes clear that these concepts are not in opposition, but rather creative tension with each other.

This led me to look at my conversations about software production through the lens of another apparent dichotomy: analysis versus synthesis. As in Gould’s example, I don’t consider these concepts to be in opposition, but rather our decision which of them to emphasise, which to give primacy, has a profound impact on the way we approach software production.

Analysis

Analysis, ἀνάλυσις, is the breaking (λῦσις, from λύω, to untie, detach) up (ἀνά) of a problem. In software production, this describes taking a set of requirements or a system, and breaking it into smaller pieces, each of which is easier to reason with. This is an essential tool for creating software of any complexity, as reasoning with the entirety of the system is beyond most human abilities.

Synthesis

Synthesis, σύνθεσις, is the putting (θέσις, from τίθημι, to put, place) together (σύν) of a solution. In software production, this describes assembling parts, whether they are method calls, classes, packages or deployable components, into a system. This is an essential tool for creating software of any complexity, as the many moving parts need to interact with each other.

The Analyst Doctrine

There is a school of thought in software production that strongly favours analysis over synthesis. According to this school, software can be successfully produced by analysing the solution into various components, which can then be developed in isolation. Bringing these components back together (synthesis) should be trivial if the analysis has been adequate; if problems arise, then this is a consequence of either inadequate analysis or incorrect implementation.

This doctrine goes hand-in-hand with loosely coordinated development teams. After all, with adequate analysis, the software developers should have all the information they need to write the software, and the interdependencies between the constituent components have been taken care of during the analysis phase. The majority of coordination will be about scheduling, so alert and energetic project management is important.

Testing is focused on the components, ensuring that they conform to their requirements. Where components have dependencies on each other, these can be abstracted away with the use of system mocks, which are straightforward to create, as the contracts have been established.

As combining the components is considered trivial, this can be delayed until development and testing on the individual components has been completed. There can then be a short phase of testing across the entire system to demonstrate that it works as planned, before release to customers.

In my opinion, this is a recipe for disaster. In particular, the system testing phase is rarely trivial, and often takes a dedicated Quality Assurance (QA) team significant amounts of effort, as they find themselves testing all possible routes through the system and uncovering plenty of unexpected behaviour, which is then reported to development teams as bugs.

If the development teams are attempting to work in an ‘Agile’ way and deliver features incrementally, then the work of the project manager becomes even more important, as the delivery of capabilities in the constituent systems needs the be coordinated for each testing phase.

The Synthesist Doctrine

There is also a school of thought in software production that favours synthesis over analysis. According to this school, software can only be successfully produced by bringing together the constituent parts as early and often as possible. This school sees the greatest potential for complexity and uncertainty in the interactions of the components, and seeks to minimise risk by testing the underlying assumptions continuously.

This doctrine goes hand-in-hand with highly networked teams. It is expected that the complexities of the components’ interactions will only become apparent over time, and it is important that these any simplifying assumptions are revised as soon as possible. Scheduling becomes a global rather than local question, and it’s much more important to ensure that requirements evolve and priorities are revisited, rather than focusing on meeting delivery dates.

Testing occurs at all levels, but particular value is given to testing that the entire system works as expected. These tests are the ultimate proof that the customers’ needs have been met and that the software is fit for purpose. Mocks are fundamental practices, but they are most suitable for lower-level tests, and whole-system tests try to exercise all integration points.

As getting the interactions right is prioritised over the detail of the individual components, they may start as broad sketches of the expected behaviour, and complexities and edge cases are added as they become necessary. Indeed, some of the initially desired behaviour may never make it into the final system. As combining the components into a whole system and exercising it with tests happens continuously, there is often no need for a final testing phase.

In my opinion, this methodology gives us the best chance of success.

Continuous Integration

In the preceding sections I have avoided the word ‘integration’, but I’ve skirted around this issue many times.

We refer to the act of combining any parts of software as integration, to the extent that it’s almost a synonym for ‘synthesis’. (Curiously, the word comes from the Latin ‘integer’, meaning un- (in-) touched (from tango, to touch) and implies unity and atomicity, rather than acknowledging the analysis–synthesis cycle). Whether we leave it to a final phase or do it continuously, all non-trivial software needs to be integrated at some point.

A commonly attempted practice is Continuous Integration (CI). I find it interesting that most discussion of CI focuses on integrating code changes into a central codebase, when the practice also enables us to integrate behavioural changes into a complete system. Needless to say, I believe that the pursuit of CI is a key tool in a synthetic approach to software production.

Integration Tests

Ask n developers to define integration tests, and you’ll get n+1 answers. I try to avoid the term altogether, using more specific phrases to capture specific types of test.

I talk about adapter tests, where we test the (ideally very thin) parts of our code that interact with other components and systems. I see these are developer-facing tests, and consider them an important part of a developer’s toolkit.

I’ve seen teams in an Analytic context omit adapter testing altogether, as these tests blur the boundary between an isolated, tightly specified system and the messy outside world. When this happens, a debt of uncertainty is incurred that must be paid off with interest during the integration phase.

I also talk about various types of cross-system and whole-system tests. These can be thought of as integrated tests, as they exercise an integrated system. This is the level at which we prove that the desired behaviour has been implemented, and these are often customer-facing tests, which form an important part of the team’s delivery.

It’s worth observing that integrated tests form part of both approaches, but that the tendency under the analyst doctrine is to do extensive manual testing during an integration phase, whereas under the synthesist doctrine we perform lightweight automated testing after every integration. J.B. Rainsberger argues that Integrated Tests are a Scam, and I have some sympathy for this point, so it’s worth noting that the extensive QA performed under the analyst doctrine fits Rainsberger’s critique much closer than the lightweight whole-system testing of the analyst doctrine.

London and Chicago

It’s interesting to notice in passing that these approaches appear to have parallels in the two styles of Test Driven Development (TDD). London-Style TDD characterises the behaviour of a system in broad brushes in its entirety, and then digs down into the details to write just enough code to implement that behaviour. Chicago-Style TDD (certainly when practised at scale) focuses on evolving well-characterised components, and then assembles them into whole systems. We can see that the London Style responds to Synthetic thinking, whilst the Chicago Style responds to Analytic thinking.

Waterfall versus Agile

The Analytic process I described above looks very much like the delivery pipeline of a Waterfall project. Indeed, the Poppendiecks in their book Lean Software Development characterise the traditional approach to software production as implementing an Analytic mindset, whilst they see a Synthetic mindset in the Lean and Agile ethos of Seeing the Whole, and building entire systems in rapid iterations.

It’s interesting to look at the projects that fall between these two approaches. As I mention above, many organisations maintain an Analytic approach, even though they attempt to introduce Agile concepts by delivering functionality in increments. The tensions created by this mixed approach can lead to more work for project managers as they attempt to coordinate teams’ priorities.

It’s Not All or Nothing

Having said all this, we must remind ourselves that Analysis and Synthesis are not in opposition to each other, but are two sides of the same coin. You cannot reassemble something that hasn’t been broken apart. Even the pure Analytic process includes a phase of synthesis, and even the most radically Synthetic project demands analysis of each increment. What is important is that these two concepts give bias our decisions and working practices, and whereas the Synthetic approach demands frequent small acts of analysis, the Analytic approach puts off synthesis to the final phases. It’s clear to me which approach I find safer.

SoCraTes BE 2019

Floréal La Roche

I’ve spent the last few days at the SoCraTes BE Unconference. Here is a brief report.

SoCraTes takes place at a holiday camp in a socialist realist château among the sheer wooded slopes of a Belgian Ardennes.

It’s an unconference, which means that rather than having a predetermined schedule, the participants apply the Open Space Principles to create each day’s schedule.

Here are some of the sessions I attended:

A group exercise creating a Wardley Map of a fictional shop. I’ve heard lots of people talking about Wardley Maps, but this was the first time I got to try them out.

A workshop practising a couple of Liberating Structures. I didn’t think I was familiar with Liberating Structures, but it turns out I’ve been using a few of them for a while! I particularly liked the Troika Consulting structure, and the problem we encountered enabled me to talk through a few techniques I’ve recently learnt from Goldratt’s Thinking Processes.

A nice group discussion on What makes a good stand-up? It turns out lots of us have encountered similar problems and found similar solutions. Hurray!

Talk like Sandi. We watched Sandi’s talk, Get a Whiff of This, and then had a group discussion about what makes her such a compelling speaker.

Code Smells quiz show. This was based on an activity I recently ran with my team, and as luck would have it, my friend Pedro, who wrote the source code for the exercise, was also at SoCraTes, so we ran this session together. It was really popular, and definitely worth repeating.

The Transport Tycoon exercise: modelling a delivery network. This gave us a good chance to compare Classic TDD and Domain Modelling techniques to understand this problem.

Making illegal state transitions impossible. A fairly involved look at modelling state machines in functional languages. We spent rather too long struggling with the language, but it was good to discuss the basic concepts.

Powerpoint Karaoke with each other’s presentations. This is always an entertaining evening activity. It’s usually played with random slide decks from the internet, but this time we challenged each other to improvise talks to presentations that other members of the group had once given.

I had a casual discussion with my friend Pedro Santos about how often personal and professional development is accompanied by pain (an idea that goes back to Aristotle: μετὰ λύπης γὰρ ἡ μάθησις), and whether we can find ways to teach and coach that break this dynamic. The use of games seems to be one approach, as they can offer a safe context for failure.

An introduction to Aikido, out by the river under the hornbeams as the sun went down.

Bring your Shadow to Work

Handrail and shadow

There‘s an idea in certain circles that we should be able to bring our whole selves to work.

There are aspects of this notion that I find unproblematically wonderful. For those of us who are invisible members of minority groups, the ability to drop the mask and be open about our identities can help us find a level of safety and inclusion at work.

There are areas that I find problematic, particularly questions about how permeable the work/life barrier should be. These are questions for another day.

The point I’m thinking about today is that there are aspects of all of us that are unpleasant. We think dark thoughts and entertain transgressive fantasies. These are parts of our whole self, but do we really want to bring them to work?

Carl Jung characterises this aspect of us as our Shadow, and sees our encounters with our Shadow as part of the way we Individuate ourselves. Repression and denial of the Shadow can lead to dysfunction: we can become overwhelmed by it and start Acting Out our fantasies, rather than enjoying them in the privacy of our mind.

So I find a tension here: being a psychologically healthy person requires us to have a healthy relationship with the dark areas of our minds, to admit these areas into our whole selves. But if we are to bring our whole selves to work, then we need to bring these dark areas to work as well.

This question becomes more pressing if we accept that there is a close relationship between our Shadow and our creativity. If we hope to do creative work, then we need to be able to dip our bucket into this dark well.

In this context, I read something interesting in an interview with Phoebe Waller-Bridge:

More than anything, she says, as a writer she wants to show women indulging their appetites and venting their grievances. “We sexualise women all the time in drama and TV. They are objectified. But an exploration of one woman’s creative desire is really exciting. She can be a nice person, but the darker corners of her mind are unusual and fucked up, because everyone’s are.” Has she always been able to say the unsayable? “Yes. As long as it feels truthful, as long as it’s pointing at the elephant, it is always exciting.” [Emphasis mine]

And this got me thinking again: Waller-Bridge is making quite a name for herself by bringing the darker corners of the mind, the Shadow, into her work. As a screenwriter this may be rather more straightforward than for a software developer, for example. But is there a way we can openly and honestly bring these aspects of ourselves to work? Is a truly psychologically safe workplace one where we can invite our Shadows?

Team Depression: a recipe for first aid

An interesting parallel occurred to me the other day during a conversation at work: the mood of a team is subject to changes, just as that of an individual, and sometimes depression can set in. So, just as we can learn techniques to fight of depression in ourselves, maybe we can do the same within our teams.

It became clear to me a few weeks ago that my team was in the doldrums: we had come to the end of several significant pieces of work, but had released this work with very little fanfare, which led to a feeling of deflation; furthermore, our future workload was both daunting in size and vague in scope, with few clear short-term goals, which gave us a sense of listlessness; in the past few months, several really talented team members had left us, and we hadn’t yet managed to to find a new dynamic for the team, so we had lost the buzz that comes when collaboration becomes second nature; finally, a raft of factors beyond our control meant that we kept finding our work blocked, which just added another layer of frustration.

I had recently taken on the role of team lead, which meant not only that these issues became a particular problem for me, but also that I had an opportunity as primus inter pares to do something about this. In working to find a way out of this morass, I came to a realisation: I had been here before, and I already knew how to deal with it.

A rich seam of depression runs through my family, and it has been part of my life since childhood. In the past few years I have pushed it into remission, and it rarely raises its head now. However, from time to time I do catch the onset of a spell of depression, and I have identified a set of first-aid techniques that I can use to stop it developing further. Many of these techniques—regular exercise and fresh air, early nights, cutting down on alcohol, making time to read and relax—seem simple and obvious, but these are just the habits that can get sidelined when depression sets in, so I have to treat them as a strict regime and push myself to follow them. The result of this is incredibly effectively for me.

Here are my key actions in fighting the signs of depression:

  • I have identified and look out for the early warning signs, so I know when I need to take action
  • When I spot these signs, I acknowledge that the situation warrants special behaviour, even if this means putting other priorities on hold
  • I have identified specific behaviours that I know help me recover
  • I stick with these behaviours until I am back on an even keel

This brings me back to my team’s situation. Of course, the ideal is to develop good everyday habits that keep depression at bay, but while we work on that, we may well find ourselves slipping into the doldrums occasionally. It seems to me that all four of these actions can apply to a team just as readily as to an individual.

I would be interested to hear other people’s experiences of dealing with lapses in team mood, as well as thoughts on how these ideas fit with various codified working patterns. Please share your ideas!