หลีกเลี่ยงวัตถุโดเมนป่อง


12

เรากำลังพยายามย้ายข้อมูลจากเลเยอร์บริการที่ป่องของเราไปยังเลเยอร์โดเมนของเราโดยใช้วิธี DDD ขณะนี้เรามีตรรกะทางธุรกิจจำนวนมากในบริการของเราซึ่งกระจายไปทั่วสถานที่และไม่ได้รับประโยชน์จากการสืบทอด

เรามีโดเมนระดับกลางซึ่งเป็นจุดสนใจของงานส่วนใหญ่ของเรา - การค้าขาย วัตถุการค้าจะรู้วิธีกำหนดราคาตัวเองวิธีประเมินความเสี่ยงตรวจสอบตัวเอง ฯลฯ จากนั้นเราสามารถแทนที่เงื่อนไขด้วย polymorphism เช่น SimpleTrade จะตั้งราคาเองทางเดียว แต่ ComplexTrade จะกำหนดราคาอีกทางหนึ่ง

อย่างไรก็ตามเรามีความกังวลว่าสิ่งนี้จะขยายชั้นการค้า มันควรจะเป็นหน้าที่ของการประมวลผลของตัวเอง แต่ขนาดของชั้นเรียนจะเพิ่มขึ้นแบบทวีคูณเมื่อมีการเพิ่มคุณสมบัติมากขึ้น

ดังนั้นเราจึงมีทางเลือก:

  1. ใส่ตรรกะการประมวลผลในระดับการค้า ตรรกะการประมวลผลตอนนี้เป็นแบบ polymorphic ตามประเภทของการค้า แต่ขณะนี้ชั้นการค้ามีความรับผิดชอบหลายอย่าง (การกำหนดราคาความเสี่ยง ฯลฯ ) และมีขนาดใหญ่
  2. ใส่ตรรกะการประมวลผลลงในคลาสอื่นเช่น TradePricingService ไม่มี polymorphic อีกต่อไปกับแผนภูมิการสืบทอดการค้า แต่คลาสมีขนาดเล็กและง่ายต่อการทดสอบ

อะไรคือแนวทางที่แนะนำ


ไม่มีปัญหา - ฉันยินดีรับการย้ายถิ่น!

1
ระวังการกลับ: martinfowler.com/bliki/AnemicDomainModel.html
TrueWill

1
"ขนาดคลาสจะเพิ่มขึ้นแบบทวีคูณเมื่อมีการเพิ่มฟีเจอร์" - โปรแกรมเมอร์คนใดควรรู้ดีกว่าการใช้คำว่า "เอ็กซ์โพเนนเชียล" ในทางที่ผิด
Michael Borgwardt

@Piskvor นั่นเป็นเพียงแค่โง่
Arnis Lapsa

@Arnis L .: ขอบคุณสำหรับความคิดเห็นที่รอบคอบของคุณ โปรดทราบว่านี่คือคำพูด "ย้ายจาก stackoverflow.com 22 พ.ย. เวลา 22:19" พร้อมกับความคิดเห็นของฉันจากนั้น ตอนนี้ฉันได้ลบความคิดเห็นของฉันที่ "จะดีกว่าที่ programmers.SE"; ตอนนี้คุณมีอะไรเพิ่มหรือไม่หรือเป็นความคิดเดียวที่คุณต้องการแสดงออก?
Piskvor ออกจากอาคาร

คำตอบ:


8

หากคุณกำลังใช้โดเมนแบบขับเคลื่อนให้ลองพิจารณาคลาสการค้าของคุณเป็นรูทรวมและแยกความรับผิดชอบออกเป็นคลาสอื่น ๆ

คุณไม่ต้องการที่จะจบลงด้วย subclass การค้าสำหรับการรวมกันของราคาและความเสี่ยงดังนั้นการค้าอาจมีวัตถุราคาและความเสี่ยง (องค์ประกอบ) วัตถุราคาและความเสี่ยงทำการคำนวณตามจริง แต่ไม่สามารถมองเห็นได้ในทุกระดับยกเว้นการค้า คุณต้องลดขนาดของการค้าโดยไม่เปิดเผยคลาสใหม่ของคุณสู่โลกภายนอก

พยายามใช้องค์ประกอบเพื่อหลีกเลี่ยงต้นไม้มรดกขนาดใหญ่ การรับมรดกมากเกินไปอาจทำให้เกิดสถานการณ์ที่คุณพยายามใส่รองเท้าแตะในพฤติกรรมที่ไม่เหมาะกับโมเดล เป็นการดีกว่าที่จะดึงความรับผิดชอบเหล่านั้นออกไปสู่ชั้นเรียนใหม่


ฉันเห็นด้วย. การคิดของวัตถุในแง่ของพฤติกรรมที่เป็นตัวแก้ปัญหา (การกำหนดราคา, RiskAssessment) แทนที่จะพยายามทำแบบจำลองปัญหาเพื่อหลีกเลี่ยงคลาสเสาหินเหล่านี้
Garrett Hall

ยังเห็นด้วย องค์ประกอบจำนวนมากของการเรียนขนาดเล็กที่มีเฉพาะความรับผิดชอบเดียวใช้งานที่ จำกัด ของวิธีเอกชนจำนวนมากของการเชื่อมต่อมีความสุข ฯลฯ
เอียน

