Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Software Architecture with Kotlin
Software Architecture with Kotlin

Software Architecture with Kotlin: Combine various architectural styles to create sustainable and scalable software solutions

Arrow left icon
Profile Icon Jason (Tsz Shun) Chow
Arrow right icon
€20.99 €23.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.3 (3 Ratings)
eBook Dec 2024 462 pages 1st Edition
eBook
€20.99 €23.99
Paperback
€29.99
Subscription
Free Trial
Renews at €18.99p/m
Arrow left icon
Profile Icon Jason (Tsz Shun) Chow
Arrow right icon
€20.99 €23.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.3 (3 Ratings)
eBook Dec 2024 462 pages 1st Edition
eBook
€20.99 €23.99
Paperback
€29.99
Subscription
Free Trial
Renews at €18.99p/m
eBook
€20.99 €23.99
Paperback
€29.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Product feature icon AI Assistant (beta) to help accelerate your learning
OR
Modal Close icon
Payment Processing...
tick Completed

Billing Address

Table of content icon View table of contents Preview book icon Preview Book

Software Architecture with Kotlin

The Essence of Software Architecture

Software architecture is the blueprint of a software system. It may not contain a single line of code but it describes how different structures work together so that systematic behaviors emerge from these structures, and thus the system serves its intended functions.

This is a book for those who wish to boost their architectural knowledge and mindset to solve daily engineering problems. In this chapter, we will discuss the essential values of software architecture and its position in an organization. We are going to cover the following topics:

  • The importance of software architecture
  • The role of an architect
  • Conway’s law
  • Choosing a framework
  • Documentation and diagrams

The importance of software architecture

Why should we bother with software architecture? In theory, a good engineer can simply jump into coding. Given time and effort, a software system can be produced to start functioning. This is a typical example of jumping to the result without extracting the value from the process.

A software system is a living entity that needs to adapt to the changes in the environment. Let us use a real-life example to illustrate this concept.

Real-life use case – community service exchange as a contract

In a village community, every household offers help to each other. One household’s members have certain skills lacking in another household. A member in household A is good at plumbing but not good at making clothes, while a member in household B is a tailor but the household needs pipes fixing.

So, household A offers to fix the pipes of household B in exchange for household B making clothes for a newborn baby in household A.

Each household uses bookkeeping software to keep records of the exchange of services in each household’s file. Each copy of the software in each household does not communicate with the other.

It works well for a while until some households have a dispute over what was agreed in their exchange of services. Both households claimed their records were correct in the software; however, the records in each copy of the software are slightly different. Since each copy of software does not communicate with the other, the dispute cannot be easily resolved.

One of the possible enhancements of the bookkeeping software would be to keep the records in a central data store so that households can view and agree on the details of the exchange of services before carrying out their services.

However, the bookkeeping software was written without architecture. All we have are lines and lines of codes, scattered in multiple files, and with some duplicated logic in multiple places. The code itself may be well-written and organized, but the original engineer has left the village, and the new engineer does not understand the rationale behind the code.

Software architecture as a means of communication

Software architecture is fundamentally a way of communication. Firstly, it defines what problems it solves in an abstract manner that stakeholders from non-engineering backgrounds can understand and reason about the software system.

Stakeholders use specific terms in describing the problem. Sometimes, different stakeholders use different terms that mean the same thing, or they might use the same term but mean different things. Engineers will also need to align with the terms and usage in the engineering structures. Software architecture acts as a common language and understanding so that all stakeholders and engineers can communicate with well-defined terms.

Usually, stakeholders make use of software architecture to integrate with their operation workflows. They may have other systems to interact with, or they need teams of people to work in various parts of the system. Software architecture becomes a visualization of the automated part of the workflow.

Software architecture as training materials

Secondly, software architecture provides an abstract view of how different structures work together and focuses on certain concerns at a time. A new engineer joining the team usually has a lot to learn to understand how the current system works. Source code is the ultimate source of truth; however, it could be laborious and time-consuming to read it all. Source code is usually cluttered with language syntax and layers of function invocations. Building up an understanding of the system from the code bottom-up is certainly possible, but it would take a long time.

Learning is much more effective with architectural documents that guide new members directly to the areas they care about. It is less overwhelming than source code, and it avoids engineers treating the bugs in code as the correct behaviors. New engineers can learn one aspect of the system at a time, with the aid of architectural documents.

Software architecture to manifest system quality attributes

System quality attributes, also known as system non-functional attributes, are the characteristics of a software system that define its overall behaviors, and operational and performance aspects. They are non-functional in that they are agnostic to the functional or business problems the system solves.

System quality attributes, such as availability, scalability, security, testability, extendability, and maintainability, are difficult to measure with only code. Software architecture provides at least one view to manifest each of these attributes so we can tune the system accordingly.

In the given example, the software could be lacking redundancy in the sense that each copy of the software stores the data in its own local storage and does not communicate with any other. If a copy has stopped working, the household would lose all data. Also, because each copy does not communicate with the other, there is no reliable way to guarantee that two households who exchanged services have the same records in their own software copies.

By having software architecture to describe the system attributes, engineers will be able to identify the issue and design a change to improve the given attributes. Moreover, it enables us to measure and monitor how these attributes change over time and correlate them with software changes. We are even able to project and predict these attributes when we plan a change to the current software architecture.

Software architecture as a change management tool

Usually, problems change and evolve over time. In the example, separated records of the exchange of services in each copy of the software were sufficient, as there was not a dispute. Software architecture provides a foundation for changes and enhancements. In many cases, different stakeholders have different priorities in their minds. Software architecture facilitates the discussion of how the system could evolve and at what cost, so the enhancement can be prioritized in order.

