. NET MVC สถาปัตยกรรมโครงการ / ชั้น


11

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

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

นอกจากนี้สิ่งที่จะเป็นตรรกะของแอปพลิเคชันซึ่งตรงข้ามกับธุรกิจ - ฉันคาดเดาสิ่งต่าง ๆ เช่นการตรวจสอบการป้อนข้อมูลเซสชัน / ผู้ใช้?

ตัวอย่างเช่นตัวควบคุมรถอาจส่งคืนผลลัพธ์การกระทำ / มุมมองที่แสดงรายการรถยนต์สิบอันดับแรกที่กรองตามประเภทและ mpg ที่ดีที่สุด ดังนั้นสมมติว่าฉันมีICarRepository'carRepo' ฉีดเข้าไปในคอนโทรลเลอร์ของฉัน (โดยใช้รูปแบบพื้นที่เก็บข้อมูล / DI) ฉันกรองรถยนต์ของฉันจากพารามิเตอร์วิธีการกระทำเช่นvar cars = carRepo.getCarsByType("hatchback");

ดังนั้นฉันจึงเก็บความรู้การเข้าถึงข้อมูลออกจากตัวควบคุมของฉันโดยใช้ที่เก็บตอนนี้เพื่อให้ตรรกะทางธุรกิจออกจากตัวควบคุมโดยใช้รูปแบบโดเมน - var result = new MpgCalculator (cars); - สมมติว่าฉันต้องการคลาสเครื่องคิดเลขเพราะมันต้องใช้ตรรกะเพิ่มเติมเพื่อคำนวณประสิทธิภาพการใช้เชื้อเพลิงที่ดีที่สุดมากกว่าแค่การโหลด / กรองเอนทิตีจาก DB ดังนั้นตอนนี้ฉันมีชุดข้อมูลสำหรับมุมมองของฉันในการเรนเดอร์ที่ใช้ที่เก็บเพื่อดึงข้อมูลจากเลเยอร์การเข้าถึงข้อมูลและวัตถุเฉพาะโดเมนเพื่อประมวลผลและดำเนินงานที่เกี่ยวข้องกับธุรกิจในข้อมูลนั้น

ฉันทำผิดพลาดที่นี่ เรายังต้องใช้รูปแบบพื้นที่เก็บข้อมูลหรือฉันสามารถโค้ดกับส่วนต่อประสานเพื่อแยกแยะ ORM และทดสอบได้หรือไม่ ในหัวข้อนี้เนื่องจากคลาส data access ของฉันเป็นรูปธรรม dbcontext อยู่ใน data layer คำจำกัดความอินเตอร์เฟสควรเข้าสู่ domain / business layer หมายความว่าหากเทคโนโลยีการเข้าถึงข้อมูลเปลี่ยนแปลงไปเลเยอร์อื่น ๆ ของฉันจะไม่ได้รับผลกระทบหรือไม่

จากสิ่งที่ฉันได้ศึกษาไปแล้วโครงสร้างของฉันมีลักษณะเช่นนี้:

MVC Internet Application -> โครงการอินเทอร์เน็ตมาตรฐาน - รุ่นที่นี่คือ ViewModels

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

จำเป็นต้องมีที่เก็บบทคัดย่อ? -> ฉันได้ยินการถกเถียงกันมากมายเกี่ยวกับเรื่องนี้โดยเฉพาะเมื่อใช้ ORM

ชั้นข้อมูล -> คลาสเอนทิตี (รถยนต์, รถตู้, รถจักรยานยนต์), DbContext - เลเยอร์เทคโนโลยีการเข้าถึงข้อมูลคอนกรีต

คำตอบ:


26

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

การนำเสนอ <---> ตรรกะทางธุรกิจ <---> การเข้าถึงข้อมูล

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

MVC (การนำเสนอ)

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

Repository / ORM (การเข้าถึงข้อมูล)

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

ตรรกะทางธุรกิจ

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

แนวทางของคุณ

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

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

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


สวัสดี Eric คำตอบที่ยอดเยี่ยมเกี่ยวกับที่เก็บฉันคิดว่าคลาสที่เป็นรูปธรรมจะอยู่ในชั้นการเข้าถึงข้อมูลและ 'ICarRepository' ฯลฯ ในชั้นธุรกิจ / บริการหรือไม่ จากนั้นฉันสามารถฉีดบริการลงในคอนโทรลเลอร์ซึ่งอาจมีที่เก็บอย่างน้อย 1 แห่งขึ้นอยู่กับข้อกำหนด?
Michael Harper

@MichaelHarper ใช่ว่ามันเป็นวิธีที่ดีที่สุดในการทำเรื่องนี้
Eric King

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

1
@ ทอมใช่คุณมีจุดดี ฉันคิดว่าการอนุญาตง่าย ๆ เช่นเดียวกับที่ผู้ใช้สามารถเข้าถึงเส้นทางนี้แต่อาจมีมากกว่านั้น ส่วน "มากกว่านั้น" อยู่ในเลเยอร์ธุรกิจ
Eric King

1
@HunterNelson หากคุณจับคู่ภาพเข้ากับโมเดลวิวเดอร์การแมปควรเกิดขึ้นที่มุมมองในเลเยอร์การนำเสนอ มันจะไม่สมเหตุสมผลเลย
Eric King

0

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

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

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


ขอบคุณสำหรับการตอบกลับ William 😊ฉันพิจารณาวัตถุธุรกิจ / ตรรกะและโดเมนของ บริษัท เป็น 'model' ซึ่งคอนโทรลเลอร์ใช้ในการประมวลผลการกระทำของผู้ใช้และ viewmodels เป็นแบบจำลองเฉพาะซึ่งสามารถมีกลุ่มของโมเดลเป็นต้น
Michael Harper
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.