4

คำถามของคุณแน่นอนทำให้ฉันคิดว่าของแบบกลยุทธ์ จากนั้นคุณสามารถสลับในการซื้อขาย / TradePricingServiceกลยุทธ์การกำหนดราคาต่างๆคล้ายกับสิ่งที่คุณเรียก

ฉันคิดว่าคำแนะนำที่คุณจะได้รับจากที่นี่ก็คือการใช้การจัดองค์ประกอบแทนมรดก


2

ทางออกหนึ่งที่เป็นไปได้ที่ฉันใช้ในกรณีที่คล้ายกันคือรูปแบบการออกแบบอะแดปเตอร์ (หน้าอ้างอิงมีโค้ดตัวอย่างจำนวนมาก) อาจใช้ร่วมกับรูปแบบการออกแบบการมอบหมายเพื่อให้ง่ายต่อการเข้าถึงวิธีการหลัก

โดยพื้นฐานแล้วคุณแบ่งการทำงานของผู้ซื้อขายออกเป็นหลาย ๆ ส่วนเช่นการจัดการราคาความเสี่ยงการตรวจสอบความถูกต้องทั้งหมดอาจแตกต่างกัน สำหรับแต่ละพื้นที่คุณสามารถใช้ลำดับชั้นของชั้นเรียนแยกต่างหากซึ่งจัดการฟังก์ชันการทำงานที่แน่นอนในตัวแปรที่จำเป็นต่าง ๆ - อินเทอร์เฟซทั่วไปสำหรับแต่ละพื้นที่ จากนั้นคลาส Trader หลักจะถูกลดลงเป็นข้อมูลพื้นฐานที่สุดและอ้างอิงไปยังวัตถุตัวจัดการจำนวนหนึ่งซึ่งสามารถสร้างได้เมื่อจำเป็น ชอบ

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;
  }
}

ข้อได้เปรียบที่สำคัญอย่างหนึ่งของแนวทางนี้คือการรวมกันที่เป็นไปได้ของราคาและ ricks แยกกันอย่างสมบูรณ์และสามารถรวมกันได้ตามต้องการ นี่ค่อนข้างยากกับการสืบทอดแบบเธรดเดี่ยวของภาษาโปรแกรมส่วนใหญ่ การตัดสินใจที่จะใช้ชุดค่าผสมสามารถคำนวณได้ช้ามาก :-)

ฉันมักจะพยายามเก็บคลาสอะแดปเตอร์ - เช่นคลาสย่อยIPriceCalculatorด้านบน - ไร้สัญชาติ นั่นคือคลาสเหล่านี้ไม่ควรมีข้อมูลในตัวเครื่องหากเป็นไปได้เพื่อลดจำนวนอินสแตนซ์ที่ต้องสร้าง ดังนั้นฉันมักจะให้วัตถุที่ดัดแปลงหลักเป็นอาร์กิวเมนต์ในวิธีการทั้งหมด - เหมือนgetPrice(ITrader)ข้างบน


2

ไม่สามารถพูดถึงโดเมนของคุณได้มากนัก

เรามีโดเมนระดับกลางซึ่งเป็นจุดสนใจของงานส่วนใหญ่ของเรา - การค้าขาย

... มันเป็นกลิ่นของฉัน ฉันอาจจะลองร่างความรับผิดชอบที่แตกต่างกันของชั้นเรียนและในที่สุดก็สลายไปสู่การรวมที่แตกต่างกัน การรวมจะได้รับการออกแบบรอบบทบาทและ / หรือมุมมองของผู้มีส่วนได้เสีย / ผู้เชี่ยวชาญด้านโดเมนที่เกี่ยวข้อง หากราคาและความเสี่ยงมีส่วนเกี่ยวข้องในกรณีพฤติกรรม / การใช้งานที่เหมือนกันพวกเขาอาจจะอยู่ในกลุ่มเดียวกัน แต่ถ้าพวกเขาแยกกันพวกมันอาจเป็นของมวลรวมแยกกัน

บางทีการประเมินความเสี่ยงอาจเป็นเอนทิตีแยกต่างหากในโดเมนของคุณในที่สุดด้วยวงจรชีวิตที่เฉพาะเจาะจง (ฉันไม่สามารถพูดได้จริง ๆ ฉันแค่เก็งกำไร ... คุณรู้ว่าโดเมนของคุณไม่ใช่ของฉัน) แต่กุญแจสำคัญคือการสร้างแนวคิดโดยปริยาย ชัดเจนและเพื่อหลีกเลี่ยงการแต่งงานกันที่ไม่ได้เกิดจากพฤติกรรม แต่โดยเฉพาะการเชื่อมต่อข้อมูลดั้งเดิม

โดยทั่วไปฉันคิดเกี่ยวกับพฤติกรรมที่คาดหวังและวงจรชีวิตที่แตกต่างกันขององค์ประกอบที่เกี่ยวข้อง เพียงแค่เพิ่มพฤติกรรมที่อยู่ด้านบนของข้อมูลที่จัดกลุ่มแล้วสร้างวัตถุที่ป่อง แต่ข้อมูลถูกจัดกลุ่มตามการออกแบบที่ขับเคลื่อนด้วยข้อมูลที่มีอยู่ดังนั้นจึงไม่จำเป็นต้องทำเช่นนั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.