Application layer กับ domain layer?


46

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

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

คำตอบ:


35

ฉันเพิ่งอ่าน DDD ด้วยตัวเอง เมื่อฉันมาถึงส่วนนี้ฉันรู้สึกประหลาดใจอย่างยิ่งที่ค้นพบว่าฉันค้นพบสถาปัตยกรรม 4 ชั้นที่ Evans ทำ ตามที่ @lonelybug ชี้ให้เห็นว่าโดเมนเลเยอร์ควรแยกออกจากส่วนที่เหลือของระบบโดยสมบูรณ์ อย่างไรก็ตามสิ่งที่มีการแปลค่าเฉพาะ UI (สตริงแบบสอบถามข้อมูล POST, เซสชั่น ฯลฯ ) เป็นวัตถุโดเมน นี่คือที่เลเยอร์แอปพลิเคชันเข้ามาเล่น หน้าที่คือการแปลไปมาระหว่าง UI เลเยอร์ข้อมูลและโดเมนอย่างมีประสิทธิภาพซ่อนโดเมนจากส่วนที่เหลือของระบบ

ฉันเห็นแอปพลิเคชั่น ASP.NET MVC จำนวนมากในขณะนี้ซึ่งตรรกะเกือบทั้งหมดอยู่ในคอนโทรลเลอร์ นี่เป็นความพยายามที่ล้มเหลวในการใช้งานสถาปัตยกรรม 3 ชั้นแบบคลาสสิก ตัวควบคุมยากต่อการทดสอบหน่วยเนื่องจากมีข้อกังวลเฉพาะเกี่ยวกับ UI จำนวนมาก ในความเป็นจริงการเขียนคอนโทรลเลอร์เพื่อที่จะไม่เกี่ยวข้องโดยตรงกับค่า "บริบท Http" เป็นความท้าทายที่ร้ายแรงทั้งในและของตัวเอง ตามหลักแล้วผู้ควบคุมควรจะทำการแปลประสานงานและแยกการตอบกลับ

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

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


9
ฉันไม่คิดว่าสิ่งที่คุณระบุไว้ที่นี่ถูกต้อง: "อย่างไรก็ตามมีบางสิ่งที่ต้องแปลค่าเฉพาะ UI (สตริงการสืบค้นข้อมูล POST เซสชั่น ฯลฯ ) ลงในวัตถุโดเมนนี่คือที่มาของเลเยอร์แอปพลิเคชัน" สิ่งที่คุณอ้างอิงอยู่ในข้อกำหนดของ DDD คือเลเยอร์ "การนำเสนอ" Application Layer ควรจะจัดการกับปัญหาเกี่ยวกับการประปา, การเกิดพร้อมกันและการตัดข้ามเป็นเพียงเสื้อคลุมเล็ก ๆ เหนือ Domain Layer สิ่งที่คุณอธิบายจะสอดคล้องกับเลเยอร์ (ย่อย) ในเลเยอร์การนำเสนอ
elysium กลืนกิน

23

จากรูปแบบการออกแบบองค์กรของ Martin Fowler เลเยอร์ที่พบบ่อยที่สุดคือ:

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

  • โดเมน - นี่คือที่ซึ่งกฎเกณฑ์ทางธุรกิจและตรรกะของคุณอยู่โมเดลโดเมนของคุณถูกกำหนดไว้

  • แหล่งข้อมูล - นี่คือเลเยอร์การแมปข้อมูล (ORM) และแหล่งข้อมูล (ฐานข้อมูลระบบไฟล์ ฯลฯ )

คุณจะวาดขอบเขตระหว่างสามเลเยอร์ได้อย่างไร:

  • อย่าวางตรรกะเฉพาะของงานนำเสนอไว้ในโมเดลหรือวัตถุโดเมนของคุณ

  • อย่าใส่ตรรกะในหน้าและตัวควบคุมของคุณเช่นตรรกะในการบันทึกวัตถุลงในฐานข้อมูลสร้างการเชื่อมต่อฐานข้อมูล ฯลฯ ซึ่งจะทำให้เลเยอร์การนำเสนอของคุณเปราะและยากต่อการทดสอบ

  • ใช้ ORM ซึ่งช่วยให้คุณสามารถแยกการเข้าถึงแหล่งข้อมูลและการดำเนินการจากโมเดล

  • ติดตามตัวควบคุมแบบบาง - กระบวนทัศน์แบบจำลองไขมันตัวควบคุมนั้นใช้สำหรับควบคุมกระบวนการของการดำเนินการที่ไม่ดำเนินการเพิ่มเติมที่http://www.littlehart.net/atthekeyboard/2007/04/27/fat-models-skinny-controllers/และhttp://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model model มุมมองและคอนโทรลเลอร์


17

ชั้นโดเมนแบบธุรกิจของแอพลิเคชันของคุณ นี่ควรเป็นการตีความที่ชัดเจนของคุณเกี่ยวกับกฎระเบียบมันเป็นพลวัตขององค์ประกอบและมีสถานะเป็นช่วงเวลาใดก็ตาม

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

