รุ่นหนาเทียบกับ ตรรกะทางธุรกิจคุณจะแยกความแตกต่างที่ไหน


16

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

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

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


tl; dr: ประเภทใดที่สามารถหรือควรไปในวิธีการในคลาสที่แมปเมื่อใช้ ORM และสิ่งที่ควรจะออกไปอยู่ในอีกชั้นหนึ่งของสิ่งที่เป็นนามธรรม?


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

คำตอบ:


10

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

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

Rule of thumb: คลาสควรมีตรรกะที่อธิบายข้อเท็จจริงพื้นฐานเกี่ยวกับข้อมูลที่เป็นจริงภายใต้สถานการณ์ทั้งหมด ตรรกะที่เฉพาะเจาะจงกับกรณีการใช้งานควรเป็นที่อื่น ตัวอย่างคือการตรวจสอบความถูกต้องมีบทความที่น่าสนใจจาก Martin Fowlerซึ่งเขาชี้ให้เห็นว่าควรพิจารณาตามบริบท


+1 สำหรับส่วนที่สองของคำตอบของคุณ ในส่วนแรกฉันแน่ใจว่าทำไมคุณพูดว่ารูปแบบโดเมน anemic ต้องการงานพิเศษมากในกรณีที่มีการเปลี่ยนแปลง ความเข้าใจของฉันคือการเปลี่ยนแปลงจะเกิดขึ้น แต่ในชั้นเรียนที่แตกต่างกันหลาย (ซึ่งเป็นชนิดที่ไม่ดี) แต่มันก็เกือบจะเท่ากันของการเปลี่ยนแปลง; ฉันคิดว่า?
NoChance

1
@Emmad Kareem: ความคิดเห็นเกี่ยวกับการมีอยู่และรูปแบบโดเมน spearate การเพิ่มคุณสมบัติให้กับโมเดลนั้นต้องการเพิ่มลงในคลาสโมเดลสองคลาส (มากกว่าหนึ่งคลาส) รวมถึงแผนที่ใด ๆ ที่อยู่ระหว่างพวกเขา (ซึ่งในทางทฤษฎีอาจเป็นไปโดยอัตโนมัติ แต่โดยทั่วไปแล้วผู้ที่คิดว่าเป็นความคิดที่ดี "persistence model" ตัดสินใจที่จะให้เหตุผลว่าการแยกโดยทำให้พวกมันแตกต่างกันเช่นมีประเภทข้อมูลที่ตรงกับแบบจำลอง DB มากขึ้น) นั่นคือ 2 + X คูณกับจำนวนการเปลี่ยนแปลงโดย X แปรผันระหว่าง 0 และชั่วโมงของการสูญเสียผลผลิต ปัญหาการทำแผนที่
Michael Borgwardt

3

นี่คือการตัดสินที่ขึ้นอยู่กับขนาดและขนาดของสิ่งที่คุณกำลังพัฒนา วิธีที่เข้มงวดที่สุดคือการ จำกัด ประเภท ORM ให้กับคอมโพเนนต์การเข้าถึงข้อมูลและใช้ POCO ในไลบรารีทั่วไปตามประเภทที่อ้างอิงและใช้โดยเลเยอร์ทั้งหมด สิ่งนี้จะช่วยให้การแยกทางกายภาพในอนาคตเช่นเดียวกับการแยกทางตรรกะ คุณสามารถตัดสินใจว่าควรมีเลเยอร์เพิ่มเติมระหว่าง UI และเลเยอร์ตรรกะทางธุรกิจ ซึ่งมักเรียกว่าเลเยอร์ Facade หรือ Business Interface เลเยอร์เพิ่มเติมนี้เป็นที่ที่ "รหัสกรณีการใช้งานของคุณ" มีชีวิตอยู่ รหัสคู่ที่แยกกันอย่างอิสระถูกเรียกโดยเลเยอร์ Facade / BI (เช่น Facade มีฟังก์ชัน ProcessOrder () ซึ่งเรียกใช้ตรรกะทางธุรกิจ 1: M ครั้งเพื่อดำเนินการตามขั้นตอนทั้งหมดที่จำเป็นในการประมวลผลคำสั่งจริง)

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


3

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

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


1

นอกเหนือจากคำตอบอื่น ๆ แล้วให้ใส่ใจกับถ้ำที่ซ่อนอยู่เมื่อใช้โมเดลโดเมนที่มี ORM

ฉันมีปัญหาในการฉีดบริการ polymorphic ในชั้นเรียนโมเดลที่คงอยู่เมื่อพยายามที่จะบรรลุสิ่งต่าง ๆ เช่นรหัสเทียมต่อไปนี้:

Person john = new Person('John Doe')
Organisation company = organisation_repository.find('some id')
Employee our_collegue_john = company.hire(john)

ในกรณีนี้องค์กรอาจต้องการการHRServiceอ้างอิงแบบคอนสตรัคเตอร์ (เช่น) คุณมักจะไม่สามารถควบคุมการติดตั้งคลาสโมเดลของคุณได้อย่างง่ายดายเมื่อใช้ ORM

ฉันใช้ Doctrine ORM และ service container จาก Symfony ฉันต้องมองหา ORM ในแบบที่ไม่หรูหราและไม่มีทางเลือกอื่นนอกจากแยกความเพียรและรูปแบบธุรกิจ ฉันยังไม่ได้ลองด้วย sqlachemy คิด Python อาจมีความยืดหยุ่นมากกว่า PHP สำหรับสิ่งนี้

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