การออกแบบที่ขับเคลื่อนด้วยโดเมน: บริการโดเมน, บริการแอปพลิเคชัน


268

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

คำตอบ:


357

บริการมา 3 รสชาติ: บริการโดเมน , การบริการและการบริการโครงสร้างพื้นฐาน

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

การให้บริการโดเมนพร้อมกับ Domain Objects ของคุณนั้นสมเหตุสมผล - ทั้งหมดนี้เน้นที่ตรรกะของโดเมน และใช่คุณสามารถแทรกที่เก็บลงในบริการของคุณ

โดยทั่วไปแล้วแอปพลิเคชันบริการจะใช้ทั้งบริการโดเมนและที่เก็บเพื่อจัดการกับคำขอภายนอก

หวังว่าจะช่วย!


2
คุณจะวางคำสั่งและข้อความค้นหาโดย CQRS ที่ไหน บริการใดที่สร้างพวกเขาและบริการใดที่จัดการกับพวกเขา
inf3rno

5
ฉันคิดว่าบริการแอปพลิเคชันควรเป็นอิสระจากรายละเอียดทางเทคนิคเช่น "บริการบนเว็บ" ซึ่งบริการดังกล่าวถูกใช้โดยพวกเขา ดูบริการในการออกแบบที่ขับเคลื่อนด้วยโดเมน
deamon

1
@prograhammer - ตัวอย่างสำหรับบริการโดเมนอาจเป็น FundsTransferService โดยที่รูปแบบโดเมนคือ BankAccount การถ่ายโอนอาจมีตรรกะทางธุรกิจบางอย่างที่ไม่พอดีกับวัตถุบัญชีโดยตรง (นำมาจากหนังสือ DDD ของ Evans)
BornToCode

ดังนั้นตัวอย่างเช่น Loginuser () จะเป็นตัวอย่างของบริการโดเมน ที่ getUsers () เป็นบริการแอปพลิเคชั่นที่ไหน?
filthy_wizard

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

114

(ถ้าคุณไม่อยากอ่านมีบทสรุปที่ด้านล่าง :-)

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

แหล่งข้อมูลอื่น ๆ

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

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

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

ความคิดของฉัน

ฉันได้มาคิดว่าการใช้บริการเป็นอ้างอิงให้โดยแอพลิเคชัน ในกรณีนี้แอปพลิเคชันอาจเป็นแอปพลิเคชันเดสก์ท็อปหรือบริการ WCF

โดเมน

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

โซลูชันของฉัน
- My.Product.Core (My.Product.dll)
  - DomainServices
      IExchangeRateService
    สินค้า
    ProductFactory
    IProductRepository

ProductและProductFactoryเรียนได้รับการดำเนินการในการชุมนุมหลัก นี่IProductRepositoryคือสิ่งที่อาจได้รับการสนับสนุนจากฐานข้อมูล การใช้สิ่งนี้ไม่ใช่ความกังวลของโดเมนและถูกกำหนดโดยอินเทอร์เฟซ

IExchangeRateServiceสำหรับตอนนี้เราจะมุ่งเน้นไปที่ ตรรกะทางธุรกิจสำหรับบริการนี้ดำเนินการโดยเว็บเซอร์วิสภายนอก อย่างไรก็ตามแนวคิดของมันยังคงเป็นส่วนหนึ่งของโดเมนและแสดงโดยอินเทอร์เฟซนี้

โครงสร้างพื้นฐาน

การใช้งานการพึ่งพาภายนอกเป็นส่วนหนึ่งของโครงสร้างพื้นฐานของแอปพลิเคชัน:

โซลูชันของฉัน
+ My.Product.Core (My.Product.dll)
- My.Product.Infrastructure (My.Product.Infrastructure.dll)
  - DomainServices
      XEExchangeRateService
    SqlServerProductRepository

