เมื่อใดควรคลาสหรือโมดูลในแอสเซมบลี / DLL แยกต่างหาก


22

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

1) "การจัดกลุ่ม" ของคลาสทุกคลาสนั้นอยู่ใน DLL ของตัวเองเช่นที่เก็บบริการ DTO โครงสร้างพื้นฐานเป็นต้น

2) ทุกอย่างควรอยู่ใน DLL เดียว แต่แยกออกจาก namespaces / folder เช่นมี "Core" DLL ที่มี namespaces เพิ่มเติมเช่น Core.Repositories, Core.Services, Core.DTO เป็นต้น

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

สำหรับโมดูลใหม่ที่ฉันกำลังทำงานอยู่ฉันต้องการ / จำเป็นต้องมีชั้นการเข้าถึงข้อมูลแยกต่างหาก (คิดว่าเป็นการใช้งาน Repository Repository) แต่ฉันไม่ต้องการที่จะทิ้งมันไว้ในโฟลเดอร์ "BusinessObjects" กับอีก 160 (!) ชั้นเรียนที่นั่น ในเวลาเดียวกันฉันกังวลเกี่ยวกับการสร้าง Class Library ใหม่เนื่องจากทุกคนคุ้นเคยกับการบรรจุ Class ใน Library เดียว โฟลเดอร์ / namespace สามารถทำงานได้อย่างไรก็ตาม

คำตอบ:


12

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

ตัวอย่างเช่นจากสิ่งที่คุณพูดถึงฉันจะมีโครงการต่อไปนี้:

  • แกน
  • ข้อมูล
  • โดเมน (หรือ BusinessObjects)
  • บริการ
  • ยูทิลิตี้ (หรือผู้ช่วยเหลือ)

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

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

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

16

"ลุงบ๊อบ" Martin of Clean Code ชื่อเสียงหลักการของ SOLID ได้อธิบายหลักการสามข้อไว้ที่นี่ :

  • หลักการความเท่าเทียมกันของการใช้ซ้ำในรีลีส: แกรนูลของการใช้ซ้ำเป็นแกรนูลของการปลดปล่อย
  • หลักการปิดทั่วไป: คลาสที่เปลี่ยนแปลงร่วมกันจะถูกรวมเข้าด้วยกัน
  • หลักการนำมาใช้ซ้ำทั่วไป: คลาสที่ใช้ร่วมกันจะถูกจัดทำแพ็กเกจด้วยกัน

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


2
+1 หลักการเหล่านี้เป็นแนวทางที่ดี การแยกคลาสออกเป็นแอสเซมบลีที่แตกต่างกันนำเสนอข้อควรพิจารณาในการออกแบบเพิ่มเติม (เช่นเวอร์ชันใดของแอสเซมบลีแต่ละรุ่นที่ได้รับอนุญาตให้ทำงานร่วมกัน) การเพิ่ม codebase โดยรวมซึ่งจะเป็นการเพิ่มค่าใช้จ่าย
Ben

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

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

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

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

4

แนวทางที่อื่นที่ฉันทำงานด้วย:

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

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

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


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