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


70

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

ตอนนี้ฉันอ่านในคำถามนี้ว่าคุณควรใส่ตรรกะทางธุรกิจลงในแบบจำลองเสมอและตัวควบคุมนั้นเชื่อมต่ออย่างลึกซึ้งกับมุมมอง

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

และถ้าฉันต้องการมุมมองอื่นฉันต้องเขียนทั้งมุมมองและคอนโทรลเลอร์อีกครั้ง

มีคนอธิบายได้ไหมว่าเพราะอะไร

คำตอบ:


69

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

ชี้แจงสอง:

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

4
เฟรมเวิร์ก MVC ส่วนใหญ่เป็นประเภทของการจัดเก็บข้อมูล / ฐานข้อมูลทั้งหมดลงในแบบจำลองเพื่อให้ง่ายต่อการจัดเก็บแบบจำลองของคุณ (บ่อยครั้งโดยทำให้คุณขยายขอบเขตแบบจำลองคลาส) นี่อาจเป็นที่มาของความสับสน ในทางเทคนิคแล้วโค้ดโมเดลที่คุณเขียนควรเป็นโมเดลจริง (โดเมนเลเยอร์) ในขณะที่โค้ดที่จัดเตรียมโดยเฟรมเวิร์กควรจัดการกับหน่วยเก็บข้อมูล (เลเยอร์คงอยู่) ตัวอย่างเช่นบางอย่างเช่น User.find (... ) (โดยที่ผู้ใช้เป็นแบบจำลอง) ทำงานได้เนื่องจากเฟรมเวิร์กนำรูปแบบที่เก็บมาใช้เป็นส่วนหนึ่งของโมเดล
Waquo

3
View-Controller-Model-Storage เป็นหลักการทั่วไป (แม้ว่าความสัมพันธ์ระหว่าง M, V และ C ควรจะมองเห็นเป็นรูปสามเหลี่ยม) เมื่อเฟรมเวิร์กของคุณรวมที่เก็บข้อมูลไว้ใน "แบบจำลอง" มันจะทำงานในลักษณะนี้: View-Controller- (รุ่นที่สืบทอดการจัดเก็บจากเฟรมเวิร์ก)
Waquo

2
View-Controller-Model-Storage ค่อนข้างหยาบเพราะมันไม่ควรแบน ตัวอย่างเช่นเมื่อตัวควบคุมทำอะไรบางอย่างเช่น User.find (... ) เพื่อให้ได้แบบจำลองมันจะถามเลเยอร์การจัดเก็บโดยตรงแทนที่จะไปผ่านเลเยอร์โดเมน
Waquo

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

1
@flipdoubt ตรรกะทางธุรกิจเป็นตรรกะใด ๆ ที่ควรจะเก็บไว้เหมือนกันถ้าคุณพอร์ตจาก mvc เพื่อพูดแอป uwp
แอนดี้

23

คุณและส่วนใหญ่ของโลกการเขียนโปรแกรมดูเหมือนจะเข้าใจผิดว่าบทบาทของส่วน MVC คืออะไร กล่าวโดยย่อคือ:

Model = ตรรกะโดเมน

ดู = ตรรกะเอาต์พุต

ตัวควบคุม = ตรรกะอินพุต

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

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

คุณอาจต้องการอ่านเกี่ยวกับสถาปัตยกรรมหลายชั้น ที่ MVC เป็นแบบทางเดียว (การไหลเป็นตัวควบคุม -> รุ่น -> มุมมอง), Multi-Tier เป็นสองทาง (การนำเสนอ -> ลอจิก -> ข้อมูล -> ลอจิก -> การนำเสนอ) และค่อนข้างน้อย เฟรมเวิร์กที่แสร้งทำ MVC จริงแล้วทำสามระดับนำเสนอการติดป้ายใหม่เพื่อดูลอจิกสู่ตัวควบคุมและข้อมูลจากแบบจำลอง


2
ฉันเชื่อว่าคุณบิดเบือนโมเดล ("Model = domain logic") ในใจของฉันมันเป็นเรือสำหรับประชากรที่มีข้อมูลมากกว่าซึ่งจะแสดงผลโดยใช้มุมมองในรูปแบบบริสุทธิ์ของรูปแบบ MVC แน่นอนว่าในกรณีที่ใช้งานง่ายคุณสามารถใช้มันเป็น "ตรรกะทางโดเมน" แต่ฉันขอรับรองว่าระบบที่มีอยู่ในปัจจุบันส่วนใหญ่จะโตเร็วกว่านั้น ดีกว่าที่จะแยก "domain logic" ออกเป็นเลเยอร์ / คลาสที่แยกต่างหากเช่นเลเยอร์บริการ
A. Murray