สำหรับตัวอย่างการประยุกต์ใช้ซอฟต์แวร์ทางการเงินของฉันมีการดำเนินการของผู้ใช้สำหรับเปลี่ยนสถานะของรูปแบบนิติบุคคล (นิติบุคคลตามที่กำหนดใน DDD [89]):

  • "หัวหน้าฝ่ายปฏิบัติการสามารถอนุมัติข้อเสนอทางการเงิน"

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

หมายเหตุ:

  • ธุรกิจเป็นหนึ่งในคำเหล่านั้นที่มักนำไปสู่การตีความที่หลากหลายของความหมาย แต่แน่นอนว่าคุณสามารถหาตัวอย่างมากมายและพูดคุยใน DDD;
  • DDD ย่อมาจากหนังสือออกแบบโดเมนขับเคลื่อนโดย Eric Evans และหมายเลขภายในวงเล็บสี่เหลี่ยมสำหรับหมายเลขหน้า

6

Domain Layer ควรได้รับการออกแบบเป็นชั้นแยกซึ่งหมายความว่าตรรกะทางธุรกิจและกฎระเบียบไม่ควรได้รับผลกระทบกับรหัสใด ๆ (ใน Application Layer, Presentation Layer และ Infrastructure Layer) การเปลี่ยนแปลง

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

ควรออกแบบ Application Layer เป็น Layer Layer ซึ่งหมายความว่าพฤติกรรมของแอพพลิเคชั่นไม่ควรได้รับผลกระทบใด ๆ กับการเปลี่ยนแปลงของรหัส (ใน Presentation Layer, Domain Layer และ Infrastructure Layer)


2
อย่างน้อยในวรรณคดีเช่น Domain ขับเคลื่อนการออกแบบ (อีแวนส์) ก็เป็นที่ยอมรับว่าชั้นมีทางเดียวพึ่งพา ... ความจริงก็คือในบางจุดรหัสของคุณขึ้นอยู่กับบางสิ่งบางอย่าง UI ขึ้นอยู่กับแอปพลิเคชัน แต่ไม่ใช่ในทางกลับกัน แอปพลิเคชันขึ้นอยู่กับโดเมน แต่ไม่ใช่ข้อรอง โดเมนกับโครงสร้างพื้นฐานไม่ใช่ในทางกลับกัน

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

นั้นยอดเยี่ยมและทั้งหมดบนกระดาษ แต่ในทางปฏิบัติความต้องการทางธุรกิจส่งผลให้เกิดการเปลี่ยนแปลงที่อาจส่งผลกระทบต่อส่วนต่อประสานของชั้นแอปพลิเคชันในลักษณะที่เปลี่ยนฟองอากาศผ่านชั้นนำเสนอและบางครั้งก็เป็นชั้นจัดเก็บข้อมูล นั่นคือทั้งหมดที่ฉันได้รับที่ ...

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

3

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

สิ่งนี้ช่วยให้คุณสามารถมุ่งเน้นไปที่โดเมนได้เองโดยไม่รบกวน (เช่นการประสานงานระหว่าง UI และบริการการคงอยู่)


จากนั้นแหล่งข้อมูล (ORM) อยู่ภายในโดเมน
Maykonn

@Maykonn - อาจเป็นได้ อย่างไรก็ตาม ORM ไม่ใช่แหล่งข้อมูล มันเป็นเครื่องมือระหว่างรหัสของคุณและแหล่งข้อมูลที่แท้จริง (ฐานข้อมูลเชิงสัมพันธ์) วิธีที่คุณเข้าถึงข้อมูลไม่ควรกังวลเกี่ยวกับโดเมน - ผู้สร้างและโรงงานสามารถจัดการกับเรื่องนั้นได้ (และ ORM หากคุณมี)
Oded

ฉันเห็นด้วย. และฉันผิดเกี่ยวกับแหล่งข้อมูลและออม ขอบคุณ!
Maykonn

3
  • Application LayerและDomain Layerนั้นอยู่ภายใต้ขอบเขตของการใช้
  • Application Layerทำหน้าที่เป็น API
  • Domain Layerทำหน้าที่เป็นการนำ API มาใช้ซึ่งประกอบด้วยตรรกะทางธุรกิจดังนั้นจึงเรียกว่าBusiness Logic Layer

ป้อนคำอธิบายรูปภาพที่นี่


ไม่ว่าจะเป็นแบบนี้ .... ฉันรู้สึกรู้แจ้ง
Nikos

2

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

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

เป้าหมายสูงสุดคือการทำให้รหัสของคุณง่ายต่อการบำรุงรักษามากที่สุด

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

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


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

1
นั่นเป็นคำถามที่สมบูรณ์แบบสำหรับเว็บไซต์นี้ คุณควรโพสต์ไว้เพื่อให้ทุกคนมีโอกาสได้รับคำตอบ
Charles Lambert

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