Domain Driven-Design - Varlık probleminde dış bağımlılıklar


23

Domain-Driven-Design'ı başlatmak isterdim, ancak başlamadan önce çözmek istediğim birkaç sorun var :)

Bir Grup ve Kullanıcılarım olduğunu ve kullanıcı bir gruba katılmak istediğinde, bir groupsService.AddUserToGroup(group, user)yöntem çağırdığımı hayal edelim . DDD'de yapmalıyım ki group.JoinUser(user)bu oldukça iyi görünüyor.

Sorun, kullanıcı eklemek için bazı doğrulama kuralları varsa veya kullanıcı gruba eklendiğinde bazı harici görevlerin başlatılması gerekiyorsa ortaya çıkar. Bu görevlere sahip olmak, kuruluşun dış bağımlılıklara yol açmasına neden olacaktır.

Bir örnek olabilir - kullanıcının en fazla 3 gruba katılabileceği bir kısıtlama. Bu, bunu doğrulamak için group.JoinUser yönteminin içindeki DB aramalarını gerektirir.

Ancak, bir Kurumun bazı dış hizmetlere / sınıflara bağlı olması, bana çok iyi ve "doğal" görünmüyor.

DDD'de bununla baş etmenin doğru yolu nedir?

Yanıtlar:


15

Bir Grup ve Kullanıcılarım olduğunu ve kullanıcı bir gruba katılmak istediğinde, groupService.AddUserToGroup (group, user) yöntemini çağırdığımı varsayalım. DDD'de, oldukça iyi görünen group.JoinUser (user) yapmalıyım.

Ancak DDD ayrıca, eğer elinizdeki görev çok karmaşıksa veya bir varlık modeline uymuyorsa, görevleri yerine getirmek için (vatansız) hizmetleri kullanmaya teşvik eder. Etki alanı katmanında hizmetlerin olması sorun değil. Ancak, etki alanı katmanındaki hizmetler yalnızca iş mantığını içermelidir. Diğer yandan, harici görevler ve uygulama mantığı (bir e-posta gönderme gibi), etki alanı servisini, uygulama katmanında kullanmalıdır; örneğin, onu paketleyen ayrı bir (uygulama) hizmeti alabilir.

Bir kullanıcı eklemek için bazı doğrulama kuralları varsa sorun ortaya çıkıyor ...

Doğrulama kuralları etki alanı modeline aittir! Etki alanı nesnelerinin (varlıklar vb.) İçine alınmalıdırlar.

... veya kullanıcı gruba eklendiğinde bazı harici görevlerin başlatılması gerekir. Bu görevlere sahip olmak, kuruluşun dış bağımlılıklara yol açmasına neden olacaktır.

Ne tür bir dış görevden bahsettiğinizi bilmeme rağmen, bunun bir e-posta göndermek gibi bir şey olduğunu varsayıyorum. Fakat bu gerçekten etki alanı modelinizin bir parçası değil. Uygulama katmanında yaşamalı ve orada asılmalı. Uygulama katmanınızda etki alanı hizmetleri ve bu görevleri gerçekleştiren varlıklar üzerinde çalışan bir hizmetiniz olabilir.

Ancak, bir Kurumun bazı dış hizmetlere / sınıflara bağlı olması, bana çok iyi ve "doğal" görünmüyor.

Doğal değil ve olmamalı. İşletme, sorumluluğu olmayan şeyler hakkında bilgi sahibi olmamalıdır. Servisler varlık etkileşimlerini düzenlemek için kullanılmalıdır.

DDD'de bununla baş etmenin doğru yolu nedir?

Senin durumunda, ilişki muhtemelen iki yönlü olmalıdır. Kullanıcının gruba katılıp katılmayacağı veya kullanıcıyı alıp almadığı, etki alanınıza bağlıdır. Kullanıcı gruba katılıyor mu? Yoksa kullanıcı bir gruba eklenir mi? Alanınızda nasıl çalışır?

Her neyse, iki yönlü bir ilişkiniz var ve böylece kullanıcının zaten kullanıcı toplamında olduğu grupların miktarını belirleyebilirsiniz. Kullanıcıyı gruba veya gruba kullanıcıya iletip iletmemeniz, sorumlu sınıfı belirledikten sonra teknik olarak önemsizdir.