Also, with system attributes being described in software architecture, we can identify and mitigate risks since we understand which part of the architecture is being changed.

Software architecture as records of reusable solutions

Software architecture documents a series of concerns raised and decisions made. In the example of the bookkeeping software, since the original engineer has left the village, no one really knows the thinking process and why certain design choices were made at the time. It becomes very risky to enhance the system as no one knows the impact of changing one line of code. The idea of a central data store was planned and we are just one step behind it, or it was never designed to share data. We simply do not know.

This leaves us unable to safely improve the software, or even just to fix a bug. We might end up making the same mistake. We might misunderstand the original intent of the software and even create a bug. It becomes difficult to continue using the software if the problem evolves like the given example.

Software architecture acts as a set of records of decisions made to solve the problem. It explains the rationale of what drove the decisions and what factors were considered to make the choice. It also records any alternatives considered and why they were not eventually chosen.

Software architecture also identifies any constraint the system is bound to. It is important to include constraints because any new technological advancement may eliminate such constraints, such as new frameworks, and thus create new opportunities for improvement.

All this information provides solid ground if, one day, we decide to start a new system from scratch to solve the problem. We will not need to start from zero. We can start from what we have learned and the journey behind it. We can reuse a lot of the concepts from previous architecture if the context is applicable. We can significantly improve the next system with fewer constraints imposed on the previous system.

The role of a software architect

It may seem obvious that a software architect (the architect) is someone who creates software architecture. However, software architecture is the result of multi-dimensional thought processes that involve a lot of people. There is no single architect who would produce architecture alone and require no input from others.

It is important to point out that, although a software architect can be a job title in some organizations, the role of a software architect is not restricted to only someone who has the title.

Interface between engineers and stakeholders

Software architects align and translate the language used by engineers and non-technical people (the stakeholders). They facilitate communication using documentation and diagrams to illustrate key topics in the software system for discussion. There are variations in how the interface works between engineers and different stakeholders with the facilitation of software architects. We are going to explore these variations now.

Engineers and product managers

Software architects translate product requirements into technical designs. Engineers can do the same, but software architects apply a broader view in the sense of how certain implementations may impact system quality attributes. Software architects do not dictate the choice of implementation; however, they define non-functional requirements that predict system quality attributes. The non-functional requirements provide directions and constraints on the implementation.

In the example given previously, if a software architect were involved in the technical design process, they could have required the records of the exchange of service between neighbors to be replicated in both software copies and thus could have avoided the dispute of inconsistent records.

Software architects also take part in translating technical constraints, bugs, and implementations into information that product managers can digest and engage in. Software architects provide an abstract view of the code implementation to facilitate communication with product managers.

Imagine there is a new framework that facilitates two software copies to synchronize records of service exchange between neighbors, which permanently solves the dispute problem. Software architects can document this new approach and abstract the interaction to provide a foundation to discuss with product managers how this improves user experience.

Engineers and delivery managers

There is often tension when it comes to engineers developing features and delivery managers managing the timeline for when those features can be released. It is common for engineers to not deliver the full features in time. Software architects can facilitate the discussion of how the features may be delivered in phases and still be operational. In each phase, software architects determine the impact on system quality attributes and how users can operate in the meantime.

This is just an example of how software architects are involved when full features will not be available in time.

Regulators and compliance

Software systems, particularly in regulated industries, must address compliance concerns. The range is wide, and it may include the processing of personal data, auditing of persisted data, or complying with regulatory procedures.

Software architects are not only involved in designing an architecture that complies with regulations but also in illustrating how it was implemented. Regulatory bodies will examine technical documents, including architecture diagrams, as part of their due diligence process.

Security professionals

People who specialize in the fields of information security or cybersecurity work with software architects in multiple areas.

They provide security requirements in line with security policies, procedures, and guidelines. The requirements might include authentication, access control, and even the choice of encryption algorithms.

Software architects work with security analysts to perform threat modeling and risk assessment. They analyze the system architecture, identify vulnerabilities and risks, and discover potential attacks. The likeliness and impact of threats drive architectural choices.

Software architects may also work with penetration testers or ethical hackers to discover security holes and potential fixes.

Security architects collaborate with software architects to identify and choose the approach to address identified risks and meet security requirements.

Stakeholders

Stakeholders usually come from multiple departments of the organization, and they are likely to have different requirements and priorities for how the system is required to work. Software architects can navigate these tangled requirements and ensure that the system can fulfill these requirements in an agreed priority order.

Software architects also play the part of extracting common terms from multiple domain experts and stakeholders so the terms can be used in the architecture documents in a clear and unambiguous manner.

Balancing appropriate architecture and budget

While some software architects might be keen on having the most state-of-the-art technology and the latest and the fastest, realistically, they are more balanced with the budget the organization can afford.

Financial constraints on technology choice do not necessarily result in bad architecture; on the contrary, they encourage software architects to find more cost-effective ways to solve problems, and they could lead to a leaner and simpler architecture. If two architectures can address an identical set of concerns, the simpler and cheaper one is always better.

The decision of whether to buy or build is often affected by multiple factors, and the technical factor is only one of them. Although software architects may not have the power to decide which way to go, they provide technical and operational analysis so the organization can make an informed choice.

When the organization cannot afford the most technically sound system or service, software architects are there to bring out compromise, trade-offs, and impact analysis for the “second-class solution.” It may seem not ideal initially, but software architects can design the system in a way that leaves room for enhancement and expansion in the future.

