ฉันสามารถบังคับการพึ่งพาระหว่างเนมสเปซใน C # ได้หรือไม่

ฉันสามารถจำกัดคลาสจากเนมสเปซเฉพาะไม่ให้อ้างอิงคลาสในเนมสเปซเฉพาะอื่นได้หรือไม่ เนมสเปซทั้งสองมีอยู่ในแอสเซมบลี .NET เดียวกัน

ตัวอย่าง:

namespace LegacyCode
{
    class LegacyClass { ... }
}

namespace NewCode
{
    class NewClass {...}
}

ฉันไม่ต้องการให้คลาสจาก 'NewCode' สามารถอ้างอิงคลาสใน 'LegacyCode' ได้

ตัวเลือก:

  1. มีแอสเซมบลีที่แตกต่างกัน (ทำให้การปรับใช้ยากขึ้น การสร้างใช้เวลานานขึ้น)
  2. การใช้เครื่องมือเช่น NDetect (เสียเงิน!)

ใครมีความคิดอื่น ๆ อีกบ้าง?


person GarethOwen    schedule 20.07.2010    source แหล่งที่มา


คำตอบ (5)


ลองทำเครื่องหมายคลาสด้วย แอตทริบิวต์ที่ล้าสมัย นี่จะทำให้โค้ดใดๆ ที่ไม่ได้ทำเครื่องหมายว่า 'ล้าสมัย' เพื่อสร้างคำเตือนระหว่างการคอมไพล์

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

แก้ไข:

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

แก้ไข #2:

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

person MPritchard    schedule 20.07.2010
comment
ตัวสร้างที่โอเวอร์โหลดตัวหนึ่งของคลาส ObsoleteAttribute ใช้พารามิเตอร์ bool ที่ระบุว่ามีการอ้างอิงหรือไม่ ถึงคลาสที่ทำเครื่องหมายไว้ควรทำให้เกิดข้อผิดพลาดในการคอมไพล์ - person Dan Tao; 20.07.2010
comment
ขอบคุณ Dan - ฉันไม่เคยสังเกตมาก่อน! - person MPritchard; 20.07.2010

บันทึกการออกแบบ พูดคุยกับผู้คน ทบทวนโค้ด อย่าพยายามโยนเทคโนโลยีใส่ปัญหาของผู้คน (ส่วนการตรวจสอบจะมีประสิทธิภาพมากขึ้นด้วยเครื่องมืออย่าง NDetect)

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

person Pontus Gagge    schedule 20.07.2010
comment
โดยหลักการแล้ว ฉันคิดว่าคุณพูดถูก และนั่นคือวิธีแก้ปัญหาในปัจจุบันของเรา (เพื่อสื่อสารกฎ) แต่ในทางปฏิบัติสิ่งนี้ไม่ได้ผล นักพัฒนาที่มีประสบการณ์ได้ตรวจสอบคลาสใหม่ที่ทำลายการพึ่งพา - และผู้ตรวจสอบก็พลาดไปเช่นกัน นั่นคือเหตุผลที่ฉันต้องการวิธีควบคุมสิ่งนี้ที่เข้มงวดกว่านี้ - person GarethOwen; 20.07.2010
comment
ดีใจที่ได้ยิน! ฉันคิดว่าคุณจะต้องกัดกระสุนและยอมรับค่าใช้จ่ายทั้งในรูปแบบของการจัดการแอสเซมบลีแยกต่างหากหรือในเครื่องมือบังคับใช้การพึ่งพา ฉันไม่ทราบทางเลือกฟรีใด ๆ สำหรับ NDepend (และแน่นอนว่าไม่ใช่ชุดฟีเจอร์) แต่การทำลายการพึ่งพาจะทำให้คุณเสียเงิน โดยเฉพาะอย่างยิ่งหากการบำรุงรักษาดำเนินต่อไปอีกสองสามปี การลงทุนล่วงหน้าเพื่อป้องกันหนี้ทางเทคนิคในภายหลังฟังดูดีกว่า - person Pontus Gagge; 20.07.2010

ฉันคิดว่าการประกอบแบบแยกเป็นวิธีแก้ปัญหาเดียวที่เป็นไปได้

person Incognito    schedule 20.07.2010

MS ใช้แอตทริบิวต์ System.ObsoleteAttribute เพื่อทำเครื่องหมายรหัสล้าสมัย/ดั้งเดิม แอ็ตทริบิวต์นี้จัดเตรียม ctor ที่สร้างข้อผิดพลาดของคอมไพเลอร์ แม้ว่าฉันจะใช้สิ่งนี้หากมีคลาสดั้งเดิมไม่มากเกินไป

