วัตถุธุรกิจ - ภาชนะบรรจุหรือฟังก์ชั่น?


19

นี่เป็นคำถามที่ฉันถามกลับไปซักพักแล้ว แต่มันอาจจะดีกว่าที่นี่ ...

ที่ที่ฉันทำงานเราได้ย้อนกลับไปในเรื่องนี้หลายครั้งและกำลังมองหาการตรวจสุขภาพ นี่คือคำถาม: หาก Business Objects เป็น data container (เหมือนDTO ) หรือควรมีตรรกะที่สามารถใช้งานบางอย่างกับวัตถุนั้นได้

ตัวอย่าง - นำวัตถุลูกค้าอาจมีคุณสมบัติทั่วไปบางอย่าง (ชื่อรหัส ฯลฯ ) หากวัตถุลูกค้านั้นควรมีฟังก์ชั่น (บันทึก, คำนวณ, ฯลฯ )?

การใช้เหตุผลหนึ่งบรรทัดบอกว่าแยกวัตถุออกจากฟังก์ชั่น (ผู้รับผิดชอบหลักเดียว) และวางฟังก์ชันการทำงานในเลเยอร์หรือตรรกะทางธุรกิจ

อีกเหตุผลหนึ่งบอกว่าไม่ใช่ถ้าฉันมีวัตถุลูกค้าฉันแค่ต้องการโทรหาลูกค้าบันทึกและทำได้ด้วย ทำไมฉันต้องรู้เกี่ยวกับคลาสอื่นเพื่อบันทึกลูกค้าถ้าฉันใช้วัตถุ?

โครงการสองโครงการสุดท้ายของเรามีวัตถุที่แยกออกจากฟังก์ชันการทำงาน แต่การอภิปรายได้รับการยกขึ้นอีกครั้งในโครงการใหม่

ซึ่งทำให้รู้สึกมากขึ้นและทำไม?


1
คุณช่วยบอกเราเพิ่มเติมเกี่ยวกับโครงการของคุณได้ไหม ธรรมชาติของโครงการของคุณจะเป็นตัวกำหนดทางออกที่ดีกว่า

คำตอบ:


5

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

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

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

public static CustomerDTO GetDTO(Customer c) { /* ... */ }

public static Customer GetCustomer(CustomerDTO cdto) { /* ... */ }

โดยสรุปแล้วมันมีเหตุผลที่เหมาะสมที่จะมีการดำเนินการกับวัตถุโดเมนที่สอดคล้องกับการดำเนินการทางตรรกะในโดเมน

Google สำหรับ 'Persistence Ignorance' สำหรับการสนทนาที่ดีจำนวนหนึ่งเกี่ยวกับเรื่องนี้ ( คำถาม SO นี้และคำตอบที่ยอมรับได้เป็นจุดเริ่มต้นที่ดี)

** สิ่งนี้ได้รับความสับสนเล็กน้อยกับซอฟต์แวร์ OR / M บางตัวที่คุณถูกบังคับให้สืบทอดจากฐานถาวรที่มีวิธีการ 'บันทึก'


3

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

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


3

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

ดังนั้นฉันจะถามตัวเองนี้ในกรณีที่เป็นรูปธรรมของคุณ: ลูกค้าควรทราบวิธีการช่วยตัวเอง?

สำหรับฉันคำตอบก็คือไม่: มีเหตุผลสำหรับฉันมันไม่สมเหตุสมผลและลูกค้าไม่ควรต้องรู้อะไรเกี่ยวกับกรอบการคงอยู่ใด ๆ เลย (การแยกหน้าที่)

สำหรับตัวอย่างของ SnOrfus กับ Customer.UpgradeWarranty () หรือ Customer.PromoteToPreferred () พวกเขาเห็นได้ชัดว่ามีตรรกะทางธุรกิจมากกว่า Customer.Save () มีวิธีการที่แตกต่างกัน แต่ถ้าคุณถามตัวเองว่าลูกค้าควรจะสามารถอัพเกรดการรับประกันของเขาได้หรือไม่คำตอบอาจเป็นได้ทั้งใช่หรือไม่ใช่ขึ้นอยู่กับว่าคุณมองอย่างไร:

  • ใช่: ลูกค้าสามารถอัพเกรดการรับประกันได้
  • ไม่: ลูกค้าสามารถขอให้อัปเกรดได้ แต่มีบุคคลอื่นทำการอัปเกรด

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

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