XEExchangeRateServiceดำเนินการIExchangeRateServiceให้บริการโดเมนโดยการสื่อสารกับxe.com การใช้งานนี้สามารถใช้งานได้โดยแอปพลิเคชันของคุณที่ใช้โมเดลโดเมนของคุณรวมถึงการประกอบโครงสร้างพื้นฐาน

ใบสมัคร

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

public class CachingExchangeRateService : IExchangeRateService
{
    private IExchangeRateService service;
    private ICache cache;

    public CachingExchangeRateService(IExchangeRateService service, ICache cache)
    {
        this.service = service;
        this.cache = cache;
    }

    // Implementation that utilizes the provided service and cache.
}

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

โซลูชันของฉัน
- My.Product.Core (My.Product.dll)
  - DomainServices
      IExchangeRateService
    สินค้า
    ProductFactory
    IProductRepository
- My.Product.Infrastructure (My.Product.Infrastructure.dll)
  - ApplicationServices
      ICache
  - DomainServices
      CachingExchangeRateService
      XEExchangeRateService
    SqlServerProductRepository
- My.Product.WcfService (My.Product.WcfService.dll)
  - ApplicationServices
      MemcachedCache
    IMyWcfService.cs
  + MyWcfService.svc
  + Web.config

ทั้งหมดนี้มาพร้อมกันในแอปพลิเคชันเช่นนี้:

// Set up all the dependencies and register them in the IoC container.
var service = new XEExchangeRateService();
var cache = new MemcachedCache();
var cachingService = new CachingExchangeRateService(service, cache);

ServiceLocator.For<IExchangeRateService>().Use(cachingService);

สรุป

แอปพลิเคชันที่สมบูรณ์ประกอบด้วยสามเลเยอร์ที่สำคัญ:

  • โดเมน
  • โครงสร้างพื้นฐาน
  • ใบสมัคร

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

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

ชั้นแอปพลิเคชันมีการใช้งานบริการแอปพลิเคชัน เลเยอร์แอปพลิเคชันอาจมีการใช้งานเพิ่มเติมของอินเทอร์เฟซโดเมนถ้าการใช้งานที่จัดทำโดยชั้นโครงสร้างพื้นฐานไม่เพียงพอ

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


2
@ dario-g: คุณต้องสร้างใหม่ / เปลี่ยนชื่อรุ่นโดเมนของคุณใหม่จากโมเดลคำขอและส่งต่อโมเดลโดเมนไปยังบริการโดเมน คำถามนี้อาจให้ความคิดกับคุณ ถ้าไม่บอกให้ฉันรู้แล้วฉันจะดูว่าฉันมีเวลาเพิ่มคำตอบให้กับคำถามอื่นหรือไม่
Niels van der Rest

1
@Tiendq: คุณหมายถึงIExchangeRateServiceส่วนต่อประสานหรือไม่ นี่คือแนวคิดโดเมนคือสิ่งที่รวมอยู่ในภาษาที่แพร่หลายของลูกค้าของคุณ ส่วนอื่น ๆ ของโดเมนของคุณอาจขึ้นอยู่กับบริการนี้ซึ่งเป็นสาเหตุที่ส่วนต่อประสานที่กำหนดไว้ในเลเยอร์โดเมน แต่เนื่องจากการนำไปใช้งานนั้นเกี่ยวข้องกับเว็บเซอร์วิสภายนอกคลาสการนำไปใช้จะอยู่ในเลเยอร์โครงสร้างพื้นฐาน วิธีนี้เลเยอร์โดเมนจะเกี่ยวข้องกับตรรกะทางธุรกิจเท่านั้น
Niels van der Rest