Vision and roadmap to technical evolution

Legacy systems are outdated software systems that are still in use by the organization. They are legacy because their technology has very little room for improvement, and it is likely at least a few years backward.

There are systems that became legacy due to external factors such as discontinued technology support and severe limitations. And there are no feasible or cost-effective ways to evolve.

Legacy systems can also be the result of the lack of technical vision and roadmaps, in which software architects are heavily involved. Some small start-ups may not have someone taking the role of software architect, or there is no one championing software architecture continuously. These can all be reasons for systems to become legacy.

However, software architects can still jump in at any point to modernize the current architecture. They start by understanding what the current system does and what the organization really needs. Then, they decompose the system into autonomous parts, modernize them individually, and recombine them in a separate way so the whole technical ecosystem can be up to date again.

Usually, a technical vision includes inspiration in achieving a software architecture that manifests certain system quality attributes, such as highly available and scalable systems. While a technical roadmap includes small steps to achieve short- to medium-term goals, and some more dramatic changes to long-term goals, it requires meticulous planning and thought toward how the system evolves. Also, the technical roadmap must interact with the external technological evolution to pivot and adapt to a better alternative.

Cross-cutting concerns in a technical ecosystem

Cross-cutting concerns are typically the concerns that require multiple software components to work together to derive the desired outcome.

One example can be standardizing logging messages so they can facilitate cross-service log searches.

Engineers are often divided into teams and each team looks after a certain area of business. They do not necessarily have the bandwidth to ensure that services in other teams conform to the same convention to achieve cross-cutting outcomes.

Software architects engage these cross-cutting concerns in a holistic manner. They consult, engage, and discuss with multiple teams to form a consensus or convention so cross-cutting concerns can be addressed.

Software architects also drive common infrastructures, frameworks, and tooling to address these cross-cutting concerns. These concerns are closely related to the system quality attributes.

Let us say there are multiple services that need to communicate with each other, and REST endpoints are chosen to be the way of communication. However, without establishing standards among teams, the system quickly falls into a collection of inconsistent APIs. The URI resource hierarchy can be inconsistent, as can the error response payload. All these impact the maintainability and reusability of the system.

Software architects can be involved in understanding each team’s requirements and their concerns about using REST endpoints. Then, a guideline of REST endpoints can be created so that there is a pattern that engineers align with. A typical example would be to define a general payload structure for error responses to contain information in addition to the HTTP response status:

{
     "resource": "/users/32039/address/0",
     "shortMessage": "first line of address must be present",
     "longMessage": "A valid address must contain the first line",
     "details": {
           "addressLine1": null,
           "city": "London",
           "postCode": "EC12 10ED",
     }
}

This sample payload represents an error of an address input; it contains general fields such as resource, shortMessage, and longMessage that every service can conform to, while also having a details section to be customized by each service.

By having this standard, we can achieve overall observability of these errors and persist them in a universal format for audit purposes. Engineers can reuse this structure to reduce the time needed to develop a new REST endpoint. Engineers will also find it easier to maintain a REST endpoint even if it was developed by other engineers.

In a sense, standardizing the REST error payload has addressed the cross-cutting concerns of observability, auditability, maintainability, and reusability in the whole technical ecosystem.

Conway’s law

Conway’s law is an observation that the system design of an organization mirrors the organizational structure. A computer programmer called Melvin Conway introduced this idea in 1967, and his original wording is as follows:

“Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.”

In the context of software systems, software architecture mirrors the organization structure. The classic example can be illustrated in this diagram:

Figure 1.1 – A company organized by skill set

Figure 1.1 – A company organized by skill set

The company has a backend engineering (BE) team, a frontend engineering (BE) team, and a database engineering (DE) team. This organization groups people by their skill set. Everyone in a team is responsible for all business functions. This structure is likely to produce a monolithic system, which usually manifests in a single source code repository or one single logical process.

Figure 1.2 – A company organized by business functions

Figure 1.2 – A company organized by business functions

The organization in Figure 1.2 groups people by their business functions. So, everyone in a team is responsible for a designated business function, but each member may not have the same skill set. This structure is likely to produce a modular system, which contains multiple logical processes that interact with each other. Usually, there are dedicated source code repositories for each team.

Systems scale better when the team size is small because the number of communication channels required for people to talk to each other is n (n – 1) / 2 so it is exponentially scaled up. Jeff Bezos from Amazon proposed his two-pizza rule:

“If you can’t feed your team with two large pizzas in a meeting, you’re in trouble.”

So, if teams cannot be too big to scale the organization as well as the system, then it usually ends up with many teams. This resonates a lot with the architectural concepts we will cover very soon.

On the other hand, despite best efforts in modernizing the architecture of a legacy system, if the organization structure refuses to align with it, it is likely that the new architecture will eventually fall back to its old habitual structure.

This is something that should be solved by engineering management and upward. It is beyond what software architects can solve. However, it is worth understanding this phenomenon so the issue can be escalated as soon as possible.

Some big organizations found it extremely difficult to change their structures. And they even created start-up companies to run with modern organization structures alongside modern software architecture.

Choosing a software framework

A software framework (a framework), or a software development framework, is a standardized set of tools that aim to solve certain problems by consistent approaches.

A software system typically needs quite a few frameworks, so that they can focus on the business functions instead of lower-level concerns such as logging, JSON transformation, and configuration management. These frameworks provide a proven way to achieve the target software architecture. Choosing a framework is a part of architectural decision-making.

It is rare that organizations build every framework themselves these days. The major reason is that most of the frameworks are open-sourced and supported by the community. It would take a lot of justifications for an organization to decide to develop its own framework while there are similar competing frameworks that can be used for free.

