Evolution in Software Architecture

Img src :Unfinished Evolution by György Csepeli

Over the last decade, software engineering’s scope has risen to provide more responsibility and perspective. A decade ago, with lots of bureaucracy, the typical relationship between architecture and operations was contractual and formal. Most companies, trying to mitigate the complexity of hosting their operations, often outsourced operations for a third party company, consisting of contractual obligations for service level agreements. Nowadays, architectures such as microservices freely leverage former solely operational concerns. This article’s primary objective is to briefly discuss the ‘Software Structure’ as an initiative for our topic.

Introduction

To begin with, let’s discuss the background of Software Architecture. Computer architecture has traditionally been distinct from the method of development used to build software. There are hundreds of standard software building methodologies, including Waterfall and several Agile flavors (such as Scrum, Extreme Programming, Lean, and Crystal), which often do not impact software architecture. Over the last few years, however, it can see that technological advancements have thrust process concerns upon software architecture. Most importantly, it is useful to separate the software development process from engineering practices. Perusing this further, let’s move on to understand what software architecture is.

What is Software Architecture?

Initially, this industry doesn’t have a proper definition itself. However, individual architects discuss software architecture as the system’s blueprint, while others identify it as the roadmap for system growth. So that understanding of the blueprint or roadmap comprises the common issue with these concepts.

Software architecture consists of four features; software structure, architecture decisions, architecture characteristics, and design principles described by Mark Richards and Neil Ford in their book (Software Architecture Fundamentals). Moreover, due to the rapidly changing software development ecosystem, software design has continuously shifted target.

In the same manner, it does not entirely elucidate an architecture by defining an architecture purely by its form. To properly understand the software architecture, knowledge of the architectural elements, architecture decisions, and design concepts should also be required.

Figure 1 : Software Architecture — Ref : Fundamentals of Software Architecture

Another feature in describing software architecture is software architecture characteristics. Many characteristics can be defined, and there are no hard and fast rules where any system’s architecture should comply with all software architecture characteristics. First of all, the software architect should determine the software’s business and functional objectives and define the characteristics that should follow in a way that best suits the business goals. Determining these characteristics is an act of balance that depends on what we are trying to achieve from the system. One best example to illustrate this is the usage of Graphic equalizer in sound systems. Based on the genre, intensity, loudness, clarity of the music, environment, etc., one needs to adjust its knobs to achieve optimal music satisfaction. As a more concrete example, if your system is more concerned about security, you need to compromise aspects such as performance.

Figure 2: Software Architecture Characteristics — Ref : Fundamentals of Software Architecture

What are the Expectations of an Architect?

Before moving on to our topic, let’s understand some of the core expectations placed on a software architect.

Decision making

An architect must describe the architectural decisions and design concepts used within the team, the department, or the organization to drive technology decisions. The main operative word in this first expectation would be ‘guide.’ An architect should direct technology choices rather than defining them.

It is challenging to direct technology choices through architecture decisions and design concepts. The key to making the right architectural decisions is to consider if the architectural decision helps direct teams make the right technical choice or whether the architectural decision’s technical choice is made.

Continually analyzing the architecture

It is expected that an architect will continuously evaluate the architecture and current environment of technology and then propose proposals for change. This type of architect’s expectation refers to the viability of architecture, which assesses how viable the architecture that was defined years ago.

Keep current with the latest trends

To stay relevant, developers must keep up to date with the innovations they use daily. The choices that an architect makes tend to be long-lasting and hard to alter. Moreover, the architect will plan for the future and make the right decision by recognizing and tracking key trends.

Ensure compliance with decisions

Ensuring compliance ensures that the architect continuously verifies that software development teams obey the architectural choices and design principles identified, registered, and communicated by the architect.

Diverse exposure and experience

It is anticipated that architects will be exposed to different and varied technologies, structures, platforms, and ecosystems. In any system, medium, and language, this expectation does not mean that an architect must be an expert. Instead, an architect must at least be familiar with a range of technologies. A good architect should possess technical breadth knowledge rather than in-depth knowledge in selected technologies.

Have business domain knowledge

It is assumed that an architect would have a certain degree of business domain experience. Successful software architects recognize the business domain of a problem space, not just technology. Without knowledge of the business domain, it is difficult to understand the business issue, priorities, and requirements, making it challenging to develop an efficient architecture to satisfy the business requirements.

Possess interpersonal skills

Most good software architects possess outstanding leadership and interpersonal skills since technologists, engineers, and architects like to solve technological issues rather than problems with people. But at the end of the day, you should successfully lead your technical teams.

Understand and navigate politics

An architect is supposed to consider the company’s political environment and be able to manage politics.

The evolution of the Software Architecture

Moving on with our topic, in this article, we will go through only the evolution of the ‘software structure’ part in software architecture. It is starting from the good old Monolith, where most software applications began their lifeline.

I will use the architecture evolution of one of the SaaS software products I worked on for few years to walk you through this journey. Furthermore, I would be considering only the structural evolution of software architecture.

Monolith

Let’s say that the users’ project has started as a pre-sales project, a throwaway prototype, or a university assignment situation. At these particular scenarios, you are not mainly focusing on high-end software architecture patterns and styles. But, you will be only focusing on MVP or Minimal Viable Project situations to cater to the client requirements as soon as possible, so as by moving onto Monolith Architecture in this particular situation.

Many tend to think that the Monolithic architecture style is becoming obsolete now. But as I see, it is one of the simplest and easy to understand and implement architectural patterns that we do have.

Figure 3 : Monolithic Software Architecture

Subsequently, when many people try to get on board with the Monolithic SaaS application that we have created, problems such as scalability, elasticity, and resilience occur. In these situations, what is normally done is we identify which part of the module that users have been using more frequently and consequently take out that particular component from the initial Monolith.

