Domain Driven Design

KATEGORİ

Application service act as the first contact point to outside of domain, and it will forward the call to the domain service and entities to complete a business logic.

Yazılım geliştirmeyi karmaşık hale getiren pek çok sebep olabilir. Bu karmaşıklığın merkezinde ise yapılan işin (business) temelinde bulunan zorluklar ve karmaşıklıklar bulunur. Bir iş kolunu yazılım ile otomatize hale getirmeye çalışıyorsak, yapacağımız yazılım o iş kolunun kendine özgü zorlukları ve karmaşıklıklarıyla yüzleşecektir.

Karmaşıklığı kontrol etmenin yolu, iş alanının yüzeysel görünümünün ötesinde yapıya derinlemesine bir giriş yapan ve bu şekilde yazılım geliştiricilere ihtiyaçları olan gücü veren iyi bir iş alanı modelidir.

İş alanı modelleyici, büyük miktarda veriyi işleyerek ilgili olan ayrıntıları bulmaya çalışır. Bilgi işleme genellikle bir ekip faaliyetidir. Yazılımcılar ve iş alanı uzmanları, bilgiyi çeker ve bunu kullanışlı bir biçime dönüştürmek için bir araya gelirler. Bu süreçte, iş alanı uzmanlarının düşünceleri, mevcut sistem kullanıcılarının geri bildirimleri, teknik ekibin önceki deneyimleri ve proje için yazılan belgeler gibi çeşitli kaynaklardan faydalanılır. Ekip, bu bilgiyi kullanarak projenin erken versiyonlarını veya prototiplerini oluşturur.

Waterfall methodunda iş sahipleri, uzmanları analistlerle konuşur. Analistler bu bilgileri alır, işler, soyutlar ve yazılımı geliştiren yazılımcılara iletir. Bu yaklaşım geri bildirim mekanizmasındaki eksiklikler nedeniyle başarısız olur. Analistlerin, iş uzmanlarından gelen bilgiler temelinde bir model oluşturma sorumlulukları vardır. Fakat yazılımcılardan bir şeyler öğrenme ya da yazılımın ilk versiyonları hakkında deneyim kazanma şansları yoktur. Bilgi tek yönlü olarak akar ancak birikmez.

Başka bazı projeler de yinelemeli bir süreç kullanmalarına rağmen, bilgi birikimini sağlayamazlar. Soyutlama işlemi yapılamadığı için böyle olur. Yazılımcılar, iş uzmanlarından bir özelliği açıklamalarını ister ve ardından bunu geliştirirler. Yazılımcılar, uzmanlara sonucu gösterir ve ne yapılması gerektiğini sorarlar. Programcılar refactoring uygularlarsa, yazılımı yeterince temiz tutabilirler ve genişletmeye devam edebilirler, ancak programcılar iş alanına önem vermezlerse, sadece uygulamanın ne yapması gerektiğini öğrenirler. Onun ardındaki prensipleri anlamazlar. Bu şekilde kullanışlı bir yazılım geliştirilebilir, ancak proje, güçlü yeni özelliklerin eski özelliklere bağlı olarak ortaya çıkacağı bir noktaya asla ulaşmaz.

İyi programcılar soyutlama yapmaya eğilimlidirler ve bu şekilde daha fazla iş yapabilen bir model geliştirebilirler. Bu soyutlama süreci, yalnızca teknik bir ortamda, iş alanı uzmanlarıyla işbirliği yapmadan gerçekleşirse, ortaya çıkan sonuç basit olur. Bilgi yetersizliği nedeniyle, yazılım temel görevleri yerine getirebilir belki ancak iş alanı uzmanının düşünce tarzına tam olarak uyum göstermeyebilir.

Yazılım ekibi arasındaki iletişim, iş alanı modelini tüm ekip birlikte ele aldığında gelişir. Sürekli olarak geliştirilen iş alanı modeli, yazılımcıları sadece mekanik işlevleri (fonksiyonlar) üretmek yerine üzerinde uğraştıkları işin temel prensiplerini öğrenmeye zorlar. Bu süreçte iş alanı uzmanları da bilgilerini temele indirgeyerek kendi anlayışlarını geliştirirler ve bir yazılım projesinde olması gereken netliğin, tutarlılığın ve anlayış birliğinin önemini daha iyi anlarlar.

Bütün bunlar takım üyelerinin daha yetkin bilgi işleyenler haline gelmelerini sağlar. Gereksiz detaylar elenir. Model daha kullanışlı bir forma dönüşür. Analistler ve yazılımcılar tarafında sürekli bilgi akışı olduğu için, daha organize ve soyutlanmış, güçlenmiş bir model ortaya çıkar. İş alanı uzmanları da bu sürece dahil oldukları için de model işin derin bilgisini yansıtabilir. Soyutlamalar gerçek iş prensipleridir.