Some technology companies develop their own frameworks when there are no existing ones that suit their needs. Some companies develop their own frameworks with the intent to compete with the other frameworks, and to potentially monetize from consulting business or to cross-sell their other products. It would take a lot of research effort and talent to achieve that.

The other option would be to choose a framework that already exists in the market, commercial or open-sourced.

The new framework paradox

New frameworks are released every month with the intent to solve the age-old problems of existing frameworks. Usually, there are one or two popular frameworks on the market, and the new frameworks advertise that they solved the old ones with an approach that everyone has always wanted.

Of course, there are true paradigm-shifting new frameworks that made engineers more productive and really have moved the industry forward with an innovative approach. For example, Ruby on Rails has transformed the repetitive and boilerplate code configuration of web development into inference and conventions, hence vastly reducing the number of lines of code.

But there are also a lot of cases where the new frameworks started with innovative approaches that did not go too well. And here comes the new framework paradox.

If a new framework aims to replace a framework that has been around for many years, the new framework will need to cover a lot of areas and keep the “new approach” in each area. This is a huge undertaking for the contributors.

For example, the Spring frameworks were created in 2002 to simplify dependencies of code by using Dependency Injection (DI) and Inversion of Control (IOC). But now, the frameworks have evolved to cover an extensive range of features, such as web, messaging, security, persistence, and so on. A next-generation framework to replace Spring frameworks would have to cover over 20 years of development, with a very comprehensive coverage of technical areas.

The most significant risk is that the new framework may have solved one of the longest-standing problems of a framework but it falls short of the areas that are fundamental and essential. It traps the engineers who adopt the new framework and makes them face the dilemma of whether to fix the new framework or return to the old one.

Another risk is that the community may not agree on what the “new approach” should be, and therefore, multiple new frameworks are created to solve the same age-old problem of the old framework. Engineers who want to try a new framework face the choice overload problem. And sometimes, it becomes a choice paralysis as there is no single definitively better choice to choose from.

Let us say your team has chosen a framework and everyone is quite happy with it. However, for whatever reason, the major contributor has decided to not work on this project anymore. Then, your team is at risk of the framework not being kept up to date with the fixes and planned enhancements. Not to mention that most open-sourced frameworks are contributed by normal engineers who spend their personal time for free on this.

How to compare and decide between software frameworks

However, in a real situation, the team would still need to choose some frameworks to move forward. An example situation would be a framework for logging messages for a Java application. Do we use the Java Logging framework that comes with the standard Java Development Kit (JDK), Apache Log4J, or Logback? How could we make the most sensible choice? Unfortunately, there are no golden rules that guarantee the best choice, but there are several aspects that the team should consider before making the decision.

Community

Community is the most crucial factor in your consideration. People are the reasons the framework is created, used, and maintained. Without people, the framework will not continue. There are at least three areas of the community for the framework to look for:

  • Firstly, the bigger the community, the more likely the framework will have someone to continuously support and enhance the framework. A framework should be like a living being, powered by the people in the community. Also, reasons for having a large community for a framework are likely that the framework is universally applicable and of acceptable quality for general usage.
  • Secondly, we need to look at how well the framework is supported by the community. It could be as simple as getting help from another user on how to use the framework. It could also be the quality and quantity of technical blogs written by the members of the community to share their tips on how to apply the framework to problems. It could be measured by suggestions the community made for new features and enhancements.
  • Thirdly, we need to see how the members of the community communicate with each other. Do they have a Slack channel, a Discord server, an email distribution list, or any instant messaging platform? How responsive are the members of the community when people post their questions out there? Are the people helpful and positive in receiving feedback?

Contribution

Every commit to the source code repository made up the framework the way it is now. It is worth checking some statistics to understand how actively the framework is being maintained.

When was the last commit? Was it recently updated? How many commits have been made so far? Also, we can check the number of commits in the last month, the last 6 months, or the last year. Moreover, we can look at the variety of contributors. A good sign is that the commits are done by a variety of contributors, not only the usual ones. It indicates a diverse and healthy growth from contributors putting their efforts into the framework.

How many forks and branches are there? Bigger numbers usually indicate healthy growth that either some members of the community are working on a change or there could be a variant of the framework soon. It is likely that there are useful features already in the code base that people are willing to spend their effort on.

The number of tags indicates historical releases and may give a hint about the evolution and growth of the framework. However, be careful of versions under 1.0 (e.g., 0.67), or simply just build numbers. The contributors in this case may not want to commit to the current shape of the framework, and there may be breaking changes in the future.

Versions under 1.0 also could mean contributors may not have confirmed their commitment to keep the framework running for long yet. Extra caution must be taken if you intend to put a 0.x library dependency in your production system. It is going to be difficult if the library discontinues or introduces breaking changes.

We should also look at the source code and get an impression of the code’s quality and test cases. We should glance at the test coverage to understand how deep and broad the code was tested. This would help us predict the reliability and stability of the framework.

Tooling and documentation

We should also consider whether the framework uses mature tooling to manage itself. It may include an issue tracking system that members of the community can submit bugs and track how long it takes for a bug to go from reported to fixed.

The framework may also use an established Continuous Integration (CI) system. This is also a good sign of a healthy, long-running, and mature framework since there is a need to automate builds to handle the number of commits, control the quality, and release the framework.

Documentation is a key factor to consider since this is where engineers learn how to use the framework. The documentation does not necessarily need to be polished or automatically generated. It is the quality of the content that matters. And diagrams would be nice if they help engineers understand the concepts.

