Authors: David Le, José Miguel Sánchez Martínez, Honza Moudrik
One of the benefits we enjoy at Mews is a strong learning culture, which includes a company-covered trip to a conference. So, we seized the opportunity to attend the Global Software Architecture Summit in the heart of sun-drenched Barcelona. What are our takeaways? What should modern software architects be mindful of? Let’s dive deep into these complex landscapes and explore the four topics that stood out most.
Navigating architectural seas through independent value streams
Let’s begin with the first valuable topic that strongly resonated with us, presented by Nick Tune: the buzzwordy paradigm of independent value streams, which software architects can use as a guiding compass in modern architectural approaches. This paradigm urges architects not to view software architecture in isolation but rather holistically, encompassing business domains and team organizations. When any of these three components are not well aligned, it can create friction, leading to slower feature development. You might have encountered this throughout your career – you need to introduce a new feature and end up touching multiple subdomains, some of which belong to other teams.
This leads us to the concept of a value stream, which references a sequence of steps that result in value for an end user. When these value streams are executed independently of each other, they enable teams to work in an agile way. Even though the topic is abstract, the presentation was filled with high-level techniques and heuristics that can pave the way to embracing this concept. Independent value streams revolve around a few key pillars:
- Domain aligned
Business domain boundaries play a crucial role in software architecture!
So, why do architects struggle to lay these domain boundaries correctly if they play such a crucial role? The answer to this question lies in a phrase that echoed throughout the entire conference:
There is no simple, one-size-fits-all flowchart that can be applied across all organizations. That is where great software architects shine, as they can effectively identify conceptual boundaries.
- Outcome oriented
As Nick said: “Modern architects know which business outcomes to optimize for and how each value stream contributes.”
Understanding the broader business context helps you make decisions more aligned with the company’s goals. Nick presented a visualization he has developed over time known as the Core Domain Chart, which maps out important pieces of the domain for better clarity on where to direct focus.
- Team empowered
It is no revelation that a skilled and motivated team is as crucial as having robust software architecture. To foster an autonomous working team within the product realm, Nick suggested utilizing John Cutler’s diagram for systematic team assessment. We were pleasantly surprised by the positioning of our team within this framework.
John Cutler’s diagram mapping out different team structures and approaches to collaboration, source: Journey to Product Teams.
- Software decoupled
Decoupled software is a significant enabler of overall robustness and quality. The key takeaway from Nick’s presentation is the emphasis on modern architects possessing a nuanced vocabulary for describing coupling and complexity, which enables them to distinguish an acceptable level of coupling in a system.
Defining architecture success with fitness functions
When discussing software architectures, a crucial and obvious question arises: how do we determine that one architecture is better than another? Does a certain decision bring us closer to what we want to achieve? When evolving the architecture of our system, we need to have a guiding principle to steer us in the right direction.
A fitness function offers exactly that, as Neal Ford defined in his talk:
“An architectural fitness function is any mechanism that provides an objective integrity assessment of some architectural characteristic(s).”
When first hearing about this concept, we anticipated a (very estimated) function that would output a single number. But, as some of you might have guessed, software architecture is not that straightforward. The best the industry has come up with is a collection of various separate characteristic goals that you look at in parallel, for example:
- Flatten components – If your goal is to have flat components, you may want to measure this by checking how deep your namespaces go. For example, if you have a class in ‘Reservations.Notification.Email` namespace, moving it to ‘Reservations.Notification` flattens the `Reservations` component, making your architecture more fitting.
- Component dependencies – If you want as few dependencies as possible, you may want to set a maximum limit: a component should have no more than five dependencies in total.
A very engaging real-life example of how a microservices architecture is measured was provided by Niklas Gustavsson, Chief Architect at Spotify. While their architecture spans thousands of components in production, they monitor:
- The number of lines of code in a component
- The number of components managed by a team
- The number of dependencies a component has on other components
- The daily count of successful deployments
Choosing these metrics is up to you and the architectural goals you have with your application. But it is essential to establish them and constantly (especially during rapid growth) reevaluate them. Otherwise, you are guide-less in your (d)evolution.
Bytesize architecture sessions
A particularly useful and applicable workshop technique was presented by Andrea Magnorsky. It can enhance an event storming or any workshop (virtual or IRL) where multiple participants have knowledge to share.
Here are a few steps to follow:
- Set a goal: For example, create a diagram of how a system currently works.
- Alone together: Allocate a time-boxed period (e.g., 10 mins) where each person solves the goal on their own and then explains their solution to the rest of the group.
- Consensus: The team creates a common solution based on what they have heard.
What’s great about this approach is that it captures various perspectives, resulting in a genuinely comprehensive body of knowledge. The differentiating factor is the “Alone Together” step, where extroverted and introverted participants – yes, archaic terms to use, but you get the point – have a very low threshold opportunity to shine and share their insights. The primary purpose here isn’t necessarily solving the goal but sharing knowledge, a crucial prerequisite for many things.
If you would like to learn more, including a more detailed step-by-step guide, take a look at bytesizearchitecturesessions.com.
Do you find the blog interesting?
Would you like to be the author of the next one at Mews R&D?
Dismantling monoliths: Microservices
Of course, one of the main topics covered during the conference was microservices and how to effectively migrate from a monolithic architecture to a microservices ecosystem.
When considering system architecture, some people want simple, black-and-white rules to guide their decisions, but those rules cannot cover all situations, and absolutism fails more often than not. Making decisions is a trade-off, and “it depends” is usually a valid answer to every question.
As there’s nothing worse than flip-flopping on decisions, we should also consider constraints as a way to narrow down choices, ultimately helping us reach conclusions.
The following simplified table taken from the talk “Effective Microservices: Lessons Learned” by Mark Richards can help us compare different architectures and decide which one better fits our needs:
If you’re creating something from scratch, one concept we found really interesting was evolutionary architecture. It states that building software should evolve as technologies, priorities, and customer requirements change.
On the other hand, if the goal is to split a monolithic architecture, despite this being a time-consuming process, we may also want some quick wins. That means we have to be conscientious when trading off the cost of extraction (of a certain part of the code) against the benefits of decomposition.
Before undertaking a task like this, it can be a good exercise to identify and size components, flatten them, analyze their dependencies (both incoming and outgoing), try to limit them in the future, and also create component domains.
Decomposition patterns like database-per-service pattern (taking all database tables and assigning ownership to services, creating a physical bounded context) or domain-data pattern (where more than one service can interact with the database storing all the coupled data, forming a broader physical bounded context) can help us in this regard.
In the end, we have to remember that “micro” does not refer to the number of classes or lines of code; it’s about what the services actually do.
Another interesting topic around microservices is coupling. As developers, we often only think about code-level coupling, but it goes far beyond that. As coupling is inherent to software design, we will never be able to get rid of it completely. The idea is to choose wisely the type and amount of coupling we are happy to live with.
The most memorable formula of the conference was “Vladik’s Magic Dependency Pain Formula”. It was featured in several talks and reminded us of the importance of managing and reducing dependencies in software design to minimize pain points.
Pain = Strength of coupling * Volatility * Distance
Coupling happens in three dimensions:
- Distance: Defines the coordination effort and the cost of change
- Volatility: Defines how often coupled components change
- Strength: Defines the cascading impact of changing something in one place. From the highest to the lowest level of shared knowledge, we can have:
- Intrusive coupling: Dependence on implementation
- Functional coupling: Implementing similar business-related functionality in two places
- Contract coupling: Components are integrated through an explicit contract
- Model coupling: Sharing a model
In the specific scenario of decomposing monoliths, we’re creating new types of coupling between the different microservices. As distance will always grow, we need to balance volatility and strength.
Even though software architecture is not the easiest topic to digest, we wanted to keep our blog post concise while covering a broad range of topics, hoping to ignite your spark of interest just like the conference did for each of us.
GSAS proved to be an inspiring gathering, filled with bright and knowledgeable people. As the presentations unfolded, one had the opportunity to connect more dots as the presentations referenced and built upon each other. The conference’s diversity of topics contributed to its engaging and multifaceted nature.
If you were to remember a single point from this blog post, we would urge you to make it this one – while there’s an abundance of tools and concepts to explore, it’s essential to remain pragmatic. Use everything judiciously, be aware of the trade-offs, and recognize that popularity does not equate to a holy grail.
P.S. If you want to see some of the talks, you can find them on the conference’s YouTube channel.