Doğrulama daha sonra işletme tarafından gerçekleştirilmelidir. Her şey, e-posta göndermek gibi, teknik şeyler de yapabilen uygulama katmanının bir hizmetinden çağrılır.

Ancak, doğrulama mantığı gerçekten karmaşıksa, bir etki alanı hizmeti daha iyi bir çözüm olabilir. Bu durumda, iş kurallarını oraya alın ve ardından uygulama katmanınızdan çağırın.


Fakat varlık dışında çok fazla mantık taşırsak, içeride ne saklanmalı?
SiberianGuy,

İşletmenin doğrudan sorumlulukları! Örneğin "kullanıcı bir gruba katılabilir" diyebilirseniz, kullanıcının sorumluluğu size aittir. Bazen teknik nedenlerden dolayı tradeoff kararları vermelisin. Ben de iki yönlü ilişkilerin büyük bir hayranı değilim, ama bazen modele en uygun olanı. Etki alanı hakkında konuşurken dikkatlice dinleyin. "Bir işletme var ..." "Bir işletme olabilir ..." Bu tür cümleler duyduğunuzda, o zaman bu işlemler büyük olasılıkla işletmeye aittir.
Falcon,

Ayrıca, iki veya daha fazla alakasız nesnenin bir şeyi başarmak için bir göreve katılması gerektiğinde bir servise ihtiyacınız olduğunu da bilirsiniz.
Falcon,

1
Cevabınız için teşekkürler Falcon! BTW, her zaman durumsuz hizmetleri kullanmaya çalıştım, bu yüzden DDD'ye bir adım daha yakınım :) Diyelim ki bir etki alanında, bu UserJoinsToGroup işleminin Grup'a ait olduğunu söyleyelim. Sorun şu ki, bu işlemi doğrulamak için, Kullanıcının zaten ne kadar gruba katıldığını bilmem gerekiyor (zaten bir işlemi reddetmek için> 3). Veritabanını sorgulamam gerektiğini bilmek için. Bunu Grup varlığından nasıl yapabilirim? Başka bir örneğim daha var, DB'ye doğal olarak ait olması gereken işlemlerde dokunmam gerektiğinde (gerektiğinde onları
göndereceğim

2
Peki, eğer düşünürsem: Peki ya bir GroupMembership varlığı? Bir fabrika tarafından inşa edilebilir ve bu fabrika işyerlerine erişebilir. Bu iyi bir DDD olur ve üyelik oluşumunu kapsar. Fabrika, Depolara erişebilir, bir Üyelik yaratır ve bunu sırasıyla kullanıcıya ve gruba ekler. Bu yeni varlık aynı zamanda ayrıcalıkları da kapsayabilir. Belki bu iyi bir fikirdir.
Falcon,

3

Doğrulama sorununa yaklaşma yöntemim şu şekilde: Adında bir Etki Alanı Hizmeti oluşturun MembershipService:

class MembershipService : IMembershipService
{
   public MembershipService(IGroupRepository groupRepository)
   { 
     _groupRepository = groupRepository;
   }
   public int NumberOfGroupsAssignedTo(UserId userId)
   {
        return _groupsRepository.NumberOfGroupsAssignedTo(userId);
   }
}

Grup kuruluşuna enjekte edilmesi gerekir IMemberShipService. Bu, sınıf düzeyinde veya yöntem düzeyinde yapılabilir. Bunu yöntem düzeyinde yaptığımızı varsayalım.

class Group{

   public void JoinUser(User user, IMembershipService membershipService)
   {
       if(membershipService.NumberOfGroupsAssignedTo(user.UserId) >= 3)
         throw new BusinessException("User assigned to more than 3 groups. Cannot proceed");

       // do some more stuff
   }
}

Uygulama hizmeti: daha sonra sınıfın yöntemine geçebileceği, Yapıcı enjeksiyonunu kullanarak GroupServiceenjekte IMemberShipServiceedilebilir .JoinUserGroup


1
Okunabilirlik için yazınızdaki kaynak kodu biçimlendirmeyi düşünebilirsiniz
Benni
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.