Interoperability with other frameworks

Many frameworks were designed to work with other frameworks, and some of them have innate dependencies on other frameworks. This is common and not a bad sign; however, caution must be taken on the impact.

Adopting a framework that uses or works with another framework implies we are also indirectly adopting the other framework. Is the other framework compatible with the engineering approach the team has taken? Do we allow engineers in the team to use the transitive dependencies directly in the code?

Even if we are OK with the other framework, we still need to ensure that the versions are compatible. For example, framework A may have used the Apache Commons IO library, version 2.14.0, and our project currently uses 1.4. Importing framework A to our project would bring version 2.14.0 as a dependency to the project. Luckily, build frameworks such as Gradle and Maven provide a graceful way to explicitly specify a version and exclude a particular version from the transitive dependency. In this example, we will upgrade our dependency on Apache Commons IO to 2.14.0 from 1.4 to use framework A.

Building instead of choosing a framework

Engineers might want to build their own framework instead of choosing an existing one. Under certain conditions, this could be beneficial.

If the software has unique requirements that cannot be met by existing frameworks, then it would justify building a bespoke framework. It could be a very specific domain, or it could have very strict non-functional requirements. For instance, engineers for High-Frequency Trading (HFT) software might write their own framework to meet ultra-low-latency requirements.

Building a bespoke proprietary framework might also be justified if the organization treats it as a competitive advantage in the market with cutting-edge technology.

It may also be the start of a new open-sourced framework in the community if no such framework has existed before. In this case, it may be beneficial to gather engineering talents among the communities and collaborate.

What if we made the wrong choice?

Despite all our best efforts, we might still have chosen the wrong framework. The framework may not have delivered the intended behaviors. The contributors may have given up on the project. The framework may have taken a novel approach that no longer suits our needs.

The adoption of the wrong framework becomes technical debt. Unfortunately, we need to source a replacement framework and plan the refactoring works to remove this dependency.

The technique of refactoring is beyond the scope of this book, though. And it is not always possible to avoid choosing the wrong framework. All we can do is exercise our due diligence in the process of decision. If appropriate, we can also create interfaces so that only minimal classes in the code base have direct reference to the framework, while the framework usage to the rest of the code base is transparent.

Documentation and diagrams

Software architecture as a blueprint of the system is captured in documentation and diagrams. Some of them could be captured in configuration files and templates, but when software architects need to present the system or communicate with stakeholders, documentation and diagrams are still the most used formats. Some of these diagrams will be used in upcoming chapters.

Business Process Model and Notation

Software systems, at a high level, can be seen as automated business processes that can be visualized in diagrams. Business Process Model and Notation (BPMN) standardizes graphical notations and provides a common language for modeling business processes. It is commonly used among engineers and stakeholders for communication and documentation purposes.

Taking the example of two households coming to a mutual agreement on the contract of services they exchange (the service contract), the business process could be modeled as follows:

Figure 1.3 – Example of a BPMN diagram

Figure 1.3 – Example of a BPMN diagram

Household A and Household B have their own swimlanes to illustrate the process on each side. Household A submits a draft of the service contract and Household B receives it. Household B reviews the draft and submits its decision. If Household B rejects the service contract, then both processes at Household A and Household B end. Otherwise, Household B waits for Household A’s response; meanwhile, Household A records the service contract, and the process ends. Finally, Household B receives the service contract from Household A and records the service contract, and the process ends.

BPMN has a rich collection of notations to describe business processes. They can be categorized into four groups.

Flow objects – activities, events, and gateways

Activities can be tasks and sub-processes that happen in the business process. Events are outcomes that have happened. Gateways are the points where a decision is made or the process splits into branches.

Connecting objects – sequences and associations

Sequences illustrate the flow of control and the messages communicated among flow objects. Associations describe the relationship among objects, such as inputs, outputs, or dependencies.

Swimlanes

Swimlanes are the groupings of flow and connecting objects based on the roles and responsibilities of participants involved in the business process.

Artifacts

Artifacts are additional information to the diagrams, and they provide context such as the data objects involved or simply free-text annotations.

Architecture decision record

Software architecture can be seen as a journey from problem discovery to solution implementation. Along the journey, there are a lot of decisions made to move the system forward. An Architecture Decision Record (ADR) is a document that captures the decision made based on the context at that time and the consequences coming with it.

There are many ADR templates available on the internet, which conceptually cover the following sections.

Status

This is typically just a single word to describe the current state of the ADR in the process. Here is an example of the ADR process:

Figure 1.4 – An example of the ADR process

Figure 1.4 – An example of the ADR process

The basic possible states are Proposed, Accepted, and Rejected. In this example, there are other states, such as Under Review and Changes Required. It varies from one organization to another.

Context

This section should introduce the background where the discussions started. A good introduction would bring the needs of the change to the current situation e.g., pain points of the current operations, organization restructuring, business expansion, etc.).

It also introduces the terms that are used throughout the discussion so they can be easily referred to without ambiguity. A bit of the current organizational structure and technical infrastructure would also be helpful.

If applicable, this section can mention the current system quality attributes and why we want to change them. For instance, if our system can only handle 100 concurrent logins and the company wants to support 10,000 in the new technical design, then scalability is the system attribute this ADR proposes to change.

It should also mention the desired outcomes. This sets up a target state we want our change to achieve. The motivation here should refer to the problems mentioned previously and elaborate on how the outcome could improve business results.

Decision

This section describes the proposed change in detail. It should focus on how the change would produce the desired outcome described in the previous section. It may also mention the concerns raised and how the decision was driven by the discussion.