4
@Tiendq: ในสถาปัตยกรรมแบบเลเยอร์ดั้งเดิมโครงสร้างพื้นฐานมักจะไม่เชื่อเรื่องโดเมน แต่ในสถาปัตยกรรมหัวหอม (ดูลิงก์ในคำตอบของฉัน) โครงสร้างพื้นฐานใช้การพึ่งพาภายนอกของโดเมน แต่ฉันจะไม่พูดว่าโครงสร้างพื้นฐานขึ้นอยู่กับโดเมนมันแค่อ้างอิงมัน ฉันใช้คำว่า 'โครงสร้างพื้นฐาน' จากสถาปัตยกรรมหัวหอม แต่ 'ภายนอก' อาจเป็นชื่อที่ดีกว่า
Niels van der Rest

1
@Derek: 'สิ่งของ' หนึ่งในนั้นอาจเป็นExchangeRateตัวอย่างซึ่งมีสกุลเงินหลักสกุลเงินที่เคาน์เตอร์และและอัตราแลกเปลี่ยนระหว่างสองสกุลเงินเหล่านี้ ค่าที่เกี่ยวข้องอย่างแน่นหนาเหล่านี้แสดงถึงแนวคิด 'อัตราแลกเปลี่ยน' จากโดเมนดังนั้นสิ่งเหล่านี้จึงอยู่ในเลเยอร์โดเมน แม้ว่ามันอาจจะดูเหมือน DTO ธรรมดา ๆ แต่ใน DDD นั้นเรียกว่า Value Object และอาจมีตรรกะทางธุรกิจเพิ่มเติมสำหรับการเปรียบเทียบหรือแปลงอินสแตนซ์
Niels van der Rest

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

38

ทรัพยากรที่ดีที่สุดที่ช่วยให้ฉันเข้าใจความแตกต่างระหว่างบริการแอพลิเคชันและบริการโดเมนคือการใช้ Java ตัวอย่างการขนส่งสินค้าเอริคอีแวนส์พบที่นี่ หากคุณไม่ได้โหลดคุณสามารถตรวจสอบภายในของ RoutingService (บริการโดเมน) และ BookingService, CargoInspectionService (ซึ่งเป็น Application Services)

ช่วงเวลา 'aha' ของฉันถูกกระตุ้นโดยสองสิ่ง:

  • การอ่านคำอธิบายของบริการในลิงค์ด้านบนประโยคนี้แม่นยำยิ่งขึ้น:

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

  • อ่านโพสต์บล็อกนี้โดยเฉพาะส่วนนี้:

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


3
ฉันเห็นด้วยนี่คือวิธีที่ฉันกำหนด Application Services และตรงกับทุกสถานการณ์ที่ฉันพบ บริการโดเมนจัดการกับทุกสิ่งที่เกี่ยวข้องกับวัตถุโดเมน แต่มันเกินขอบเขตของเอนทิตีเดียว เช่น BookReferencesService.GetNextAvailableUniqueTrackingNumber () จุดเน้นคือกฎทางธุรกิจอย่างชัดเจน * เกี่ยวกับ Application Service มันเป็นสิ่งที่คุณอธิบายส่วนใหญ่เวลาที่ฉันเริ่มต้นโดยใส่เวิร์กโฟลว์ธุรกิจนี้ลงในการดำเนินการควบคุมของฉันและเมื่อฉันสังเกตเห็นว่าฉัน refactor ตรรกะนี้ในชั้นบริการแอปพลิเคชัน เราอาจพูดได้ว่าเลเยอร์นี้มีไว้สำหรับกรณีการใช้งาน
tobiak777

1
* และอินเทอร์เฟซบริการโดเมนดังกล่าวถูกใช้โดยหน่วยงานของโดเมน
tobiak777

32

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

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

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


10
"บริการโดเมนเหมาะสมกับที่ที่ไม่มีรัฐมิฉะนั้นจะเป็นวัตถุโดเมน" ทำให้มันคลิกสำหรับฉัน ขอบคุณ.
Nick

31

จาก Red Book (การใช้การออกแบบโดเมนขับเคลื่อนโดย Vaughn Vernon) นี่คือวิธีที่ฉันเข้าใจแนวคิด:

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