person Florian Reischl    schedule 20.07.2010
comment
ฉันไม่ทราบถึงคุณลักษณะที่ล้าสมัย - ฟังดูดี แต่น่าเสียดายที่เรามีคลาสดั้งเดิมมากมาย :( - person GarethOwen; 20.07.2010
comment
เชื่อฉันเถอะ การใช้เวลาช่วงบ่ายในการคัดลอกและวาง [ล้าสมัย] นั้นคุ้มค่า หากโค้ดของคุณถูกจัดวางอย่างเหมาะสมในโฟลเดอร์ ดังนั้นโค้ดที่ล้าสมัยทั้งหมดของคุณจึงอยู่ในโฟลเดอร์เดียวกัน ให้ลองค้นหาและแทนที่โดยใช้ Regex ใน Visual Studio ฉันคิดว่าคุณจะต้องการสิ่งนี้กับคลาส enums & structs - person MPritchard; 20.07.2010
comment
เจ้านายไม่ค่อยพอใจกับการที่ฐานโค้ดของเราถูกทำเครื่องหมายว่าล้าสมัยถึง 90% - person GarethOwen; 20.07.2010
comment
เห็นด้วยกับคุณ เอ็มพริ้นท์ บางทีฉันอาจจะเขียนแอตทริบิวต์ที่กำหนดเองของตัวเอง ซึ่งเหมือนกับ 'ล้าสมัย' แต่มีชื่อที่เป็นมิตรกว่า - person GarethOwen; 20.07.2010
comment
Obsolete เป็นอีกคำหนึ่งของ Depreciated ใช่ไหม? - person Nate; 20.07.2010
comment
@GarethOwen: การใช้ Obsolete ไม่ใช่ประโยชน์ของคอมไพเลอร์รายงานคำเตือน/ข้อผิดพลาดเมื่อมีอยู่ในรหัสอ้างอิงใช่หรือไม่ ถ้าเป็นเช่นนั้น แสดงว่าคุณโชคไม่ดีกับการเขียนของคุณเอง ฉันเกรงว่า: stackoverflow.com/questions/154109/custom-compiler-warnings/ ฉันพยายามดิ้นรนเพื่อทำความเข้าใจว่าเกิดอะไรขึ้นกับการทำเครื่องหมายโค้ดที่ล้าสมัยว่าล้าสมัย.... - person MPritchard; 20.07.2010
comment
@Nate Bross: ฉันคิดว่าคุณหมายถึงเลิกใช้แล้ว .. เลิกใช้แล้วหมายถึงการไม่อนุมัติอย่างจริงจังของ Obsolete หมายถึงไม่ใช้งานทั่วไปอีกต่อไปหรือเพื่อจุดประสงค์นี้จึงถูกแทนที่ด้วยสิ่งใหม่กว่า อย่างไรก็ตาม สำหรับคำเตือนของคอมไพเลอร์ ไม่มีตัวเลือกสำหรับ Deprecated ดังนั้น Obsolete คือทั้งหมดที่เรามีและใกล้เพียงพอแล้ว - person NotMe; 20.07.2010
comment
เราไม่มีแผนที่จะแทนที่โค้ดเดิม ซึ่งเป็นเหตุผลว่าทำไม 'ล้าสมัย' จึงรู้สึกผิด - ฉันแค่ไม่อยากให้โค้ดใหม่อ้างอิงโดยตรง ในไม่กี่แห่งที่ฉันต้องอ้างอิงโค้ดดั้งเดิม ฉันจะซ่อนมันไว้ด้านหลังอินเทอร์เฟซ (ที่ไม่ใช่แบบเดิม) - person GarethOwen; 20.07.2010
comment
ใครรู้อะไรเกี่ยวกับ FxCop บ้าง? ฉันสามารถเขียนกฎที่กำหนดเองเพื่อตรวจจับเมื่อคลาสจากเนมสเปซ 'newCode' อ้างอิงคลาสในเนมสเปซ 'ดั้งเดิม' ได้หรือไม่ - person GarethOwen; 21.07.2010

อย่างที่คนอื่นบอก ให้ใช้แอตทริบิวต์ที่ล้าสมัย (แม้ว่าคุณจะต้องเปลี่ยนชื่อก็ตาม)

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

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

person NotMe    schedule 20.07.2010
comment
เราได้เพิ่มมันเข้าไปเป็นสถิติบิลด์ให้กับบิลด์ TeamCity ของเรา มีบางอย่างที่ดีเกี่ยวกับการเห็นกราฟค่อยๆ มีแนวโน้มไปที่ 0 - person MPritchard; 20.07.2010