In some cases, alternative changes are mentioned. If they are mentioned, there should be a comparison between the proposed change and the alternatives. One way to compare is to list the pros and cons of each option. Another way could be to compare each option against a list of factors and conclude why an option is proposed.

Consequences

This section describes the impact of choosing the proposed change. Does it change the way the team operates? Which system attribute would it change and how? Does it optimize one aspect of the system but sacrifice another aspect? Which part of the system may become obsolete?

Request for Comments

Request for Comments (RFC) is a series of documents in which standards, protocols, procedures, and guidelines are proposed, discussed, agreed, and defined. Internet Engineering Task Force (IETF), a standard development organization (SDO), defined the numerous significant standards for the internet via the RFC processes, such as Internet Protocol (IP) version 4 (RFC 791) and 6 (RFC 2460), and Hypertext Transfer Protocol (HTTP) version 1.1 (RFC 2616).

RFCs can be submitted by anyone, and anyone is allowed to comment on existing RFCs. They go through an iterative review and feedback process in an open and transparent manner. They are usually initiated by subject experts but are maintained by the wider community. The outcome of an RFC can be standards and protocols adopted by the industry, which are useful for framework extension, further research, or the basis for the next RFC.

The format of an RFC document varies among organizations. In general, the document should cover the following sections.

Status

There are several possible statuses: Drafted, Collecting Feedback, Accepted, Rejected, and Abandoned.

Figure 1.5 – An example of the RFC process

Figure 1.5 – An example of the RFC process

Once an RFC is drafted, it goes through a review and feedback iterative process. The RFC exits the iteration when it is either accepted, rejected, or abandoned.

Context

This section explains the need to submit this RFC. An example may be presented to illustrate the need for standardization or the problems caused by the lack of consistent protocols.

Approach

This section explains the approach agreed with the community after the review-feedback process. It should be as detailed as possible to capture the consensus of the approach.

Pros and cons

The benefits and drawbacks of the approach should be covered in detail so that it is clear to the community whether there should be another round of feedback collection, or at least the community is informed about the consequences of the approach.

Alternatives

This section mentions any alternative approach that was considered and discussed, but not adopted.

References

This section includes any previous RFCs mentioned, an academic paper, or any additional materials that give more context to the discussion.

Update log

As an RFC is likely to result in a lengthy review-feedback process, an update log is useful in keeping each meaningful change of the RFC in chronological order.

RFC and ADR

RFC and ADR share many similarities in their document formats, but they are also different in terms of usage. RFC focuses on industry standards and protocols among large communities, while ADR focuses on conventions within an organization. RFC tends to be closer to best practices, while ADR tends to be closer to solutions and code.

Despite the difference, RFC and ADR can work in collaboration. For topics that require consensus, expect long discussion, or have significant impacts, an RFC can be written first to come to an agreement on the approach. Then, an ADR can be written as a record of the decision and as a detailed technical specification of the approach.

UML diagrams

Unified Modeling Language (UML) is a software modeling language standardized from different modeling languages and notations since 1994. UML 1.0 was adopted as a standard by an international standards consortium called the Object Management Group (OMG) in 1997.

UML has a diverse collection of well-defined software elements that can form various diagrams that help engineers model business problems in a structural and visual manner. There are 14 UML diagrams, grouped into two categories.

Structural diagrams

Structural diagrams represent the static structure of a system. They focus on elements such as classes, objects, components, and packages. They emphasize how these elements are organized and connected with each other in a system. The following diagram is an example of a class diagram:

Figure 1.6 – An example of a UML class diagram

Figure 1.6 – An example of a UML class diagram

A class diagram usually contains classes and interfaces. Each class can contain a few attributes and a few functions. For example, the ServiceContract class has three attributes: agreedDate, received, and provided. The class also has one function, isContractConcluded, that returns a boolean value. The received and provided fields of the ServiceContract class references the other class, Service. We could say the multiplicity of the ServiceContract class to the Service class is one-to-two, as depicted in the diagram.

From the business perspective, a ServiceContract class is a contract of exchanged services modeled as two instances of the Service class: one is a received service and the other is a provided service. If the contract is mutually agreed, then the agreedDate field should capture the time when it was agreed.

There are seven UML structural diagrams, and there is a specific use for each, depending on which element is under the spotlight:

  • Class diagrams, as illustrated, depict the static structure of classes, and their attributes, functions, and relationships with other classes.
  • Object diagrams visualize the instances of classes and their relationships at a point in time, usually from a real-life example, to represent a snapshot of the system runtime structure.
  • Package diagrams show how classes and components are organized into packages and the relationship among packages.
  • Component diagrams represent the high-level logical or physical components that make up a system and their relationships.
  • Deployment diagrams depict the software components physically deployed to hardware infrastructure and their connections to other physical nodes.
  • Composite structure diagrams describe the internal structure of a class or a component, with a focus on how the internal fields and functions collaborate.
  • Profile diagrams are extensible and customized diagrams that combine other UML diagrams. They facilitate UML language being extended to be domain-specific.

Behavioral diagrams

Behavioral diagrams represent the dynamic interactions of a system. They include elements such as actors, messages, activities, states, and transitions. The key focus in these diagrams is how the system’s behavior emerges from the flow of control, interactions, or state transitions. The following is an example of a state diagram:

,

Figure 1.7 – Example of a UML state machine diagram

Figure 1.7 – Example of a UML state machine diagram