บริการโดเมน encapsulate พฤติกรรมดังกล่าวที่ไม่เหมาะสมในวัตถุโดเมนเดียว ตัวอย่างเช่นห้องสมุดหนังสือที่ยืมBookไปยัง a Client(ที่มีInventoryการเปลี่ยนแปลงที่สอดคล้องกัน) อาจทำได้จากบริการโดเมน

บริการแอปพลิเคชันจัดการกับกรณีการใช้งานรวมถึงข้อกังวลเพิ่มเติมใด ๆ ที่จำเป็นด้านบนของโดเมน มันมักจะเปิดเผยวิธีการดังกล่าวผ่าน API เพื่อการบริโภคโดยลูกค้าภายนอก หากต้องการสร้างตัวอย่างก่อนหน้าของเราบริการแอปพลิเคชันของเราอาจเปิดเผยวิธีการLendBookToClient(Guid bookGuid, Guid clientGuid)ที่:

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

บริการแอปพลิเคชันโดยทั่วไปควรมีขั้นตอนง่าย ๆ บริการแอพพลิเคชั่นที่ซับซ้อนมักจะแสดงว่าลอจิกโดเมนหลุดออกจากโดเมนแล้ว

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


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

10

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

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

Millett, C (2010) รูปแบบการออกแบบ ASP.NET มืออาชีพ สำนักพิมพ์ไวลีย์ 92


6

บริการโดเมน : บริการที่แสดงตรรกะทางธุรกิจที่ไม่ได้เป็นส่วนหนึ่งของรูทรวม

  • คุณมี 2 มวลรวม:

    • Product ซึ่งมีชื่อและราคา
    • Purchase ซึ่งมีวันที่ซื้อรายการผลิตภัณฑ์ที่สั่งซื้อพร้อมปริมาณและราคาสินค้าในเวลานั้นและวิธีการชำระเงิน
  • Checkout ไม่ได้เป็นส่วนหนึ่งของทั้งสองรุ่นนี้และเป็นแนวคิดในธุรกิจของคุณ

  • Checkout สามารถสร้างเป็นบริการโดเมนที่ดึงผลิตภัณฑ์ทั้งหมดและคำนวณราคารวมชำระทั้งหมดโดยโทรไปที่บริการโดเมนอื่น PaymentServicePurchaseด้วยส่วนการดำเนินงานของโครงสร้างพื้นฐานและแปลงเป็น

บริการแอปพลิเคชัน : บริการที่"orchestrate"หรือแบบฝึกหัดวิธีโดเมน สิ่งนี้สามารถทำได้ง่ายเพียงแค่ควบคุมของคุณ

นี่คือสถานที่ที่คุณมักจะทำ:

public String createProduct(...some attributes) {
  if (productRepo.getByName(name) != null) {
    throw new Exception();
  }

  productId = productRepository.nextIdentity();

  product = new Product(productId, ...some attributes);

  productRepository.save(product);

  return productId.value();
  // or Product itself
  // or just void if you dont care about result
}

public void renameProduct(productId, newName) {
  product = productRepo.getById(productId);

  product.rename(newName);

  productRepo.save(product);
}

คุณสามารถทำการตรวจสอบที่นี่เช่นการตรวจสอบว่าProductเป็นเอกลักษณ์ เว้นแต่Productชีวิตที่ไม่ซ้ำใครนั้นจะเป็นค่าคงที่ซึ่งควรเป็นส่วนหนึ่งของ Domain Service ที่อาจถูกเรียกUniqueProductCheckerเพราะมันไม่สามารถเป็นส่วนหนึ่งของProductชั้นเรียนและโต้ตอบกับ Aggregates หลาย ๆ ตัว

นี่คือตัวอย่างเต็มรูปแบบของโครงการ DDD: https://github.com/VaughnVernon/IDDD_Samples

คุณสามารถค้นหาตัวอย่างมากมายของ Application Service และ Domain Service สองสามอย่าง


