Şişirilmiş Alan Nesnelerinden Kaçınmak


12

Bir DDD yaklaşımı kullanarak şişirilmiş Hizmet katmanımızdan Alan katmanımıza veri taşımaya çalışıyoruz. Şu anda hizmetlerimizde birçok yere yayılmış ve mirastan faydalanmayan birçok iş mantığımız var.

Ticaretimizin çoğunun odak noktası olan merkezi bir Domain sınıfımız var. Trade nesnesi kendini nasıl fiyatlandıracağını, riski nasıl tahmin edeceğini, kendini nasıl doğrulayabileceğini vb. Bilecektir. Sonra koşulluları polimorfizm ile değiştirebiliriz. Örneğin: SimpleTrade kendisini bir şekilde fiyatlandıracak, ancak ComplexTrade kendisini başka bir şekilde fiyatlandıracak.

Bununla birlikte, bunun Ticaret sınıflarını şişireceğinden endişe duyuyoruz. Gerçekten kendi işlemesinden sorumlu olmalı, ancak daha fazla özellik eklendikçe sınıf büyüklüğü katlanarak artacak.

Yani seçeneklerimiz var:

  1. İşlem mantığını Ticaret sınıfına koyun. İşleme mantığı artık ticaretin türüne göre polimorfiktir, ancak Ticaret sınıfı artık birden fazla sorumluluğa (fiyatlandırma, risk vb.) Sahiptir ve büyüktür.
  2. İşlem mantığını TradePricingService gibi başka bir sınıfa yerleştirin. Artık Ticaret mirası ağacıyla polimorfik değil, ancak sınıflar daha küçük ve test edilmesi daha kolay.

Önerilen yaklaşım ne olurdu?


Sorun değil - Göçü kabul etmekten mutluluk duyuyorum!


1
"daha fazla özellik eklendikçe sınıf boyutu katlanarak artacaktır" - herhangi bir programcı "katlanarak" kelimesini yanlış kullanmaktan daha iyisini bilmelidir.
Michael Borgwardt

@Piskvor bu sadece aptalca
Arnis Lapsa

@Arnis L .: Düşünceli yorumunuz için teşekkür ederiz. Bu, benim yorum ile birlikte, "22 Kasım, 22:19 stackoverflow.com göç etti" teklif olduğunu unutmayın. Şimdi "bu programcılar daha iyi olurdu" yorumumu kaldırdım; şimdi, eklemek istediğiniz bir şey var mı, ya da ifade etmek istediğiniz tek fikir bu muydu?
Piskvor binadan ayrıldı

Yanıtlar:


8

Domain Driven'a gidiyorsanız, Ticaret sınıfınıza toplu bir kök gibi davranmayı ve sorumluluklarını diğer sınıflara ayırmayı düşünün.

Her bir fiyat ve riskin birleşimi için bir Ticaret alt sınıfıyla sonuçlanmak istemezsiniz, bu nedenle bir Ticaret Fiyat ve Risk nesneleri (kompozisyon) içerebilir. Fiyat ve Risk nesneleri gerçek hesaplamaları yapar, ancak Ticaret dışında hiçbir sınıf tarafından görülemez. Yeni sınıflarınızı dış dünyaya açığa çıkarmadan Ticaret'in boyutunu azaltabilirsiniz.

Büyük kalıtım ağaçlarından kaçınmak için kompozisyon kullanmaya çalışın. Çok fazla miras, modele gerçekten uymayan davranışlarda ayakkabı çekmeye çalıştığınız durumlara yol açabilir. Bu sorumlulukları yeni bir sınıfa çıkarmak daha iyidir.


Katılıyorum. Nesneleri, sorunu modellemeye çalışmak yerine çözümü oluşturan davranışlar (Fiyatlandırma, RiskAssessment) açısından düşünmek, bu yekpare sınıflardan kaçınır.
Garrett Hall

Ayrıca katılıyorum. Kompozisyon, belirli, tek sorumlulukları olan çok sayıda küçük sınıf, özel yöntemlerin sınırlı kullanımı, çok sayıda mutlu arayüz, vb.
Ian