This state machine diagram describes the life cycle of a service contract between two households. It begins with the submission of a service contract drafted by one household. Then, while the service contract is under review, the service contract can be amended by either household, until it is either rejected or mutually agreed. Afterward, the service contract may still be withdrawn. Otherwise, the households involved exercise the services in the contract until both services are exercised and the service contract reaches the end of the life cycle.

There are seven UML behavioral diagrams. It is technically possible to use any of them to describe the same system behavior. The difference is the aspect of the behaviors shown in the diagram:

  • State machine diagrams, as visualized, model how the system responds differently in each state and how the state transitions from one to another.
  • Communication diagrams, also known as collaboration diagrams, emphasize the messages exchanged between objects or components.
  • Activity diagrams represent a business or operational workflow of a component in a system as a sequence.
  • Interaction overview diagrams represent a business or operational workflow of a component in a system, with a focus on interactions among components in a system.
  • Sequence diagrams visualize the messages exchanged between objects and components in chronological order.
  • Timing diagrams visualize the messages exchanged between objects and components within a period with a focus on time constraints and the ordering of events.
  • Use case diagrams capture the interactions between actors and the system. Actors can be users or external systems, so actors can achieve their goals through the functions of the system.

The C4 model

The C4 model is a visual modeling approach developed in the 2010s. This approach originated from the observation that many software architecture diagrams were either lacking details (too high level) or overwhelmed with details (too low level). This approach aims to provide a set of guidelines and conventions to document architectures at the right level of abstraction.

It gained popularity over time among software architects and engineers who wanted a simple and effective way to document their systems. The Structurizr tool was developed by the C4 model creator, Simon Brown, to allow the creation of architecture models as code.

The C4 model can be described using the metaphor of maps: from a street view, where we could see pedestrians and cars on the roads, then zoom out to see a city map of how the main roads are connected in the city, then zoom out to see a country map, where we see the main cities and towns of the country, then to the world map, where we see the Earth.

The C4 model has four levels of abstraction. Each level helps different people to communicate and collaborate with the subject in question highlighted. It is helpful to bring up the right diagram in a meeting or workshop to start a conversation.

Level 1 – System context diagram

The system context diagram is the “big picture” diagram, and the major focus is the “system.” The diagram should be centered around the system, and it interacts with actors, business operations, and external systems. This diagram is particularly useful for communication with non-technical stakeholders and external organizations.

Figure 1.8 – An example of a system context diagram (C4 level 1)

Figure 1.8 – An example of a system context diagram (C4 level 1)

The Community Service Exchange software is a standalone software installed as an isolated copy in each household. The copies of the software do not communicate with each other.

Level 2 – Container diagram

The container diagram zooms in on the “system” and focuses on how multiple containers inside the system work together. Each container here refers to a deployable process and has its own role, responsibility, and boundary in the system.

The container diagram can also be used to illustrate any middleware or infrastructure used in the system, such as messaging brokers, data stores, or filesystems.

This diagram is useful for communication with technical stakeholders such as platform engineers, database administrators, network engineers, or security engineers.

Figure 1.9 – An example of a container diagram (C4 level 2)

Figure 1.9 – An example of a container diagram (C4 level 2)

The Community Service Exchange software contains a module to organize all the static content such as images and fonts. There is an application module to validate data and run checks. The application module uses the relational database to persist the data required. The application module also retrieves report data from the relational database and exports it to the filesystem. The household can read the report file from the filesystem.

Level 3 – Component diagram

The component diagram zooms in a container and provides a view of how different components constitute a container.

It describes the input to the component (e.g., REST endpoints, message consumers, or a scheduler) and the output from the component (e.g., events, response to a request, etc.).

Another important function of this diagram is to demonstrate the logical packages inside the container that serve business operations. They typically load, transform, combine, and compute functions on multiple representations of entities modeled for the business purpose.

This diagram is closer to the software engineers, so they understand the context where they write code and scripts.

Figure 1.10 – An example of a component diagram (C4 level 3)

Figure 1.10 – An example of a component diagram (C4 level 3)

The application module of the Community Service Exchange software has a service exchange controller that operates a service contract (the “contract”) between two households. It is business logic that manages the life cycle of a contract from the beginning till the end. It passes the contracts to the service exchange repository for persistence logic such as translating the contract entities into database tables and columns.

On the other hand, the file export controller serves a request from the household to generate a report of the contracts the household was involved in. The file export controller validates the request and generates the file ready to be available in the filesystem, which is outside of this application module. There is part of the statistical data on the contracts, and the calculations are done by the service statistic calculator.

Level 4 – Code diagram

Finally, we come to the lowest level of abstraction – the code diagram. This is a microscopic view of a component for engineers to understand the design patterns used, and how source code is represented in an abstract view in relation to other source files.

We could describe the entities modeled in the component and the relationship among them. That can be translated into a relational database schema.

We could be describing a process that involves multiple classes in the object-oriented style. We could demonstrate the fields captured in each class and how classes interact with each other.

It is not mandatory to have a code diagram for every part of the system because simple logic can be expressed directly in the source code. Typically, code diagrams are used to capture more complex interactions so engineers can be mindful when they are coding. This is also where you will see UML diagrams.

Figure 1.11 – An example of a code diagram (C4 level 4)

Figure 1.11 – An example of a code diagram (C4 level 4)

Inside ServiceExchangeController, there is a data class called Household that contains a list of HouseholdMember objects. The HouseholdMember data class models a household member who has the skills to execute a contract.

There is a Service class that captures the execution details of a contract from a household. It provides an isExecuted function that returns a Boolean value of true if its executedBy and executedAt fields are both not null.

