Domain Centric Architecture ve Domain Driven Design
Domain Centrict Architecture
Bundan yıllar önce insanoğlu sistemin merkezinde dünyanın olduğunu güneşin ve diğer tüm gezegenlerin dünyanın etrafında döndüğünü düşünüp kabul etmişti. Ta ki aykırı birisi çıkıp sistemin merkezinde dünyanın değil de güneşin olduğunu diğer tüm gezegenlerin güneş etrafında döndüğünü ortaya çıkarana kadar. Her yeni fikir ve değişim gibi sistemin merkezinde dünyanın değil de güneşin yer aldığı fikri de uzun yıllar şiddetle karşı çıkılıp kabul görmemiş olsa da suan artık hepimizin kabul ettiği bir gerçek.
Yazılım mimarisinde de benzer yolda giden bir süreç var. Yıllardan beri kabul gören, yazılım mimarilerinin merkezine database’i oturtma yaklaşımı farklı düşünen birileri tarafından eleştirilmiş ve yazılım mimarisinin merkezine database yerine domain/use caselerin oturtulması fikri ortaya atılmıştır.
Yazının devamı boyunca mimarinin merkezine database’i oturtan yaklaşımı Data Centrict Architecture, domaini oturtan yaklaşıma da Domain Centric Architecture olarak isimlendireceğim.
- Data centrict architecture aslında hepimizin yıllardır kullandığı sistemin merkezine database’i koyan 3 katmanlı mimaridir. Katmanlar UI(Presentation), Business Logic ve Data Access Layer olarak oluşturulur ve bağımlılıklara baktığınız zaman UI katmanı Business Logic katmanına, Business Logic katmanı Data Access katmanına ve Data Access katmanı da Database’e bağımlıdır. Yani tüm bağımlılıklar doğrudan ya da dolaylı olarak database’de toplanır ki bu da aslında bu mimari tipinin neden Data Centrict Arcitecture olarak adlandırıldığıdır.
- Domain Centrict Architecture’da ise aşağıda da görüldüğü gibi tüm katman bağımlılıkları doğrudan ya da dolaylı olarak domain katmanında toplanır ve domain katmanı da hiç bir katmana bağımlı değildir.
Peki domain yazılım dilinde ne ifade eder?
Yazılım dünyasında domain; bir uygulama içerisinde bir biri ile bağlantılı olan ve uygulamanın logic’ini oluşturan ufak kümeler anlamına gelmektedir. İşin mimari kısmında ise bu katman business use caselerini ve entitylerini bulundurur.
Bu aşamada domain katmanının içerisindeki tüm field ve functionların direkt olarak iş sürecinden bir use case’e karşılık gelmesi gerektiğini ve teknik nitelikte olmayan iş biriminin dahi bu entity, field ve function isimlerini duydugunda direkt olarak businesstaki karşılığının kafasında canlandığı katman olduğunu bilmemiz yeterlidir. Örneğin, Product denildiğinde iş biriminin kafasında canlanan tüm ürün özellikleri sizin kodunuzda field olarak yer almalı ve ürün satışı use caseinde iş biriminin tariflediği tüm akış sizin SellProduct() metodunuzda direkt karşılık bulmalı. Yani domain katmanı iş birimi ve teknik ekibi ortak paydada buluşturan core business logici barındıran katmandır ve bu sebeple mimarinin merkezinde yer alır diyebiliriz.
Yazının ilerleyen kısımlarında ubiquitous language ve özellikle son kısım olan Domain Service başlıklarında domain kısmının neleri içermesi gerektiğinden ve neden mimarinin merkezinde yer aldığından tekrar bahsedeceğim.
Peki bu Domain Centrict Mimarinin çıkış noktası ne olmuştur?
“The first concern of the architect is to make sure that the house is usable, it is not to ensure that the house is made of brick.” -Uncle Bob
Uncle bob’un sözünde ne demek istediğini anlamak için mimarların yeni bir ev tasarladığını düşünelim. Öncelikli amaç bu evin kullanılabilir ve ev sahibinin ihtiyaçlarını görür olmasıdır. Geriye kalan güzelleştirmeler ve tasarımlar aslında mimari birer güzelleştirme ve iyileştirmedir yani yazılım için düşünürsek tasarım detayıdır.
Tasarlanan ev için neler olmazla olmaz neler sadece bir tasarım detayıdır bir düşünürsek..
- Evin içerisinde bulunan alan gereklidir. Olmazsa olmazdır.
- Evde gerekli odalar olmaz ise ev yapılış amacına hizmet etmez. Odalar gereklidir. Olmazsa olmazdır.
- Duvar gereklidir. Olmazsa olmazdır.
- Evin neyden yapıldığı ise sadece bir detaydır. Ev taştan, tahtadan veya betondan yapılabilir.
- Evdeki süslemeler (kapı kolu, lavabo ayna mutfak fayansları ve tasarımları vs) birer detaydır.
Bunu yazılıma uyarlarsak
- Domain gereklidir.
- Tüm use caselerin(business fonksiyonlarının) varlığı gereklidir. Uygulama esas olarak kullanıcının sorunlarını çözmeli ve isteklerini yerine getirmelidir
- Presentation (Sunum) bir detaydır. Presentation’u Webform, MVC vs’de yapabilirsiniz.
- Persistance bir detaydır. Verilerinizi RDBMS’de , NoSql çözümlerinde hatta bir json dosyasında bile tutabilirsiniz.
Buradan Uncle bob’un presentation ve persistance’ın önemsiz olduğunu söylediği gibi bir anlam çıkarmak yanlış olur tabi, sadece kullanıcının problemlerini çözmekteki esas odak noktalarımız olmadığını söylemektedir. Yoksa aşağıda detaylarından da bahsedeceğim elimizde bulunan bir business problemi bir anda redis mi mongo mu rdms mi derken bir teknoloj problemi halini alabilir.
Domain Centric Architecture Çeşitleri
3 domain centrict mimari de aynı ana noktaya farklı şekilde yaklaşmışlardır. Ancak hepsi bir ortak mantıkta birleşir. Hepsi domain layeri sistemin göbeğine koyar.
Domain Driven Design ise bize domaini merkeze koyan domain centric bir mimariyi efektif bir şekilde kurgulamamız için prensipler sunan bir design principle’dır diyebiliriz.
Domain Driven Design
Domain driven design(DDD) klasik tanımıyla kompleks business problemlerimizi efektif bir şekilde modellememize yarayan insan ilişkileri, mimari yaklaşım ve bu yaklaşımı uygularken izlememiz gereken prensipleri bizlere sunan domain centric bir yapıdır. DDD’ye göre yazılım projelerinde çıkan en büyük sorunlardan biri iletişim sorunudur. İş birimi ve teknik ekibin farklı bir dil konuşması, ihtiyaçların belirlenmesinde, geliştirilmesinde ve kapsamın büyütülmesinde uzun vadede sıkıntılar çıkarır ve ana hedef yani kod ile gerçeklenmesi gereken business probleminin bir anda teknoloji problemine dönüşmesi halini alır. DDD ise prensiplerini takip ederek iş birimi-teknik ekip arasındaki iletişim verimini maksimuma çıkarmayı ve bu süreci mimari anlamda çok iyi modellemeyi vaad eder.
Yazının ilerleyen kısımlarında DDD’yi şekillendiren ana kavramlar ile devam edeceğim. Bir sonraki yazımda ise implementasyon kısmına değinip DDD kodlaması üzerine yazacağım.
1. DDD’DEN ÖNCE KARŞIMIZA ÇIKAN PROBLEMLER
1.1.Kötü iletişim : Aslında DDD’den önce iletişimin kötü olması bir derece anlaşılabilir bir durum. Teknik ekip, teknik bir dil konuşurken business ekibi tamamen süreçsel bir iş dili konuşur ve burada iletişim sıkıntıları meydana gelir. Business ekibi için core bir business problemi veya gerçeklenmesi gereken bir use case varken bu teknik ekip için tamamen bir teknoloji problemi halini alabilir. Örneğin, business ekibi için bayilerden alınan ürünlerin müşterilere dağıtımı odak nokta iken teknik ekip için olay bu veriyi mongo da mı tutalım arkasına redis mi koyalım vs gibi dertler haline gelebilir. Bir ekibin odağı business iken diğer ekibin gündemi ve dili tamamen teknoloji ise bu iki ekip arasında zaten sağlıklı bir iletişim kurulması beklenemez.
1.2. Fazla Teknoloji odaklı olmak : Kulağa kötü gelmese de yukarıda da bahsettiğim gibi, gerçeklenmesi gereken bir business varken bir anda ana problemin teknoloji olması odaktan sapmalar meydana getirebilir. Dengeyi sağlamak gerekir. Zaten DDD’nın bir itirazı da daha fazla bilgiye sahip olan architecture takımının technology-based işlere entegre edilip görece daha az bilgiye sahip developerlara da core business işlerinin yaptırılmasıdır. Halbuki DDD’ye göre architecture takımının özellikle iş süreçlerinin sağlam modellenmesinde yer alması gerekir.
1.3. Kimliksiz Parçalar : DDD uygulamıyorsak kodumuzun içerisinde çokça kimliksiz parça görebiliriz. Managerlar, helperlar vs bu kimliksiz parçalar arttıkça koda baktığımızda business ile bağdaştırıp üzerinden düşünmek gitgide zorlaşacak bu da bizi yine iş birimini anlamaktan uzaklaştıracaktır. Aslında olayın özü çok basit. Nesne Tabanlı Programlama(OOP). OOP bize doğada olan varlıkları nesne tabanlı programlama imkanı sunarken biz bu nesne tabanlılıktan uzaklaşmamalı nesneleri gerçekten doğada olduğu gibi modellemeliyiz.
4. Anemic Domain Model : Yine DDD kullanmıyorsak ya da DDD’yi ilk implemente edişimiz ise sık karşılaşabileceğimiz bir durum. Anemic domain model, hiç bir fonksiyonelliği olmayan içerisinde hiç bir fonksiyon barındırmayan sadece propertylerden oluşmuş bir modeldir ve düşünüldüğünde OOP’e aykırı bir yapı teşkil eder.
Detaylı bilgi için : Anemic Domain Model Nedir?
2.NE ZAMAN DDD KULLANMALIYIZ?
Bu sorunun cevabı şirketten şirkete ve içinde bulunduğunuz case’e göre değişir. Ancak ben kendi kriterimi söyleyeceğim. Projede DDD kullanmadan önce ya da mevcut projeyi DDD’ye geçirmeden önce şu iki soruyu göz önünde bulundurabiliriz.
1. DDD kullanmanın şirkete katacağı rekabetçi avantaj nedir?
2. DDD kullanmanın maliyeti nedir?
Bu iki sorunun cevabını bir terazinin kefelerine oturtup çıkan sonuca göre DDD kullanıp kullanmayacağınıza karar verebilirsiniz.
Örneğin, siz bir e ticaret şirketiyseniz gidip de muhasebe uygulamanızı DDD’ye geçirmek, bunun için aşağıda bahsedeceğim bounded contextler ve ubiquitous lang vs gibi yapıları oturtmak iş birimleri ve teknik ekipleri bir araya getirmek ve kodlamanın maliyeti çok yüksek iken bir e ticaret sitesi için muhasebe uygulamasınn DDD olması rekabetçi bir avantaj sağlamaz. Ancak aynı kriterleri product domaininiz için düşünürseniz işler değişir. Product domainini DDD’ye taşımanın da maliyeti yüksek olmakla birlikte bir e ticaret şirketinde uçtan uca bir iyileştirme ve rekabetçi bir avantaj sağlar.
“DDD’e geçişe karar verdiğinizde DDD’nin prensipleri iki ana stage’de karşınıza çıkar. Bu stageler Stratejik tasarım ve Taktiksel tasarımdır.”
3. STRATEJIK TASARIM
Bu stage DDD’ye geçirilecek proje için kavramsal kararların alındığı ve işbirimi-teknik ekip arasındaki ortak dilin oturtulduğu stagedir. Stratejik tasarım, Ubiquitous language ve Bounded context aşamalarından oluşur.
3.1 Ubiquitous language
DDD’nin en temel prensiplerinden biri teknik ekiple iş birimi arasında ortak bir dil kurulmasıdır ve bu dil de ubiquitous language olarak adlandırılır. Bunun anlamı iş biriminde business olarak bulunan kavramların ve aksiyonların her birinin kod tarafında da karşılığı olmasıdır ve iş birimi bir kavram ya da aksiyondan bahsettiğinde bu direkt olarak teknik ekibin kafasında canlanmalı, aynı şekilde teknik ekip bir kavramdan bahsettiğinde de iş birimi bunu direkt anlayabilmelidir. Domain katmanı içerisindeki tüm yapılar da (class, entitiy, function, field vb.) bu amaca hizmet eder.
Bu dil inşa edilirken teknik ekip ve iş birimi bir araya gelmeli, kavramlar üzerine konuşulurken iş birimi teknik ekip tarafından anlaşılması zor, tekniğe kayan kavramların elimine edilmesini isteyebilmeli aynı şekilde teknik ekip de projeyi zora sokacak kavramlara müdahale edebilmelidir. Dil yaşayan bir olgu oluduğundan sürekli geliştirmeli ve iyileştirilmelidir. Eğer ki dile kavramsal yenilikler eklenirse karşılıklı olarak hızlı bir şekilde bu güncellenmelidir.
3.2 Bounded Context
DDD kompleks sistemlerde kullanılması önerilen bir yaklaşımdır. Kompleks bir domain, içerisinde sub domainler içerebilir. Bu sub domainleri implementasyon üzerinden düşünmeye devam edelim. Uygulamamızda Membership, Subscription, Invoicing, Api Server, Api Processor gibi her bir subdomain için otonom kısımlar geliştirdiğinizi düşünelim. Her biri kendi içinde bir uygulamaymış gibi hizmet verir. Bunların her biri bir Bounded Context’tir. Bounded Contextler genel olarak ubiquitous language’in sürdürülebilirliği ve subdomainin sınır/sorumluluklarının belirlenmesi gibi bir misyona sahiptir. Dolayısıyla yine domain katmanının üyesidirler.
Bounded contextlerin her birinin kendi modelleri vardır. Ancak bu otonom bounded contextler birbirleriyle veri/model paylaşmaz ve birbirlerine bağımlı değillerdir. Yani hiç bir Bounded context modeli sınırlarını geçip başka bir bounded contextte yer alamaz. Her bir bounded context mini bir app gibi hizmet verir. Her biri kendi domaininde ve böylece sadece bu component için anlamlı modellere sahiptir. Yani sizin için Product bounded contextindeki ProductVariant modelinin bir anlamı varken Order domainindeki ProductVariant modelinin anlamı farklı olabilir. Aynı durum tanımlanan kurallar için de geçerlidir. Modeller için bir bounded contextte tanımlanan kurallar başka bir dış bounded contextte anlam ifade etmeyebilir.
Ancak Bounded contextler birbirleriyle logicsel olarak ilişkili olabilirler. Bu durumda modeller birbiri içerisinde olmalıymış gibi algılanabilir ama bounded contextler black box gibi olmalıdır. Yani içinde ne döndüğü bilinmeden hizmet verebilmelidir. Peki o zaman gerçekten birbiri ile iletişimde olması gereken boundede contextler birbirleriyle nasıl haberleşir sorusu kafamıza takılabilir ki bu da sonraki yazının konusu olacak..
4. TAKTIKSEL TASARIM
Eğer yukarıda bahsettiğim stratejik tasarım fazını tamamlamış ve kafamızda konseptleri oturttuysak, artık işin implementasyona dokunan kısmına başlayabiliriz. Taktiksel tasarım…
4.1 Aggreagate / Aggreagete Root
Domain Driven Design’da konsepti ve ihtiyaçlarını implemente ederken, birbiri ile alakalı birden fazla Entity’nin bir iş akışını, kuralını gerçekleştirmek için beraber kullanılması “Aggregate” olarak tanımlanır . Bu aggreagete’in ana nesnesi de Aggreagete root olarak adlandırılır. Bir örnek vermek gerekirse, Product, ProductVariant, ProductDetailInfo gibi entityler çoğunlukla bir akışını gerçekleştirmek için beraber kullanılır ve bu sebeple aggreagate’tir diyebiliriz. Product entitysi de bunların aggreagate rootudur diyebiliriz. Aggreate rooutin ana amacı aggreagetin tutarlılığını sağlamaktır. Bu sebeple diğer tüm aggregate üyelerini aggregate root üzerinden manipule ederiz. Eğerki aggreagetteki bir nesneyi Aggregate Root’dan bağımsız değiştirirseniz Aggregate Root konseptin valid state olduğunu bilemez. Yine bir örnek üzerinden gitmek gerekirse Araba, motor, lastik, direksiyon gibi entitylerimiz olsun. Bunlar bir logici gerçekleştirmek için çoğunlukla beraber kullanılacakladır. Dolayısıyla bu gruba Aggregate diyebiliriz. Bu grubun Aggregate Rootu da Araba nesnesi olacaktır. Nedenini ise bir örnek üzerinden düşünelim, Lastikteki bir sorunun arabadan bağımsız çözülmesi pek mümkün değildir. Lastik arabaya entegreyken bir anlam ifade eder. Arabanın lastikteki değişiklikten haberdar olması ve hatta bir sürüş ile validliğini teyit etmesi gerekir. Dolayısıyla lastiğe yapılacak her değişiklik araba üzerinden uygunluk durumuna göre yapılır mesela bir otomobile traktör lastiği takamayız gibi. Diğer tüm entitiyleri de aynı konseptte düşünürsek Araba entitysi Aggreagate Roottur çünkü aggreagetin tutarlılığından sorumludur diyebiliriz.
Buradaki en önemli nokta bu grup transactional olarak bir bütün halide düşünülür ve böylelikle entity’lerin bütünlüğü sağlanmış olur
Projede direkt Aggregate Root’u belirlemek yerine aggreageti bildiğimizden emin olmalı ve Aggregate Root’un Aggregate Consistency’sinden sorumlu olduğundan emin olmalıyız. Çünkü container olarak diğer objeleri içinde barındırması bir nesneyi Aggregate yapmaz.
A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An aggregate will have one of its component objects be the aggregate root. Any references from outside the aggregate should only go to the aggregate root. The root can thus ensure the integrity of the aggregate as a whole.
4.2 Entity Object ve Value Object
Domain Driven Design’da nesnelerimizi iki ana grupta ayrıştırırız. Bunlar Entity Objectler ve Value Objectlerdir.
- Entity objeleri kimlik sahibi objelerdir. Yani yazılımsal olarak ID’si olan nesneler entitydir diyebiliriz. Ancak bu tanım kavramsal olarak biraz sığ kalır. Evet entity’ler kimlikleri olan objelerdir ama kimliği olan objeler DDD’de bizim için aslında ne ifade eder bunu bir örnek üzerinden inceleyelim.
Person person = new Person{ Id = 2, Name = 'Çağatay', Surname ..}
Yukarıda tanımladığımız person nesnemiz var. Bu person nesnesi Id’ye sahip olduğu için entitydir. Ancak neden Id’ye sahiptir ve bir nesne ne zaman Id’li yaratılır?
Bu nesnenin Id’li olmasının nesneye sağladığı fark, nesnenin uniqueliğini ve aynılığını garanti etmesidir. Nesnedeki Adress propertysi değişse bile bu nesne hala Id=2 deki nesnedir ya da Name’i Çağatay değil de Mustafa da olsa bu nesne özünde yine aynı nesnedir. Örneği daha da somutlaştırmak için Id yerine TC kimlik no’yu düşünelim. Tc kimlik no’ya sahip bir insanın adı, soyadı, ikamet adresi veya herhangi bir bilgisi değişse de hatta tüm bilgileri dahi değişse o kişi aynı kişidir ve devlet bu bireyi unique tcsinden aynı kişi olarak tanımlayabilir.
- Value objectler ise kimliksiz nesnelerdir. Kimliksiz nesnelerin herhangi bir fieldinin değişmesi o nesneyi artık bambaşka bir nesne yapar. Zaten value objectlerin hangi nesne olduğunun bizim için önemi de olmamalıdır. Örnek olarak Para objesini düşünebiliriz. Sizin için cebinizdeki 2 tane 20 TL nin birbirinden hiç bir farkı yoktur yani value objecttir. Yani value objectler birbirleri yerine geçebilir. Yazılım dilinde düşünürsek de
Money money = new Money() { Amount='20' , Currency='TR' };
nesnesinin Id’si yoktur. Gelip kod üzerinde money.Amount=50 yaptığınız an bu nesnenin eski 20 TL ile hiç bir bağı yoktur artık bir 50 tldir ve eski 20 tlden söz edilemez çünkü kimliği yoktur.
Ancak unutmamamız gereken birşey vardır. Yukardaki örnekler genel konsepti özetlemek için olup sizin value object ve entitylerinizi sizin kendi senaryonuz belirleyecektir. Demek istediğimin anlaşılması için yukarıdaki örnekleri farklı bir senaryoya oturtalım.
Para örneğini merkez bankası için yazdığımız bir uygulama üzerinden düşünürsek her paranın kendine özel bir Seri Nosu yani kimliği vardır ve merkez bankası için her para özeldir. Yani entitiy objecttir.
Bir avm’ye kaç kişinin girip çıktığını tespit edecek bir uygulama yazıyorsak ve tek odağı sadece giren çıkan kişi sayısı ise burada Person’ın kimlikli olması gerekmeyebilir. Yani bir kişi ile arkasından giren diğer kişi bizim için fark ifade etmez mühim olan count’tur. Bu durumda Person value object halini alabilir.
5. APPLICATION ve DOMAIN SERVICE
Domain Driven Design’daki önemli ayrımlardan biri de application servis ve domain servis ayrımıdır. Bu fark en iyi kodlayarak anlaşılacak bir fark olsa bile kısaca özetlemek gerekirse,
Domain servis sizin core business use caselerinizi barındıran ve iş birimi için de anlamlı olan caseleri içeren servistir. Bu sebeple ubiquitous languagein kurulmasında rol alır. Hiç bir katmana bağımlılığı yoktur. Çünkü diğer tüm katmanlardan gelecek bağımlılıklar sizin ubiquitous languageinizi bozar. Örneğin, cachleme, loglama, redis call vs gibi metotların domain servis içerisinde herhangi bir sebepten kullanılması o metodu dil olarak iş birimine anlamız hale getirebilir.
Application servis ise domain servisteki use case fonksiyonelliklerini uygun iş akışa göre çağırarak bir fonksiyonellik oluşturan servistir. Bu sebeple Application serviste genellikle orchestrate design patternler(mediator) kullanılır. Genellikle domain servis use caselerini kullanarak transaction ve persistence ile ilgilenir, infra ve external depencenylere de bu katmandan ulaşılabilir. Çünkü yukarıda da bahsettiğim gibi infra ve external dependencylerden gelen metot ve kavramlar iş birimiyle aramızda kurulan ubiquitous language’i bozacağından domain serviste yer almaz.
Bu yazıyı kavramlar üzerinden ilertlettiğimden kod üzerinden olan örnekleri bir sonraki yazımda detaylı olarak vereceğim ancak kafamızda canlanması adına, Kütüphaneden ödünç kitap almamızı sağlayan bir uygulamamız olduğunu varsayalım.
KitapÖdünçAl( ) adında bir metodumuz olsun. Metodun yaptığı iş kitabı isteyen kişinin uygunluk kriterini sorgulamak ve uygunsa kitabı vermek olsun. Bu iş birimi tarafından da , teknik ekip tarafından da rahatlıkla anlaşılabilecek bir domain rule’dir ve domain serviste yer alır.
Ancak, domain servisteki metotları kullarak bir kullanıcı akışı yani use case tasarlarsak
- Metot çağırımını logla.
- Öğrenci kartı domaininden check fonksiyonu ile öğrenciyi sistemde sorgula.
- Kitap domanininden kitabı sorgula.
- Kitap varsa Kitabı öğrenciye ödünç ver.
- Transaction var ise save ve dispose et.
- Çıktıyı cachle.
- Email servisi ile öğrenciye aldığı kitabın bilgisini ilet.
- Metot bitişini logla.
Şeklinde tamamen hayal ürünü olan akışımdaki fonksiyonellik bir application servis üyesi fonksiyondur ve buradaki akış stepleri domain servisteki domain rulelari uygun sıralara göre kullarak ve iş birimi için anlamlı olmayan cache, transaction, logging gibi yapıları kullarak oluşturulur. Bu yüzden de yukarıda söylediğim gibi burada uygun bir ochestra pattern ile farklı servis metotları uygun akışta yönetilir.
Bu yazımda domain centric architecture ve domain driven desing’in ana kavramlarından bahsetmeye çalıştım. Ancak bu domain odaklı dünyanın implementasyonuna geçildiğinde nasıl bir yol izlenir? katmanlar nasıl oluşturulur? bounded contextler, aggreagateler, entity ve value objectler nasıl belirlenir? bounded contextler nasıl veri paylaşır, domain servis ve application servis’e tam olarak hangi metotları yazmalıyım? gibi implementasyon konularını da bir sonraki yazımda DDD odaklı bir mimari üzerinden anlatacağım. Umarım faydalı olmuştur.
Cok kaliteli bir yazi olmus. Devamini sabirsizlikla bekliyorum.
Gerçekten aradaki farkları açıklayan kaliteli bir yazı olmuş. Kod üzerinden örnekleri sabırsızlıkla bekliyorum.
Fevkalade bir yazı, elinize sağlık
Gercekten efsane anlatilmis. Ama devaminda bahsedilen kismin gelmemis olmasi uzdu. Insallah kisa zamanda devami da gelir.
Emeğinize sağlık.
Çok faydalı bir içerik olduğunu düşünüyorum. Devamını dört gözle bekliyorum.
Gerçekten çok kaliteli ve açıklayıcı bir yazı olmuş. Dilimizde bu şekilde özenle ve ayrıntılı yazılara ihtiyacımız var. Diğer arkadaşların da dediği gibi kesinlikle devamı biran önce gelmeli.
Sans eseri denk geldim ama cok guzel bir yazi olmus. Elinize saglik. Devamini bende dort gozle bekliyor olacagim.
Harika bir yazı gerçekten ,emeğinize sağlık
Elinize sağlık.
Şu ana kadar DDD ile ilgili okuduğum en açık ve başarılı yazı. Elinize sağlık. Devamını heyecanla bekliyorum 🙂
Harika bir yazı. Başarılarınızın devamını dilerim.
Devam yazısı nerede :/