@ A.Murray: แน่นอนว่า Model นั้นไม่จำเป็นต้องเป็นหนึ่ง monolithic ของโค้ดและแยกมันออกเป็นความคงทนโครงสร้างข้อมูลและตรรกะของโดเมนโดยทั่วไปแล้วสมเหตุสมผล ถึงกระนั้น MVC ก็จัดกลุ่มความกังวลทั้งสามนี้ไว้ด้วยกันในแบบจำลอง ไม่ว่าในกรณีใดเมื่อตัวควบคุมและมุมมองของคุณมีลอจิกโดเมนมันจะไม่เป็น MVC จริงอีกต่อไป
tdammers

@ ผู้ส่งอีเมลฉันชอบความเป็นระเบียบเรียบร้อยของคำตอบของคุณและให้ความสำคัญกับตรรกะ ในมุมมองของคุณแอปพลิเคชันเกี่ยวข้องกับการคงอยู่และการประมวลผลธุรกรรมอยู่ที่ไหน ดูเหมือนว่า MVC ควรเป็นตัวย่อสี่ตัวอักษรเช่น MVCS ที่ S ใช้สำหรับการบริการ
flipdoubt

15

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

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

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

UPDATE

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

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

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


ดูเหมือนว่าคุณกำลังอธิบายถึงไอ้บ้าดีเดือดของ MVC และ MVVM ที่มีทั้งคอนโทรลเลอร์และดูโมเดล นอกจากนี้ฉันคิดว่าสถาปัตยกรรมที่คุณกำลังอธิบายอาจจะหนักสำหรับความต้องการของ OP
Waquo

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

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

1

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

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

ฉันไม่สามารถนึกถึงตัวอย่างที่ดีกว่าของบางสิ่งที่ไม่ใช่ตรรกะของตัวควบคุมและนั่นเป็นของโมเดลโดยตรง

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

โดยทั่วไปแล้วคอนโทรลเลอร์จะเชื่อมโยงโมเดลและมุมมอง (ซึ่งเป็นเนื้อและมันฝรั่งของแอพ) ในการพัฒนาโกโก้นั้นสามารถทำได้ง่ายจนถึงจุดที่คอนโทรลเลอร์ถูกจัดการผ่าน XCode GUI (วัตถุคอนโทรลเลอร์และการผูก)

ส่วน "รูปแบบการออกแบบ" ของ GoF ใน MVC อ้างถึงแบบหลวม ๆ :

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

MVC นั้นเกี่ยวกับ UIs โฟกัสอยู่ที่รุ่นและมุมมอง - การกำหนดและแสดงข้อมูล หมายเหตุ "สมัครสมาชิก / แจ้งเตือนโปรโตคอล" - นี่คือที่คอนโทรลเลอร์ของคุณเข้ามาคุณสามารถสร้างมุมมองทั้งหมดที่คุณต้องการ; ตราบใดที่พวกเขาปฏิบัติตามโปรโตคอลคุณจะไม่ต้องแตะรุ่นหรือตัวควบคุม

หากคุณกำลังพูดถึงการพัฒนาเว็บโดยเฉพาะ IMHO กรอบเว็บยอดนิยมจำนวนมากนั้นรวดเร็วและหลวมด้วยคำว่า MVC และคำจำกัดความของส่วนประกอบ


ฉันเป็นนักพัฒนา C # / Java (เพียงไม่กี่โครงการเท่านั้น) ดูเหมือนว่าฉันเข้าใจผิดว่าโมเดลทำอะไร การใส่ 'ตรรกะทางธุรกิจ' ลงในตัวควบคุมนั้นเป็นเพียงผลพวง (ความคิดของฉันไปแล้ว 'โอเคฉันเป็นแบบจำลองของข้อมูล (อ่าน: การเชื่อมต่อฐานข้อมูล / การจัดเก็บ) ดังนั้นตรรกะทางธุรกิจของฉันจึงต้องอยู่ในตัวควบคุมเพราะ ฉันจะใช้มันก่อนที่จะจัดเก็บข้อมูลในฐานข้อมูล 'เพียงแค่ต้องย้ายทุกอย่างลงหนึ่งระดับจากคอนโทรลเลอร์จริง ๆ แล้วมันแก้ปัญหาที่ฉันมีอยู่ในปัจจุบัน (รองรับ MySQL และ MSSQL ในโปรแกรมเดียว)
Steffen Winkler

0

ทำไมคุณไม่แนะนำชั้นบริการ?

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

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

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