The ServiceContract class models a service contract between two Service objects. It captures the date when the contract was agreed by both households. The receiver and the provider of the contract is a Service object. It provides an isContractConcluded function that returns a Boolean value of true if the result of the isExecuted function from both objects returns true.

Summary

We have covered the importance of software architecture with a real-world example. We discussed how software architecture plays a role in communication, training, budgeting, defining visions, and addressing cross-cutting concerns in the technology ecosystems.

We have discussed Conway’s law and how the structure of an organization affects the architecture of systems.

We have navigated the topic of choosing a software framework in multiple scenarios with pros and cons.

We have also covered the documentation and diagrams that are often used in software architecture, such as ADRs, RFC, UML diagrams, and the C4 model.

In the next chapter, we will introduce some fundamental architectural principles that drive modern software architecture. We will break down and combine multiple concepts and illustrate them with the same real-world example.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Learn how to analyze and dissect various architectural styles into building blocks
  • Combine existing ideas with your own to create custom solutions
  • Make informed decisions by navigating trade-offs and compromises
  • Purchase of the print or Kindle book includes a free PDF eBook

Description

Software Architecture with Kotlin explores the various styles of software architecture with a focus on using the Kotlin programming language. The author draws on their 20+ years of industry experience in developing large-scale enterprise distributed systems to help you grasp the principles, practices, and patterns that shape the architectural landscape of modern software systems. The book establishes a strong foundation in software architecture, explaining key concepts such as architectural qualities and principles, before teaching you how architectural decisions impact the quality of a system, such as scalability, reliability, and extendability. The chapters address modern architecture topics such as microservices, serverless, and event-driven architectures, providing insights into the challenges and trade-offs involved in adopting these architectural styles. You’ll also discover practical tools that’ll help you make informed decisions and mitigate risks. All architectural patterns in this book are demonstrated using Kotlin. By the end of this book, you’ll have gained practical expertise by using real-world examples, along with a solid understanding of Kotlin, to become a more proficient and impactful software architect.

Who is this book for?

This book is for developers with basic Kotlin knowledge seeking a deeper understanding of architecture, Kotlin Android developers who are starting to get involved in backend development, and Java developers transitioning to Kotlin. It's also ideal for software architects who are less experienced in Kotlin and want to enhance their skills, as well as those who enjoy discussing and exploring unique architectural concepts.

What you will learn

  • Master the fundamental principles of architecture and design
  • Explore common architectural styles and their applicable scenarios
  • Analyze, break down, compare, and design architectural styles to solve practical problems
  • Reason, negotiate, and make difficult choices in the absence of ideal solutions
  • Mitigate risks when making compromises and trade-offs
  • Create scalable, sustainable, maintainable, and extendable software systems
  • Use the Kotlin programming language to achieve your architectural goals

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Dec 31, 2024
Length: 462 pages
Edition : 1st
Language : English
ISBN-13 : 9781835464960
Category :
Languages :

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Product feature icon AI Assistant (beta) to help accelerate your learning
OR
Modal Close icon
Payment Processing...
tick Completed

Billing Address

Product Details

Publication date : Dec 31, 2024
Length: 462 pages
Edition : 1st
Language : English
ISBN-13 : 9781835464960
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Table of Contents

17 Chapters
Chapter 1: The Essence of Software Architecture Chevron down icon Chevron up icon
Chapter 2: Principles of Software Architecture Chevron down icon Chevron up icon
Chapter 3: Polymorphism and Alternatives Chevron down icon Chevron up icon
Chapter 4: Peer-to-Peer and Client-Server Architecture Chevron down icon Chevron up icon
Chapter 5: Exploring MVC, MVP, and MVVM Chevron down icon Chevron up icon
Chapter 6: Microservices, Serverless, and Microfrontends Chevron down icon Chevron up icon
Chapter 7: Modular and Layered Architectures Chevron down icon Chevron up icon
Chapter 8: Domain-Driven Design (DDD) Chevron down icon Chevron up icon
Chapter 9: Event Sourcing and CQRS Chevron down icon Chevron up icon
Chapter 10: Idempotency, Replication, and Recovery Models Chevron down icon Chevron up icon
Chapter 11: Auditing and Monitoring Models Chevron down icon Chevron up icon
Chapter 12: Performance and Scalability Chevron down icon Chevron up icon
Chapter 13: Testing Chevron down icon Chevron up icon
Chapter 14: Security Chevron down icon Chevron up icon
Chapter 15: Beyond Architecture Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.3
(3 Ratings)
5 star 33.3%
4 star 66.7%
3 star 0%
2 star 0%
1 star 0%
Tiny Feb 05, 2025
Full star icon Full star icon Full star icon Full star icon Full star icon 5
The book provides an excellent overview of software architecture combined with Kotlin examples. If you currently use Kotlin, this can certainly help advance the case. In terms of software architecture explanations, it is probably one of the most comprehensive I've seen in a while. My one argument is there wasn't any comparison between Kotlin and other systems, some comparison would have been helpful. Overall, this makes an excellent reference for any software architecture questions working from the high level context all the way down to the code. Read more
Amazon Verified review Amazon
Om S Jan 24, 2025
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
This book provides a solid introduction to software architecture, blending theory with practical examples using Kotlin. It covers a range of architectural styles, including microservices, event-driven design, and serverless, while highlighting the trade-offs and challenges involved in real-world applications. Read more
Amazon Verified review Amazon
David K. Lee Jan 20, 2025
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
This book shows all the things in the software architecture in Kotlin. Proper code examples can help users understand the design concepts at hand. The one impressive thing is explaining sealed classes and delegation for Polymorphism. It should be helpful for my Android development in Kotlin. Read more
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.