avatarMehmet Ozkaya

Summary

This article discusses fundamental software architecture design principles, specifically the Separation of Concerns (SoC) and SOLID principles, and illustrates their application in both Layered Monolithic and Microservice architectures, with a focus on e-commerce application design.

Abstract

The article "Software Architecture Design Principles: SoC, SOLID" provides an in-depth look at two key sets of principles for software architecture: Separation of Concerns (SoC) and SOLID. It emphasizes the importance of breaking down complex systems into manageable parts, each with a single responsibility, to minimize complexity and improve maintainability. The SoC principle advocates for distinct, independent components with low dependency and high cohesion, while the SOLID principles comprise five tenets: Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion. The article further explores how these principles can be applied in practical scenarios, such as the design of an e-commerce application using either Layered Monolithic or Microservice architectures, and suggests that adhering to these principles leads to more extensible, flexible, and robust systems. Additionally, the author promotes their Udemy course, which guides learners through the step-by-step process of designing microservices architectures using patterns, principles, and best practices.

Opinions

  • The author advocates for the use of N-Layer architecture as a practical application of the SoC principle.
  • The article suggests that the SOLID principles are essential for creating software that is easy to extend and maintain without incurring significant changes to the existing architecture.
  • The author expresses a preference for low coupling and high cohesion in software design, emphasizing the benefits of distributed responsibility among components.
  • The use of message brokers and event-driven architecture is recommended as a means to decouple services and facilitate an asynchronous communication model in microservices architectures.
  • The author believes that designing software with these principles in mind can lead to systems where individual components can be easily substituted, such as switching between different message brokers like RabbitMQ and Kafka.
  • The article posits that the evolution of software architecture, from monolithic to microservices and further to nano-services, is a response to the growing complexity and scalability demands of modern software systems.
  • The author's perspective is that a well-designed software architecture can significantly reduce the complexity of a system, making it more understandable, manageable, and adaptable to future changes or enhancements.

Software Architecture Design Principles: SoC, SOLID

In this article, we are going to learn Software Architecture Design Principles: SoC, SOLID principles.

SOLID Principles

By this article, we are going to understand main design principles that we can use any software architecture.

I have just published a new course — Design Microservices Architecture with Patterns & Principles.

Introduction — Software Architecture Design Principles

In software industry, we can get projects from the easiest to the most complex projects and solutions from our clients. However, it is often that we fall into the trap of designing more complex systems than necessary required systems. So before we start to design, its good to check our design principles that we can apply on every design. These principles are;

  • SoC — Separation of Concerns
  • SOLID

Let’s see details.

Separation of Concerns (SoC)

Think about that what is the motivation the use N-Layer architecture ? Why we separate the layers to N ? What is the underlying principle to create this N-Layer architecture. This principle is Separation of Concerns (SoC).

Separation of Concerns is a design principle in software architecture that advocates breaking down a complex system into distinct, independent, and manageable parts, each of which is responsible for a specific aspect or function of the system.

SoC says that the elements in the software should be unique to them, not to share their responsibilities with other staff members. While developing the software, we can see the necessary of separating responsibilities with following this principle.

The idea behind separation of concerns is to minimize the complexity of a system by dividing it into smaller parts that can be developed, tested, and maintained independently, without interfering with the other parts. By separating the concerns, developers can focus on developing each part of the system with a clear understanding of its purpose and the interactions it has with other parts.

We can say that, we distinguish between the concepts of layer and tiers with certain responsibilities. If we go further a little more, the namespaces of our software components can also be used as limits to allocate responsibilities.

The dependencies of the components within the software and the cohesion within the components are two important concepts for the SoC principle. It should always be preferred that the dependency of the components is low and that the relationship of responsibility in a component is high.

So low-coupling, high-cohesion is indispensable. If the dependency of commitment is low, then the control of the software will be easier in our hand, since the liability will be distributed per component. Being close to each other in their responsibilities within the components will becomes re-usability. We can give an example of SoC that development of Web UI. As you can see that UI element button needs to configure by 3 structure; HTML — CSS — JS.

Separation of concerns is achieved through the use of layers, modules, or services, with each layer or module responsible for a specific function, such as data storage, user interface, business logic, or communication with external systems. This allows developers to focus on their area of expertise, making it easier to write, test, and maintain software, and also makes it easier to add new functionality to the system without disrupting existing code.

Design principles — SOLID

SOLID is one of the main principle groups to use almost every software projects.

This one though, stands for:

  • Single Responsibility Principle
  • Open-Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

So if you think about it, it’s really 5 principles all packed into one. So let’s unpack them one by one.

Single Responsibility

The idea is that each of your classes (or modules, units of code, functions, etc) should responsible only one functionality. Why ?

Because if you want to change your code, you should first have a good reason, then you should know where is that single point where that reason applies. We can use this base principles when designing the system also.

Open-Closed Principle

When you write your code, the last thing you want to do is go back to it and change it again and again whenever you implement a new functionality. You want the legacy code to work, be tested to work, and allow new functionality to be built on top of it.

In the same way, when we design the system, it should able to extend without changing existing architecture. For example using pub/sub pattern with message brokers is a good example for that. If we want to notify some other microservices, instead of calling their services, we can publish an event and they can consume them from message broker. By this way, if there will be a new microservice need to consume this event, we don’t change anything for existing architecture, the only thing to subscribe that event from message broker that’s all. So our design open for extensions and close for modifications.

Liskov Substitution Principle

I am not going to give deep explanation about that. Because we are looking this principles from the system design perspective. So we can say that, our systems can be substitute each other easily. In our case we can use plug-in services that we can shift them easily, For example if we use RabbitMQ as a message broker, we can shift to Kafka easily with abstracting Event Bus implementations.

Interface segregation principle

It basically says split your interfaces — meaning the desired functionality of your code — into pieces that are fully used.

Dependency Inversion Principle

Also known as dependency injection. If you have dependencies in your code, you should allow for them to be injected into your logic. How do you do that ? Of course By allowing them to be passed in as parameters.

This is a very useful principle that we can use system architecture design. We don’t want to dependent microservices and direct communication due to possible network problems. In order to broke this dependencies, we can use message brokers and event-driven architecture that provide to de-couple services. As you can see that we understand SOLID principles and how we can use them when architecting system designs.

Design Layered Architecture — E-Commerce App

If we design e-commerce application with Layered Monolithic architecture, you can see the image below:

There is a big single Monolithic Application Server but Application has logical layers which’s are UI, Business and Data Access. And there is one big relational databases.

Design Microservice Architecture — E-Commerce App

If we design e-commerce application with Microservice architecture, you can see the image below:

Product microservice can use NoSQL document database Shopping Cart microservice can use NoSQL key-value pair database and Order microservice can use Relational database as per microservice data storage requirements.

What’s Next ?

Step by Step Design Architectures w/ Course

I have just published a new course — Design Microservices Architecture with Patterns & Principles.

In this course, we’re going to learn how to Design Microservices Architecture with using Design Patterns, Principles and the Best Practices. We will start with designing Monolithic to Event-Driven Microservices step by step and together using the right architecture design patterns and techniques.

Software Architecture
Solid
Separation Of Concerns
Microservices
Software Development
Recommended from ReadMedium