DDD'deki istisnalar


12

DDD öğreniyorum ve bazı durumlarda istisnalar atmayı düşünüyorum. Bir nesnenin kötü bir duruma giremediğini anlıyorum, burada istisnalar iyi, ancak birçok örnekte istisnalar da var, örneğin veritabanında mevcut e-postaya sahip yeni kullanıcı eklemeye çalışıyorsak.

public function doIt(UserData $userData)
{
    $user = $this->userRepository->byEmail($userData->email());
    if ($user) {
        throw new UserAlreadyExistsException();
    }

    $this->userRepository->add(
        new User(
            $userData->email(),
            $userData->password()
        )
    );
}

Bu nedenle, bu e-postaya sahip kullanıcı varsa, uygulama hizmetinde bir istisna yakalayabiliriz, ancak try-catch bloğunu kullanarak uygulamanın çalışmasını kontrol etmemeliyiz.

Bunun için en iyi yol nasıl?


1
Etki alanı hizmetinin (işleyicilerin) istisnaları atması iyidir.
Andy

Yanıtlar:


21

Sorunlu alanın kısa bir gözden geçirmesiyle başlayalım: DDD'nin temel ilkelerinden biri, iş kurallarını, uygulanması gereken yerlere mümkün olduğunca yakın yerleştirmektir. Bu son derece önemli bir kavram çünkü sisteminizi daha "uyumlu" kılıyor. Kuralların "yukarı doğru" hareket ettirilmesi genellikle anemik bir modelin işaretidir; burada nesneler sadece veri torbalarıdır ve uygulanacak verilerle kurallar uygulanır.

Anemik bir model DDD ile yeni başlayan geliştiriciler için çok anlamlı olabilir. Bir Usermodel ve EmailMustBeUnqiueRulee-postayı doğrulamak için gerekli bilgiler enjekte edilen bir model oluşturursunuz . Basit. Zarif. Sorun şu ki, bu "tür" düşünce, doğada temel olarak prosedüreldir. DDD değil. Ortaya çıkan şey, düzinelerce Rulesdüzgün bir şekilde sarılmış ve kapsüllenmiş bir modülle kalmanızdır , ancak artık değiştirilemeyecekleri noktaya tamamen bağlamsızdırlar, çünkü ne zaman / nerede uygulandıkları açık değildir. bu mantıklı mı? Bu olabilir apaçık bir o olmak EmailMustBeUnqiueRulebir oluşturulmasına ilişkin uygulanacak Userhakkında, ama ne UserIsInGoodStandingRule?. Yavaş ama emin adımlarla,Rulesonların bağlamı dışında sizi anlamak zor (ve bu yüzden değiştirilemez) bir sistem bırakır. Kurallar, yalnızca gerçek crunching / yürütme o kadar ayrıntılı olduğunda kapsüllenmelidir; modeliniz odaklanmaya başlar.

Şimdi özel sorunuza: Service/ CommandHandleratmakla ilgili sorun Exception, iş mantığınızın alan adınızdan sızmaya ("yukarı") başlamasıdır. Bir e-postanızı neden bilmeniz Service/ CommandHandlerbilmeniz gerekiyor? Uygulama hizmet katmanı genellikle uygulama yerine koordinasyon için kullanılır. Bunun nedeni ChangeEmail, sisteminize bir yöntem / komut eklersek gösterilebilir . Şimdi, BOTH yöntemlerinin / komut işleyicilerinin benzersiz çekinizi içermesi gerekir. Bu, bir geliştiricinin anı "çıkarmak" için cazip gelebileceği yerdir EmailMustBeUniqueRule. Yukarıda açıklandığı gibi, o rotaya gitmek istemiyoruz.

Bazı ek bilgi sıkıntıları bizi daha fazla DDD cevabına götürebilir. Bir e-postanın benzersizliği, bir Usernesne koleksiyonunda uygulanması gereken bir değişmezdir . Alan adınızda " Usernesne koleksiyonu" nu temsil eden bir kavram var mı ? Sanırım buraya nereye gittiğimi görebiliyorsunuz.

