ASP.NET MVC - ตรรกะทางธุรกิจควรมีอยู่ในคอนโทรลเลอร์หรือไม่


97

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

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


ลิงก์ไปยังบทความนั้นตายแล้ว - web.archive.org/web/20150906064521/http://devlicio.us/blogs/…เป็นสำเนาจาก archive.org สำหรับทุกคนที่สนใจ
Stuart Moore

คำตอบ:


75

ตรรกะทางธุรกิจควรอยู่ในโมเดลจริงๆ คุณควรตั้งเป้าไปที่นางแบบอ้วนคุมผอม

ตัวอย่างเช่นแทนที่จะมี:

public interface IOrderService{
    int CalculateTotal(Order order);
}

ฉันอยากจะมี:

public class Order{
    int CalculateTotal(ITaxService service){...}        
}

สิ่งนี้ถือว่าภาษีคำนวณโดยบริการภายนอกและต้องให้โมเดลของคุณทราบเกี่ยวกับอินเทอร์เฟซกับบริการภายนอกของคุณ

สิ่งนี้จะทำให้คอนโทรลเลอร์ของคุณมีลักษณะดังนี้:

public class OrdersController{
    public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...}

    public void Show(int id){
        ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService);
    }
}

หรืออะไรทำนองนั้น.


1
คุณจะฉีด Services ลงในคอนโทรลเลอร์ของคุณแทนที่จะเป็นที่เก็บหรือไม่? หลักการหน่วยงานเข้ามามีบทบาทอย่างไรในกรณีนี้?
Kevin Pang

ฉันเขียนบางสิ่งเพิ่มเติมฉันหวังว่านี่จะสมเหตุสมผลกว่านี้ คุณอาจต้องการอ่าน: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model แม้ว่าจะเกี่ยวกับ Rails แต่ก็ยังใช้งานได้ดีมาก
jonnii

ฉันจะเรียกบริการที่เก็บเป็นการส่วนตัว
Brad Wilson

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

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

65

ฉันชอบแผนภาพที่นำเสนอโดยไมโครซอฟท์รูปแบบและแนวทางปฏิบัติ และฉันเชื่อในสุภาษิต 'ภาพมีค่าพันคำ'

แผนภาพแสดงสถาปัตยกรรมของ MVC และเลเยอร์การบริการทางธุรกิจ


6
มีประโยชน์จริงๆ! คุณช่วยบอกฉันได้ไหมว่าคุณพบแผนภาพนี้ที่ไหนในไซต์นั้น
Rob Church

2
นี่มาจาก 'การใช้งานฝั่งเซิร์ฟเวอร์' ของ Microsoft msdn.microsoft.com/en-us/library/hh404093.aspx
Justin

ตกลง แต่พูดในแอป MVC - ตรรกะทางธุรกิจไปไหน? ดูเหมือนว่าเราต้องการชั้นบริการเสริมหรืออะไร?!
niico

14

นี่เป็นคำถามที่น่าสนใจ

ฉันคิดว่าน่าสนใจที่แอปพลิเคชัน MVC ตัวอย่างจำนวนมากไม่สามารถปฏิบัติตามกระบวนทัศน์ MVC ได้ในแง่ของการวาง "ตรรกะทางธุรกิจ" ไว้ในแบบจำลองอย่างแท้จริง Martin Fowler ได้ชี้ให้เห็นว่า MVC ไม่ใช่แบบแผนในความหมายของ Gang Of Four แต่ก็เป็นกระบวนทัศน์ที่โปรแกรมเมอร์จะต้องเพิ่มรูปแบบไปถ้าพวกเขากำลังสร้างสิ่งที่อยู่นอกเหนือแอปของเล่น

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

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


14

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

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


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

9

ไม่ควรมีตรรกะทางธุรกิจในตัวควบคุม ตัวควบคุมควรมีขนาดเล็กที่สุดเท่าที่จะทำได้ตามรูปแบบ:

  1. ค้นหาเอนทิตีโดเมน
  2. ดำเนินการกับเอนทิตีโดเมน
  3. เตรียมข้อมูลเพื่อดู / ส่งคืนผลลัพธ์

นอกจากนี้ตัวควบคุมสามารถมีตรรกะของแอปพลิเคชันบางอย่าง

แล้วฉันจะวางตรรกะทางธุรกิจไว้ที่ไหน ในรุ่น

Model คืออะไร? ตอนนี้เป็นคำถามที่ดี โปรดดูบทความ Microsoft Patterns and Practices (ขอชื่นชม AlejandroR เพื่อการค้นหาที่ยอดเยี่ยม) ในที่นี้มีโมเดลสามประเภท:

  • View Model : นี่เป็นเพียงกระเป๋าข้อมูลที่มีตรรกะน้อยที่สุดในการส่งผ่านข้อมูลจากและไปยังมุมมองประกอบด้วยการตรวจสอบฟิลด์พื้นฐาน
  • แบบจำลองโดเมน : แบบจำลองไขมันที่มีตรรกะทางธุรกิจดำเนินการกับเอนทิตีข้อมูลเดียวหรือหลายรายการ (เช่นเอนทิตี A ในสถานะที่กำหนดมากกว่าการดำเนินการกับเอนทิตี B)
  • โมเดลข้อมูล : โมเดลที่รับรู้การจัดเก็บตรรกะที่อยู่ภายในเอนทิตีเดียวเกี่ยวข้องกับเอนทิตีนั้นเท่านั้น (เช่นถ้าฟิลด์เป็นฟิลด์ข)

แน่นอน MVC เป็นกระบวนทัศน์ที่มีความหลากหลายแตกต่างกัน สิ่งที่ฉันอธิบายที่นี่คือ MVC ครอบครองชั้นบนสุดเท่านั้นวิดีโอบทความนี้บน Wikipedia

ปัจจุบัน MVC และ Model-view-Presenter (MVP) ที่คล้ายกันเป็นรูปแบบการออกแบบ Separation of Concerns ที่ใช้เฉพาะกับเลเยอร์การนำเสนอของระบบที่ใหญ่กว่า ในสถานการณ์ง่ายๆ MVC อาจแสดงถึงการออกแบบหลักของระบบการเข้าถึงฐานข้อมูลโดยตรง อย่างไรก็ตามในสถานการณ์ส่วนใหญ่ Controller และ Model ใน MVC มีการพึ่งพาชั้น / ชั้นบริการหรือชั้นข้อมูล ทั้งหมดนี้เกี่ยวกับสถาปัตยกรรมไคลเอนต์ - เซิร์ฟเวอร์


-1

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

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