SOLID Prensiplerini Anlama, keep calm! Cloud-Native Uygulamalar İçin

Bu makale kapsamında bahsetmek istediğim konu SOLID prensipleri ama bu sefer cloud-native uygulamalar’lar için.

Bildiğimiz gibi SOLID prensipleri, object-oriented yazılım geliştirmede kuşkusuz en önemli prensip setlerinden birisidir.

Bir çoğumuz uygulama geliştireceğimiz zaman kodumuzu SOLID prensipleri doğrultusunda geliştirmeye çalışıyoruz, çünkü:

  • Geliştirilen uygulamanın well-designed olabilmesi için kod standartı sağlalamaktadır.
  • Ayrıca kolay maintenance sağlamaktadır.
  • Extendability ve Reusability de artısı.

SOLID prensiplerinin sağladığı bir kaç faydayı yazmak istedim. Söz konusu SOLID olunca, bu maddeler bitmez.

Uygulamalarımızı bu prensipler doğrultusunda kod seviyesinde iyi bir şekilde geliştirmeye çalışıyoruz. Peki uygulama seviyesinde bu kadar iyi bir şekilde geliştirmeye dikkat ediyor muyuz? Özellikle cloud-native bir uygulama geliştirme söz konusuysa.

Bir kaç gün önce LinkedIn üzerinden aşağıdaki gibi bir paylaşımda bulunmuştum.

Bu paylaşımımın ardından özelden gelen bir kaç soru doğrultusunda, cloud-native uygulamalar için SOLID prensipleri konusuna küçük bir makale ile değinmek istedim. Bu arada, özellikle Red Hat‘ın bu konu üzerinde çok güzel paylaşımları bulunmaktadır.

Biliyorsunuzki günümüz teknoloji çağında highly scalable cloud-native uygulamalar geliştirmek, oldukça önem taşımaktadır. Geliştiriyor olduğumuz uygulamaların iyi bir cloud-native vatandaşı olabilmesi için ise, uyması gereken bir takım container-related best practice’ler ve prensip’ler bulunmaktadır.

Peki, Nedir Bu Cloud-Native Uygulamalar İçin SOLID Prensipleri?

Bu prensipler “Build time” ve “Runtime” olmak üzere iki farklı kategoriye ayrılmaktadır.

Build Time Principles


1) Single Concern Principle

Bu prensip’in içeriğini, tıpkı Single Responsibility prensip’ine benzetebiliriz. Diyorki, her bir container, sadece tek bir concern ile ilgilenmelidir. Bu sayede istenilen container, sorunsuz ve bağımsız bir şekilde scale veya replace edilebilmektedir.

Eğer farklı fonksiyonalitelerin de handle edilmesi gerekiyorsa, sidecar gibi cloud-native pattern’ları kullanılabilir. Örneğin bu pattern, container’ın isolated bir şekilde heterojen bileşenlerden (Logging, Tracing, Proxying) oluşabilmesine olanak tanımaktadır.

2) Self-Containment Principle

Bu prensip ise kısaca, container’ın çalışabilmesi için ihtiyaç duyduğu her şeyi (libraries vs…), environment bazlı değiştiği için configuration’lar hariç, build time’da içermesi gerektiğini söylemektedir.

3) Image Immutability Principle

Buradaki amaç, containerized hale getirilmiş uygulamanın değişmez olmasıdır. Yani containerized bir uygulama build edildikten sonra, environment bazlı değişmemeli ve ihtiyaçlara göre configure edilmelidir. Eğer herhangi bir değişim olacaksa containerized bir uygulamada, bunun için yeni bir image oluşturulması ve tekrar environment’lar arasında kullanılması beklenir.

Runtime Principles


1) High Observability Principle

Bildiğimiz gibi distributed sistemler içerisindeki en önemli konulardan bir tanesi observability. Uygulamanın o anki sağlığını her açıdan görebilmek, olası bir problemin önüne kolayca geçebilmemize yardımcı olacaktır.