2

ฉันคิดว่าคุณกำลังพูดถึงความแตกต่างระหว่างActiveRecordลวดลายและRepositoryลวดลายโดยเฉพาะ ในอดีตเอนทิตี้รู้วิธีการคงอยู่ของตัวเองและในภายหลังที่เก็บข้อมูลรู้เกี่ยวกับการคงอยู่ ฉันคิดว่าสิ่งหลังเสนอความกังวลที่ดีกว่า

ในแง่ที่กว้างขึ้นถ้าเอนทิตีทำหน้าที่เหมือนโครงสร้างข้อมูลมากขึ้นพวกเขาก็ไม่ควรมีพฤติกรรม แต่ถ้าพวกเขามีพฤติกรรมพวกเขาก็ไม่ควรถูกนำมาใช้เป็นโครงสร้างข้อมูล ตัวอย่าง:

โครงสร้างข้อมูล:

class CustomerController
{
    public int MostRecentOrderLines(Customer customer)
    {
        var o = (from order in customer.Orders
                orderby order.OrderDate desc
                select order).First();
        return o.OrderLines.ToList().Count;
    }
}

โครงสร้างที่ไม่ใช่ข้อมูล:

class Customer
{
    public int MostRecentOrderLines()
    {
        // ... same ...
    }
}

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

คุณต้องการให้เอนทิตีของคุณเป็นโครงสร้างข้อมูลหรือบริการหรือไม่? เพื่อความมั่นคงดูเหมือนว่าดีกว่าที่จะติดกับหนึ่ง ในกรณีก่อนหน้าให้วาง "บริการ" - ตรรกะประเภทอื่นไว้ในเอนทิตี


1

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

ฉันจะพยายามทำให้ข้อเท็จจริงที่เกิดขึ้นเป็นไปตามที่คาดคิด:

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

  • ง่ายต่อการเข้าใจรหัสและการทำงานของวัตถุ bu

  • ความซับซ้อนน้อยลงในการออกแบบ

ฉันกำลังบอกพวกเขาว่าพวกเขาขี้เกียจและฉันจะทำให้เป็นแบบนี้:

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

  • การทำให้วัตถุมีความรับผิดชอบสำหรับทุกสิ่งทำให้ไม่ดีต่อความทนทานและการดูแลรักษาในอนาคต ถ้าคุณมีคลาสแยกต่างหากที่รับผิดชอบการบันทึกถ้าคุณเพิ่มวัตถุใหม่ในการออกแบบคุณสามารถใช้ funtion ของการบันทึกได้อย่างง่ายดาย แทนที่จะเข้ารหัสมันทั้งหมดอีกครั้งในชั้นเรียนนั้น

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

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

แก้ไข:

ฉันลืมที่จะพูดถึงโครงการนี้เกี่ยวกับร้านหนังสือ


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

1

คำตอบนั้นขึ้นอยู่กับว่าสถาปัตยกรรม / การออกแบบของคุณคืออะไร - สถาปัตยกรรม DDD ที่มีโมเดลโดเมนจะแตกต่างจาก CRUD data-centric model มากเมื่อมันมาถึงการออกแบบวัตถุ

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

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

ในแอปพลิเคชัน CRUD ข้อมูลจะเป็นพลเมืองชั้นหนึ่งดังนั้น ".Save" จึงเหมาะสมอย่างยิ่ง

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


0

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

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

ถ้าคุณกำลังจัดการกับผลิตภัณฑ์ที่มีอยู่ตราบใดที่คุณมีส่วนต่อประสานที่สะอาดและเป็นสัญญา - ตกลงและบำรุงรักษาได้เช่นกัน ...

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