Model geliştikçe, proje içinde akan bilgileri organize eden bir araç haline dönüşür. Model gereksinim analizine odaklanır. Programlama ve yazılımla da etkileşim içindedir. Ve bir döngü içinde yazılımcıların işi daha iyi anlamaları ve bunun sonucunda modelin daha kullanışlı bir hale gelmesi için sürekli yenilenmesi işlemleri gerçekleşir. Modeller mükemmel değildirler. Modeller iş alanını anlamanın bir aracı olarak kullanışlı olmalıdırlar.

Continuous Learning

Bir projeyi geliştirmeye başladığımızda, iş hakkında yeterli bilgiye sahip değilizdir. Bilgi dağınıktır ve hangi bilgiye gerçekten ihtiyaç duyduğumuzu bilemeyiz. Ekip üyeleri arasında bilgi aktarım süreci düzgün bir şekilde işletilmelidir. Sözlü bilgi uçup gitmemelidir. Verimli ekipler bilgiyi sürekli geliştirir ve sürekli öğrenmeyi pratiğe döker. Bu şekilde üzerinde çalışılan iş alanı hakkında ciddi bir öğrenme sağlanır.

Chapter 2 – Communication and the Use of Language

Bir iş alanı modeli, bir yazılım projesinin ortak dilinin çekirdeği olabilir. Model, projedeki insanların zihninde oluşturdukları, iş alanını yansıtan terimler ve ilişkiler içeren kavramlar bütünüdür. Bu terimler ve ilişkiler, teknik geliştirmeler için yeterli olsa da, etki alanına özgü bir dilin semantiğini de sağlar. Bu modeli geliştirme aktivitesine entegre eden ve kod ile eşleştiren kritik bir bağdır.

Bir projede ortak bir dil oluşturulamadığında ciddi problemler oluşur. Bu durumda iş alanı uzmanları kendi jargonlarında konuşurken teknik takım iş alanını tartışmaya yönelik kendi dilini kullanır.

Günlük tartışmaların terminolojisi, kod içine gömülen terminolojiden (sonuçta bir yazılım projesinin en önemli ürünü) kopar. Aynı kişi bile konuşup, yazarken farklı bir dil kullanır, bu da etki alanının en keskin ifadelerinin genellikle geçici bir formda ortaya çıkmasına neden olur ve bu ifadeler kod içine veya yazıya geçirilmez. Çeviri, iletişimi zayıflatır ve bilgi işleme enerjisini azaltır. Farklı diyalektiklerin hiçbiri tüm ihtiyaçları karşılamadığı için ortak bir dil oluşturulamaz.

UBIQUITOUS LANGUAGE, bir projedeki tüm paydaşların (örneğin, geliştiriciler, iş alanı uzmanları, iş analistleri) anlayabileceği, ortak bir dilin oluşturulmasını ifade eder. Bu dil, projedeki herkesin kullanması gereken terimleri, sınıfları ve önemli işlemleri içerir. Bu terimler ve kavramlar, hem iş alanını anlamak hem de yazılım tasarımını geliştirmek için ortak bir temel sağlamak amacıyla kullanılır.

Chapter 4 – Isolating the Domain

Bir yazılım sisteminde, genellikle küçük bir bölüm doğrudan iş alanına özgü sorunları çözer. Fakat bu küçük bölümün önemi boyutuna göre büyüktür. En uygun çözümü uygulamak için model elemanlarını bir sistem olarak görmeliyiz. Modeldeki elemanlarını, gece gökyüzündeki takımyıldızlarını tanımlamaya çalışmak gibi, çok daha büyük bir nesne karışımından seçmek zorunda değiliz. İş alanı nesnelerini sistemdeki diğer fonksiyonlardan ayırmalıyız (Decoupling).

Bir kargo uygulamasında, kullanıcının bir kargonun varış yerini şehir listesinden seçsin diyelim. (1) tüm şehirler veritabanından sorgulanır (2) ekranda bir seçim alanı görünür, (3) kullanıcının girişi alınıp validasyon işlemi yapılır (4) seçilen şehir kargo ile ilişkilendirilir (5) değişiklik veritabanına kaydedilir. Tüm bu kod, aynı programın bir parçasıdır, ancak bunların sadece bir kısmı nakliye işi ile ilgilidir. Yazılım, çok farklı görevleri yürütmek için tasarım ve kod içerir. Kullanıcı girişini alır, business logic yürütür, veritabanına erişir, ağ üzerinde iletişim sağlar, kullanıcıya bilgi gösterir vb.