4

Sorunuz beni kesinlikle Strateji Kalıbı hakkında düşündürüyor . Daha sonra, aradığınıza benzer çeşitli ticaret / fiyatlandırma stratejilerinde geçiş yapabilirsiniz TradePricingService.

Kesinlikle burada alacağınız tavsiye miras yerine kompozisyon kullanmak olduğunu düşünüyorum.


2

Benzer bir durumda kullandığım olası bir çözüm, adaptör tasarım modelidir (başvurulan sayfada çok sayıda örnek kod bulunur). Muhtemelen ana yöntemlere kolay erişim için delegasyon tasarım deseni ile birlikte .

Temel olarak, Trader işlevselliğini bir dizi ayrık alana böldünüz - örneğin fiyatların, risklerin, validasyonun hepsi farklı alanlar olabilir. Her alan için, farklı gerekli varyantlardaki tam işlevselliği işleyen ayrı bir sınıf hiyerarşisi uygulayabilirsiniz - hepsi her alan için ortak arabirimdir. Daha sonra ana Trader sınıfı en temel verilere indirgenir ve gerektiğinde oluşturulabilen bir dizi işleyici nesneye referanslar. Sevmek

interface IPriceCalculator {
  double getPrice(ITrader t);
}
interface ITrader {
  IPriceCalculator getPriceCalculator();
}
class Tracer implements ITrader {
  private IPriceCalculator myPriceCalculator = null;
  IPriceCalculator getPriceCalculator() {
    if (myPriceCalculator == null)
      myPriceCalculator = PriceCalculatorFactory.get(this);
    return myPriceCalculator;
  }
}

Bu yaklaşımın en büyük avantajlarından biri, örneğin fiyatların ve fiyatların olası kombinasyonlarının tamamen ayrılması ve böylece gerektiğinde birleştirilebilmesidir. Çoğu programlama dilinin tek iş parçacıklı kalıtımıyla bu oldukça zordur. Hangi kombinasyonun kullanılacağına karar vermek çok geç hesaplanabilir :-)

Genellikle bağdaştırıcı sınıflarını tutmaya çalışıyorum - örn. IPriceCalculatorYukarıdaki alt sınıflar - vatansız. Yani bu sınıflar, oluşturulması gereken örnek sayısını azaltmak için mümkünse herhangi bir yerel veri içermemelidir. Bu yüzden genellikle ana uyarlanmış nesneyi getPrice(ITrader)yukarıdaki gibi olduğu gibi tüm yöntemlerde bir argüman olarak sağlarım .


2

alanınız hakkında fazla bir şey söyleyemez, ancak

Ticaretimizin çoğunun odak noktası olan merkezi bir Domain sınıfımız var.

... bu benim için bir koku. Muhtemelen sınıfın farklı sorumluluklarını çizmeye ve sonunda farklı agregalara ayrıştırmaya çalışacağım. Toplamalar daha sonra ilgili paydaşların / alan uzmanlarının rolleri ve / veya bakış açıları etrafında tasarlanacaktır. Fiyat ve Risk aynı davranış / kullanım senaryosunda yer alıyorsa, muhtemelen aynı topluluğa ait olacaktır. Ancak, ayrılırlarsa, ayrı agregalara ait olabilirler.

Belki RiskEvaluation , alan adınızda ayrı bir varlık olabilir, sonunda belirli bir yaşam döngüsü (gerçekten söyleyemem, sadece spekülasyon yapıyorum ... alan adınızı biliyorsunuz, bilmiyorum), ancak anahtar örtük kavramlar yapmaktır açıktır ve davranıştan değil, yalnızca eski veri bağlantısından kaynaklanabilecek bağlantılardan kaçınmaktır.

Genel olarak, beklenen davranışı ve ilgili bileşenlerin farklı yaşam döngülerini düşünürüm. Sadece gruplandırılmış verilerin üstüne davranış eklemek şişirilmiş nesneler oluşturur. Ancak veriler mevcut bir veri odaklı tasarıma göre gruplandırılmıştır, bu yüzden buna bağlı kalmanıza gerek yoktur.

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.