จำเป็นต้องมีการตรวจสอบและบันทึกเอนทิตีเฉพาะใน Application Services หรือไม่ หากฉันมีเอนทิตี A, B และ C และทั้งหมดเกี่ยวข้องกับกันและกัน (A -> B -> C) และการดำเนินการกับ A ควรทำให้ B และ C เปลี่ยนแปลงไปโดยการเรียกใช้บริการโดเมนหนึ่งจากอีกบริการหนึ่งทำอย่างไร?
MrNVK

> จำเป็นหรือไม่ที่จะต้องตรวจสอบและบันทึกเอนทิตีใน Application Services เท่านั้น ถ้าคุณต้องใช่แล้ว ส่วนใหญ่คุณต้องตรวจสอบว่ามี ID อยู่หรือไม่เพราะคุณจะทำงานกับตัวแปรที่เป็นโมฆะ
doesnotmatter

1
> ถ้าฉันมีเอนทิตี A, B และ C และสิ่งเหล่านั้นเกี่ยวข้องกัน (A -> B -> C) และการทำงานบน A ควรทำให้ B และ C เปลี่ยนแปลงโดยการเรียกใช้บริการโดเมนหนึ่งจากอีกบริการหนึ่งจะทำอย่างไร ? ฉันไม่แน่ใจว่าคุณหมายถึงอะไรโดย "เรียกใช้บริการโดเมนหนึ่งจากอีกบริการหนึ่ง" แต่สำหรับการตอบสนองต่อการเปลี่ยนแปลงของ Entity คุณสามารถใช้กิจกรรมหรือปรับแต่งมันด้วยแอปพลิเคชันบริการเช่น: aggregateA.doOperation (), aggregateB.doAnother ( ) ค้นหา: Orchestration vs Choreography
doesnotmatter

ขอบคุณสำหรับการตอบกลับ! "เรียกบริการโดเมนหนึ่งจากบริการอื่น" - ฉันหมายถึงถ้าฉันมีการดำเนินการที่ซับซ้อนในเอนทิตี A ดังนั้นฉันต้องใช้ ADomainService แต่การดำเนินการนี้นอกเหนือจากเอนทิตี A ส่งผลกระทบต่อเอนทิตี B. การดำเนินการที่ต้องดำเนินการกับเอนทิตี B ใน ADomainService นั้นซับซ้อนเช่นกัน ดังนั้นฉันต้องใช้ BDomainService จาก ADomainService ตอนนี้ฉันสงสัยวิธีนี้ :) แต่ถ้าฉันใส่ตรรกะนี้ใน ApplicationService มันจะไม่ทำลาย encapsulation ของกระบวนการทางธุรกิจที่ควรอยู่ในโดเมนเลเยอร์เท่านั้น
MrNVK

คุณสามารถส่งเหตุการณ์จากบริการโดเมนของคุณหากคุณคิดว่าควรอยู่ในบริการโดเมนแทนบริการแอปพลิเคชัน
doesnotmatter

0

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

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

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

ลดความซับซ้อนมากเราพิจารณาเพียง 2 หน่วยงานโดเมน: DoorและLampแต่ละคนมี 2 สถานะเคารพopen/closedและon/offและวิธีการเฉพาะในการดำเนินการเปลี่ยนแปลงสถานะกับพวกเขา

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

เราสามารถเรียกใช้บริการของเราเป็นโดเมนDomoticDomainServiceและดำเนินการ 2 วิธี: OpenTheDoorAndTurnOnTheLightและCloseTheDoorAndTurnOffTheLightเหล่านี้ 2 วิธี respectevely เปลี่ยนสถานะของวัตถุทั้งสองDoorและLampไปและopen/onclosed/off

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

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


Ciro: ตัวอย่างของคุณไม่เป็นประโยชน์และมันสับสนมาก
Morteza Azizi

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