Twelve Factor App‘in “Logs” başlığında olduğu gibi özellikle log’lama, runtime’da çalışan bir uygulamanın bize davranışlarını izleyebilme olanağını sunmaktadır.

Bu prensip ise derki, containerized uygulamalarınıza bir black box gibi davranın ama davranışlarının gözlemlenebilmesi için gerekli tüm API‘ları da (health checks, tracing, logs, etc…) implemente edin.

Örneğin log’ların aggregation işlemi için Fluentd, Logstash ve ayrıca tracing işlemleri için ise OpenTracing, Jaeger implemente edilebilir.

2) Lifecycle Conformance Principle

Burada ise önemli olan nokta, container’ın platform’dan gelen event’lere karşı duyarlı olmasıdır. Bu event’ler ile, lifecycle’ını yönetmelidir.

Örneğin containerized bir uygulama “PostStart” veya “PreStop” event’lerine duyarlı olarak, warm up veya graceful shutdown işlemlerini gerçekleştirebilir.

3) Process Disposability Principle

Önemli prensip’lerden bir tanesidir. Twelve Factor App’in “Disposability” maddesinde olduğu gibi, container’lar geçici olmalıdır.

Bu prensip özellikle containerized bir uygulamanın hızlı start ve shutdown olabilmesine odaklanmaktadır. Böylece herhangi bir t anında, containerized bir uygulama kolay ve hızlı bir şekilde scale out veya replace edilebilmektedir.

4) Runtime Confinement Principle

Bu prensip bana göre en önemli prensip’lerden bir tanesi. Kısaca her bir container’ın, ihtiyaç duyduğu resource kullanımının tanımlanmasını ve tanımlanan şartlarla da resource kullanımının sınırlandırılmasını söylemektedir.

Örneğin containerized bir uygulamanın ne kadar memory veya CPU kullanması gerektiğinin belirtilmesi, auto-scaling ayarları için de minimum ve maximum instance değerlerinin belirlenmesi gerekmektedir.

Kubernetes ortamında ise bir pod için aşağıdaki gibi resource limitlerini kolay bir şekilde belirtebilmek mümkündür.

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

Unutmayalım ki limitleri belirtilmeyen containerized bir uygulama, runtime’da istenmeyen sonuçlara sebeb olabilmektedir. Ayrıca bu istenmeyen sonuçlar, platform üzerindeki diğer servis’lerin de olumsuz etkilenmesine sebep olacaktır.

Sonuç

İyi ve temiz bir uygulama geliştirebilmek için object-oriented yazılım geliştirmede SOLID prensiplerine uyulmasının önemini biliyoruz. Bu makalede ise uygulamanın iyi bir cloud-native vatandaşı olabilmesi için uyması gereken SOLID prensip’lerinden bahsettik.

Bildiğimiz gibi cloud-native uygulamalar scaling gibi bir çok güzel yeteneklerle birlikte daha hızlı yazılım geliştirmeye olanak sağlamaktadır.

Elbette bir uygulamanın iyi bir cloud-native vatandaşı olabilmesi için duruma göre uygulanabilecek bir çok farklı teknikler de bulunmaktadır. Bu makale kapsamında bahsettiğimiz prensip’ler ise, daha temel ve bir çok use-case’ler de geçerli olabilecek olan prensipler.

Referanslar

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

Containerized Uygulamaların Supply Chain’ini Güvence Altına Alarak Güvenlik Risklerini Azaltma (Güvenlik Taraması, SBOM’lar, Artifact’lerin İmzalanması ve Doğrulanması) – Bölüm 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 ay ago

Identity & Access Management İşlemlerini Azure AD B2C ile .NET Ortamında Gerçekleştirmek

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

12 ay ago

Azure Service Bus Kullanarak Microservice’lerde Event’ler Nasıl Sıralanır (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 yıl ago

.NET Microservice’lerinde Outbox Pattern’ı ile Eventual Consistency için Atomicity Sağlama

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

2 yıl ago

Dapr ve .NET Kullanarak Minimum Efor ile Microservice’ler Geliştirmek – 02 (Azure Container Apps)

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

2 yıl ago