Understanding SOLID Principles, keep calm! For Cloud-Native Applications

In this article, I want to mention about the SOLID principles but this time for cloud-native applications.

As we know, SOLID principles are undoubtedly one of the most important sets of principles in the object-oriented software development world.

We are generally trying to develop our codes based on the SOLID principles when we develop applications, because:

  • It provides coding standards in order to be well-designed.
  • It also provides easy maintenance.
  • In addition Extendability and Reusability.

I wanted to mention a few important points of the SOLID principles. If we start to talk about the SOLID principles, these important points don’t end.

We are trying to develop our applications around these principles at the code level. So what about the application level? Are we paying also attention at the application level? Especially if we talk about the develop cloud-native applications.

A few days ago, I have shared a post via LinkedIn like below.

After shared this post, I got a few question messages about the SOLID principles for cloud-native applications and I decided to mention that with a short article. By the way, Red Hat has very nice articles on this topic.

As you know, in today’s technology age, developing highly scalable cloud-native applications is very important. There are a few container-related best practices and principles that applications must follow in order to be a good cloud-native citizen.

Well, What are the SOLID Principles for Cloud-Native Applications?

These principles are divided into two different categories as “Build time” and “Runtime“.

Build Time Principles


1) Single Concern Principle

The content of this principle similar to the Single Responsibility principle. It says each container should handle just one concern. Thus, the desired container can be scaled or replaced independently.

If different functionalities need to be handled, cloud-native patterns can be used such as sidecar. For example, this pattern allows the container to be consist of isolated heterogeneous components (Logging, Tracing, Proxying).

2) Self-Containment Principle

In a nutshell, this principle says a container should be contained everything (libraries vs…) that needs to be able to run in the build time, except configurations since they can change environment-based.

3) Image Immutability Principle

The goal is a containerized application should be immutable. This means, once an application built, it should not change environment-based and should be configured according to needs. If anything needs to be changed in a containerized application, to do that it should be created a new image and it should be reused across the environments.

Runtime Principles


1) High Observability Principle

As we know, in the distributed systems, one of the important topics is observability. To be able to see the current health of an application will help us to avoid possible problems easily.

As in the “Logs” section of the Twelve Factor App, especially logging gives us the ability to monitor the behaviour of an application on runtime.

This principle says to treat your containerized applications as a black box, but should be implemented all the necessary APIs (health checks, tracing, logs, etc…) in order to monitor their behaviours.

For example, we can implement Fluentd, Logstash for logging aggregation and also OpenTracing, Jaeger for tracing operations.

2) Lifecycle Conformance Principle

The important point here is that the container should be sensitive to events which are coming from the platform. Also, it should manage its lifecycle with these events.

For example, a containerized application can perform warm-up or graceful shutdown operations as sensitive to the “PostStart” or “PreStop” events.

3) Process Disposability Principle

It is one of the most important principles. Containers should be transient as in the “Disposability” section of the Twelve Factor App.

This principle especially focusing on fast start and shutdown of a containerized application. Thus, at any time, a containerized application can be easily and quickly scaled out or replaced.

4) Runtime Confinement Principle

This principle is one of the most important principles for me. In a nutshell, it says that each container should have its resource usage conditions it will need and the resource usage should be limited with the defined conditions.

For example, it is necessary to specify how much memory or CPU a containerized application will use, also minimum and maximum instance values for auto-scaling settings.

It is possible to easily specify resource limits for a pod in the kubernetes environment as follows.

hpa:
 enabled: true
 minReplicas: 1
 maxReplicas: 3
 targetCPUUtilizationPercentage: 70
 
resources: 
 limits:
   cpu: 300m
   memory: 300Mi
 requests:
   cpu: 100m
   memory: 100Mi

We shouldn’t forget that a containerized application, which doesn’t have its resource limits, can cause unwanted results in runtime. In addition, these unwanted results will adversely affect other services on the platform.

Conclusion

We are aware of the importance of following SOLID principles in object-oriented software development in order to develop a well structured and clean application. In this article, we mentioned about the SOLID principles that the application must follow to be a good cloud-native citizen.

As we know, cloud-native applications enable rapid software development with many great capabilities such as scaling.

Of course, there are many different techniques that can be applied on a case-by-case to make an application a good cloud-native citizen. The principles we have mentioned in the context of this article are the more fundamental and can be applied in many use-cases.

References

https://www.redhat.com/en/resources/cloud-native-container-design-whitepaper
http://turnoff.us/geek/dont-sigkill-2/

Gökhan Gökalp

View Comments

Recent Posts

Securing the Supply Chain of Containerized Applications to Reduce Security Risks (Policy Enforcement-Automated Governance with OPA Gatekeeper and Ratify) – Part 2

{:tr} Makalenin ilk bölümünde, Software Supply Chain güvenliğinin öneminden ve containerized uygulamaların güvenlik risklerini azaltabilmek…

5 months ago

Securing the Supply Chain of Containerized Applications to Reduce Security Risks (Security Scanning, SBOMs, Signing&Verifying Artifacts) – Part 1

{:tr}Bildiğimiz gibi modern yazılım geliştirme ortamında containerization'ın benimsenmesi, uygulamaların oluşturulma ve dağıtılma şekillerini oldukça değiştirdi.…

8 months ago

Delegating Identity & Access Management to Azure AD B2C and Integrating with .NET

{:tr}Bildiğimiz gibi bir ürün geliştirirken olabildiğince farklı cloud çözümlerinden faydalanmak, harcanacak zaman ve karmaşıklığın yanı…

12 months ago

How to Order Events in Microservices by Using Azure Service Bus (FIFO Consumers)

{:tr}Bazen bazı senaryolar vardır karmaşıklığını veya eksi yanlarını bildiğimiz halde implemente etmekten kaçamadığımız veya implemente…

2 years ago

Providing Atomicity for Eventual Consistency with Outbox Pattern in .NET Microservices

{:tr}Bildiğimiz gibi microservice architecture'ına adapte olmanın bir çok artı noktası olduğu gibi, maalesef getirdiği bazı…

2 years ago

Building Microservices by Using Dapr and .NET with Minimum Effort – 02 (Azure Container Apps)

{:tr}Bir önceki makale serisinde Dapr projesinden ve faydalarından bahsedip, local ortamda self-hosted mode olarak .NET…

2 years ago