Bu özel durum için (ve koleksiyonlar arasında değişmezlerin zorla uygulanmasını içeren birçok) bu mantığı uygulamak için en iyi yer sizin olacaktır Repository. Bu özellikle kullanışlıdır, çünkü Repositorybu tür bir doğrulamayı (veri deposu) yürütmek için gerekli ekstra altyapıyı da "bilir". Sizin durumunuzda, bu kontrolü addyönteme yerleştiririm. Bu mantıklı mı? Kavramsal olarak, Usersisteminize gerçekten a ekleyen bu yöntemdir . Veri deposu bir uygulama ayrıntısıdır.


Ne demek istediğini sorabilir miyim Moving rules "upwards" is generally a sign of an anemic model? Yukarı doğru uygulama katmanı anlamına mı gelir? veya alan modeline?
Anyname Donotcare

1
“Yukarı” uygulama katmanınıza doğru (katmanlı bir mimari düşünün) anlamına gelir. Yukarıda buna değindim, ancak kuralların yukarı doğru hareket etmesinin nedeni anemik bir modelin bir işaretidir, veri ve davranışın temel bir etki alanı modeline sahip olmanın tüm amacını yenecek şekilde ayrılmasını temsil etmesidir. Bir e-postayı doğrulama, bir e-posta göndermekten ayrı bir modüldeyse, Emailmodelinizin göndermeden önce değişmezler için denetlenen bir veri çantası olması gerekir. Bkz: softwareengineering.stackexchange.com/questions/372338/…
king-side-slide

2
Etki Alanı Mantığını Depoya Taşıma yanlış. etki alanı kuralını etki alanı katmanında birleştirilmiş kök tarafından zorlamalısınız.
Arash

2
@Arash Set doğrulaması zor ve genellikle DDD ile iyi oynamıyor. Bu işlemi denemeden önce (a User) ekleyerek bir sürecin çalışacağını doğrulamayı seçmeniz veya bu belirli değişmez türün alanınızda düzgün bir şekilde kapsüllenmeyeceğini kabul etmeniz gerekir. Birincisi, prosedürel bir paradigmaya yol açan veri ve davranış ayrımıdır. Bu ideal olandan daha az. Doğrulama , veriler etrafında değil , veriler etrafında olmalıdır . Ayrıca, yalnızca bu kuralı kontrol etmeye yarayan bir etki alanı hizmeti oluşturmak için ne faydası vardır? Görünüşte, bu hizmet ...
kral tarafı slayt

2
@Arash çiftler senin Repository, Userbu nedenle, bu değişmeyen ve için yine de bastırıyorlar pürist vizyona ulaşmak etmez. Havuz uygulamaları alanın bir parçasıdır ve bu nedenle belirli sorumluluklar verilebilir.
kral Yandan sürgülü

0

Uygulamanızın her katmanına doğrulama uygulayabilirsiniz. Hangi kuralların uygulamanıza bağlı olduğu nereye uygulanmalıdır.

Örneğin, işletmeler iş kurallarını temsil eden yöntemler uygularken, kullanım örnekleri uygulamanıza özgü kuralları uygular.

Gmail gibi bir e-posta hizmeti oluşturuyorsanız, "kullanıcıların benzersiz bir e-posta adresine sahip olması gerekir" kuralının bir iş kuralı olduğu söylenebilir.

Yeni bir CRM sistemi için bir kayıt işlemi oluşturuyorsanız, bu kural en iyi şekilde bir kullanım senaryosunda uygulanır, çünkü bu kural aynı zamanda kullanım durumunuzun bir parçası olacaktır. Ayrıca, kullanım örneği testlerinizdeki depo çağrılarını kolayca saplayabileceğiniz için test etmek de daha kolay olabilir.

Ek güvenlik için, bu kuralı deponuzda da uygulayabilirsiniz.

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.