There are those day where I’m not sure why I bother writing. So I have tried—and failed—to provoke a discussion in this series of posts using quite a few words. Turns out, Simon Brown (of C4 Model fame) can do it in a single tweet:
While the discussion on my blog isn’t happening, I hope that this Twitter thread will trigger an interesting discussion and yield valuable insights.
As a software developer, software architect or anyone else who influences software, you’ll want to know about Ruth Malan. Ruth writes about software architecture and, particularly interesting, about visual design in the context of software architecture.
A while ago I was supporting a company that offered a digital platform to small and medium-sized business in a specific industry. Great people, interesting ideas — a very enjoyable experience.
This platform was composed of independent products which were connected only very loosely. Some of these products were also marketed to customers independently of this platform.
Greater flexibility, greater inconsistency, more duplication of effort
This approach provided great flexibility to the company and its partners, independence and perhaps even a friendly and good-natured competition of ideas and approaches. However, these products (or services) provided very different experiences to their users — in terms of visual design, but also in terms of interaction design, terminology, data structures etc..
This could be considered to be largely acceptable as users understood (at least to some degree) that different products were used by this platform, but a higher degree of consistency would likely have been appreciated by users. However, that company also experienced a higher degree of feature duplication than would have been acceptable in any of the initiatives I’ve worked before.
Trading consistency for team effectiveness and efficiency?
More cohesive platforms (products, services, applications, whatever), or platforms that are desired to be perceived as more cohesive by users, can be negatively impacted by much subtler inconsistencies than the ones I described above. Avoiding these inconsistencies while maintaining team effectiveness and team efficiency is what this discussion is all about.
There seems to be a broad consensus that many types of software are best built and developed by cross-functional, self-organizing teams with about five to nine members using lean and agile approaches. (There are types of software and problem domains that require different approaches or need to be supplemented by additional practices, for example in health and safety related domains. I don’t focus on these here.)
Much software requires more than a single team to build and run. At this point, a decision on how to shape these teams and which responsibilities they take on becomes necessary. This decisions will have a significant impact on how the teams work, on how they collaborate and communicate with each other, and on the results they produce.
Teams shaped by functional domain
The common approach seems to be to organize teams by feature or functional domain. In this case, the teams would cover the full technology stack from front-end via services and application down to databases, storage, integration and compute infrastructure. This is certainly better than organizing teams by software layer such as user interface, application logic, underlying domain logic, and the data access layer.
In an e-commerce context, one team might take responsibility for product browsing and selection while another team might be responsible for the checkout process. A third team might take responsibility for account maintenance.
This might look something like this:
This is not unreasonable when we look at a single web application — but it may not be without problems even in this limited case. Great care needs to be taken so ensure that the boundaries between these teams do not lead to observable boundaries between these features or functional domains. For example, we do not want the user interface to subtly change when moving from product selection to checkout. (Think Conway’s Law.)
Going further, how does this approach scale to different client apps and interfaces? What if we want to add an iOS app? An Android app? Plus a public API? And support for voice assistants?
Adding people with the necessary skills to the teams is likely to cause the teams to grow beyond a reasonable size (even if individual team members are skilled in multiple areas). And the problem of ensuring integrity in these client apps and interfaces multiplies with the number of apps and interfaces.
App teams and service teams
To me it seems beneficial to separate the responsibilities for the client apps and interfaces from the services (or components) providing functional capabilities (i.e. managing access to data, implementing calculations, or implementing a business interaction such as placing an order).
This might look like this:
This allows app teams to focus on their users, the context they live and work in, their needs and preferences. Ensuring experiential and structural integrity within a single app becomes easier. App teams can also develop deeper expertise in the app-specific technology stack (e.g. web front-end vs. native mobile front-end vs. API management infrastructure).
Similarly, teams taking responsibility for services (or components) in a functional area can develop deeper expertise in this functional domain (e.g. pricing, order fulfilment, or product configuration). These teams can also develop deeper expertise in their service-specific technology stack.
Broad and shallow vs. narrow and deep responsibilities
I view app teams as having broad yet shallow responsibilities while service teams have narrow yet deep responsibilities. This refers to the breadth of functional scope and the depth of the technology stack. (I do not imply that app developers are somehow less technically adept or that their work is less technically complex than that of service developers. But in order to display a price to a user I do not have to know how to determine that price. And in order to determine that price I do not have to know when and how to effectively display that price to a user.)
I envisage these broad app teams and the deep service teams like this:
This approach to organizing teams requires collaboration between the app and the service teams to design and evolve the service API. We replace informal collaboration between team members (e.g. those focused on the UI and those focused on service implementation) with formal cross-team collaboration on an interface. This collaboration on the interface also ‘pays’ for mitigating the risk of friction at the boundaries of different parts of each app.
In this context, I’m thinking more about data-centric services (probably with a fairly generic and perhaps somewhat coarse-grained interface) rather than fine-grained RPC-style functions dressed up as a not-quite-RESTful JSON-over-HTTP interface. This should lead to increased stability (i.e. reduced volatility) of the interface and simplified dependencies (i.e. coarse-grained rather than fine-grained dependencies).
This is not “separate teams per software layer” — I think
So, I’m not — at least I don’t think I am — naïvely advocating for removing the UI layer from the application component, and thus advocating for a minimal form of separate teams per software layer. Instead, I view the different client apps and public APIs as individual products. I think that these products need to be product-managed. Similarly, I view these underlying functional services as products. The sum of their interfaces form an API (potentially, an internal API) which I view as another product. These products need — and deserve — to be product-managed, too.
What’s wrong with this?
And now, considering that this approach does not seem to be widely discussed, the Gretchenfrage: What am I missing? Why doesn’t this make sense? What would be a better principle for organizing teams in such a setting? Why is the team-by-feature approach superior?
I typically work for medium-sized to large companies building B2C, B2B or B2E products. Building significant features or functional capabilities typically requires collaboration and alignment with multiple groups within in the company. Such capabilities often depend on additional systems beyond the team’s control. YMMV.
As a bonus, the diagrams in this post show clearly that there is a difference between a visual designer and a graphic designer. Ah, well…
Bob Marshall “didn’t sign up for all this people shit“. Neither did I. But like Bob — and Tom and Stuart and Ruth and Chris and Dave and so many others before me — I’ve come to realise that talking about the architecture of software-intensive systems might be distracting me from the core of the problem of building and running effective systems (although they haven’t phrased it in exactly these terms). Focusing on people and their needs might be a more effective approach. This is tough, at least for me, and I can fail at this in the most spectacular ways.
If a classification seems necessary, thinking of the architecture of people-intensive systems might be more useful to me than thinking of the architecture of software-intensive systems.
I’ve been struggling with the architecture of people-intensive systems more concretely:
In this post, Rob argues that we ought to consider our (hopefully ever improving) process of creating software as the primary product of our work rather than the software itself. In this sense, he argues that software is only a by-product of our work.
Interesting. I exchanged a few more tweets with Stuart in which he observed that “product” does not mean (physical) “good”. Indeed, services are products, too, both in a general sense and in the context of Rob’s blog post.
In my experience, clients still want to buy the results of the software process (e.g. an evolving web shop) rather than the collaborative design process yielding this result. This is despite the fact that software development processes and methods can be the subject of great debate at all phases of the sales and delivery process.
But herein might lie great opportunity: What if we could shift the conversation away from that by-product of our work to that collaborative design process that creates that seemingly auto-evolving web shop?