Figure 4 : Distributed Monolith

We have exposed that separated component as a rest API, where our frontend client can access it independently. Here, in this case, our frontend clients have to maintain two end-points, one pointing into our main Monolith and the other pointing to our newly created service.

Distributed Monolith

In the Distributed Monolith Architecture, we, one by one, take out all the parts from the main Monolith and eventually spin up independent services, as shown in figure 3. By definition, a Distributed Monolith is an application deployed as a Microservice but is built like a Monolith. In this case, it could be seen that the frontend clients need to maintain separate endpoints for each independent service and that the database is being shared as well.

One of the drawbacks of this type of architecture is that, in the deployment process, it would be a bit troublesome, as all components have to be deployed or released at once since the database is shared in between these services. Also, to overcome frontend maintenance, API gateway has been introduced in the Distributed Monolith system. In this circumstance, the frontend web application concentrates only on one endpoint where the API gateway knows about routing these particular API requests into correct services. Moreover, the API Gateway handles the authentication part as well.

The entire application is bundled into a single package in a monolithic architecture, including binaries, libraries, configurations, and all other dependencies required for it to run. With a distributed monolith, we have the heaviness and inflexibility of monoliths, microservices’ complexity, and a few of both architectures’ benefits. We would still have slow deployments and poor scalability. But we have added operational complexity and removed isolation between services. Here, in this case, the team would adopt new tooling and rebuild the applications to tolerate the dynamic and transient world of containers by adding tons of time and labor.

Distributed SOA

I have seen many architects and developers misunderstood the Microservices with Distributed Service Oriented Architecture. During many consultations that I did, they claimed to have implemented a Microservices, while the real implementation is a distributed SOA. The main common factor of this misconception is that whenever someone has many (dependant) services, they tend to think that they have implemented a Microservices architecture. As long as you have a shared database as a huge dependency, you have a distributed SOA irrespective of how many services you have. Furthermore, you should have to have many other features such as service discovery, circuit breakers, distributed tracing etc.. to make your architecture a Microservices architecture.

We had to live with this kind of distributed SOA for few months until we introduce the Event-Driven Architecture during our evolution.

Figure 5: Distributed SOA

Event-Driven Microservices Architecture

Take a look at a huge monolith application with a lot of complex functionalities strongly tied together. The scalability would be obvious, a big challenge. Eventually, the deployment process would be very cumbersome. Since all the internal components are highly coupled, even a small change in the functional flow will not be easy.

Microservices architecture emerged as a remady to many difficulties faced in all Monolithic architectures. In our solution, we never used pure Microservices architecture but Event-Driven Microservices architecture.

As the microservices are decoupled, they could scale more easily, and whenever you want to make a change, you could change just a single component. But still, there could be problems encountering. So to overcome these kinds of issues, some of the microservice applications have adopted event-driven architecture. The main disadvantage in a classical Microservices architecture is a dependency between synchronized service calls. Ie: we have a highly coupled solution even though we are using independently operating services. There could still be deployment dependencies if we have high coupling between services.

The main decoupling of services has been achieved using the event bus. Whenever there is an action, a service would publish an event to the event bus and where a specific set of services would be subscribing to it.

There are many technologies these days that you could use to stream events from one component to another, where ‘Kafka’, which may be the most popular streaming service, which is a good fit for Event-driven architecture as well.

Figure 6 : Event-Driven Microservices with enabling functions

Moreover, to remedy problems encountered when using Event Bus, as shown in Figure 6, Service Discovery and other required support services and functionalities.. Alert systems and self-healing systems have also been introduced to spin up new instances of that particular service.

In our SOA version of the product, the major pain area we had was scalability, resilience, performance, and maintainability ( it was an office fiasco during deployment days) mainly because of the shared database inter-service dependencies. With the introduction of EDM ( Event-Driven Microservices), most of these pain areas were evaporated, and the life of our DevOps guys became more relaxed.

With this, there is one more small note that I would like to make, especially when it comes to the individual services’ performance. We had few services which were heavy on both data reads and writes. To get away from the obvious performance bottleneck, we introduced the CQRS pattern as depicted in Figure 7.

Figure 7 : Command Query Responsibility Segregation to improve DB Performance

Most of our backend fine-tuning stopped from this point, but our frontend SPA application still lives in the Monolithic world. Lets see what we did for that.

EDM with Micro Frontends

For most projects, it can be seen that the frontend world remains largely monolithic. Just as with the backend before micro-services, this means that it’s hard to scale development and that teams keep stepping on each other’s toes instead of being free to independently build, deliver, and choose their frontend solutions.

Instead of working distinctly from each other, developers are all bound to the same codebase of a growing SPA or SSR app and are all forced to crowd in the same build pipeline. This makes development inefficient and hard to scale, so that the idea of micro-frontends is to allow the benefits of microservices in the frontend world.

EDM with Micro-Frontends

In this scenario, shown in figure 8, we see patterns emerge for decomposing frontend monoliths into smaller, simpler chunks that could be developed, tested, and deployed independently while still appearing to customers in a single cohesive product.

This technique is called the micro frontends. Simply, this is an architectural style where independently deliverable frontend applications are composed into a greater whole.

Benefits from Micro Frontends

  • Smaller, more cohesive, and maintainable codebases
  • More scalable organizations with decoupled, autonomous teams
  • The ability to upgrade, update or even rewrite parts of the frontend more incrementally than was previously possible

There are few frameworks. that use can use to ease off the development effort of Micro-frontend. Single SPA is one of the best example.

CTO @ ZorroSign | Seasoned Software Architect | Expertise in AI/ML , Blockchain , Distributed Systems and IoT | Lecturer | Speaker | Blogger