Separation of concerns (endişelerin ayrılması), bir yazılım sisteminin tasarımının farklı kısımlarının birbirinden izole edilmesini ifade eder. Bir bileşenin veya modülün yalnızca belirli bir sorumluluğa odaklanması ve diğer sorumluluklardan bağımsız olması anlamına gelir. Karmaşık görevleri yönetebilen programlar oluşturmak, separation of concerns uygulamayı gerektirir. Bu, tasarımın farklı bölümlerine izole bir şekilde odaklanmayı mümkün kılar. Aynı zamanda, ayrılmaya rağmen sistem içindeki karmaşık etkileşimler yürütülmelidir.

Bir yazılım sisteminin bölünmesinin çeşitli yolları vardır. Genel kabül görmüş bir yöntem de Katmanlı Mimaridir (Layered Architecture). Katmandaki bir element sadece aynı katmandaki ya da daha aşağıdaki katmanlardaki diğer elemanlarla bağımlıdır.

Önemli 4 katman;

  • User Interface (Presentation Layer)
  • Application Layer
  • Domain Layer (Model Layer) – (this layer is the heart of business software)
  • Infrastructure Layer

Karmaşık bir programı katmanlara böl. Her bir katman için sadece aşağıdaki katmanlara bağımlı olacak şekilde tutarlı bir tasarım geliştir. Üst katmanlara loose coupling sağlamak için standart mimari kalıpları kullan. İş alanı ile ilgili tüm kodu bir katmanda topla ve bunu kullanıcı arayüzü, uygulama ve altyapı kodlarından izole et. İş alanı nesnelerinin (domain), kendilerini görüntüleme, kendilerini depolama, uygulama görevlerini yönetme sorumluluğu yoktur ve bu sayede iş alanı modelini ifade etmeye odaklanırlar. Bu, bir modelin, iş bilgisini uygulamak için yeterince zengin ve açık olmasına yol açar.

Chapter 5 – A Model Expressed in Software

Entity, hayatta bir varlık olarak kabul edilen bir şeyi temsil eder. Bu varlık, zaman içinde değişebilir, ancak kimliği korunur. Bir müşteri, bir sipariş veya bir öğrenci birer entity olabilir. Value Objects, genellikle bir değeri veya kümeyi temsil eden nesnelerdir. Bir tarih aralığı, coğrafi koordinatlar veya para miktarı birer value object olabilir.

Value Object (Değer nesnesi), kendi başına benzersiz bir kimliğe sahip olmayan ve daha çok bir alanın tanımlanması için kullanılan nesneleri ifade eder.

Bir yemek siparişi olsun. Siparişin teslimat adresi, ürünlerin listesi, sipariş tarihi gibi bilgiler, siparişin bir değer nesnesini oluşturabilir. Bu bilgiler siparişin parçalarını tanımlar ancak tek başlarına ayırt edici bir anlam ifade etmezler. Bu halde veritabanında ayrı bir tabloda kayıtları tutulamaz.

Entity, bir benzersiz kimliğe sahip olan ve zaman içinde değişebilen nesneleri temsil eder. Veritabanında bir kayıt olarak tutulur ve bu kaydın bir primary key değeri vardır. Örneğin, öğrenci sınıfı id, isim ve yas bilgileri olsun. Bu kayıt zaman içinde güncellenebilir.

Value object, sadece içerdikleri değerlerle anlam ifade eden ve genellikle değişmez (immutable) olan nesnelerdir. Örneğin, address değer nesnesi sokak, sehir ve postaKodu bilgilerini içerisin.

Burada değer nesnesi öğrenci sınıfı içinde şu şekilde tutulabilir : @Embedded private Address address;

Embedded annotation’ı ile beraber veritabanına bu alanlar öğrenci tablosu içinde kaydedilir. Ayrıca bir tablo oluşturulmaz. Bu kayıtlara spring data jpa gibi bir orm’den (hibernate gibi bir orm’yi kullanan spring data jpa gibi veri erişim implementasyonu demek daha doğru) sorgu yapmak istediğimizde doğrudan findByAddressCity gibi bir sorgu yapamayız. Bunun yerine bir JPQL sorgusu yapılabilir.

@Query(“SELECT o FROM Ogrenci o WHERE o.address.city = :city”) şeklinde.

Kaynak: Domain-Driven Design Tackling Complexity in the Heart of Software By Eric Evans