2009-09-10 29 views
5

Tôi vừa xem xong một tập phim của Bob Martin tại NDC, nơi ông nói "sử dụng" chỉ thị trong C# ở đầu trang là xấu vì khớp nối chặt chẽ mà họ tạo ra/ngụ ý giữa các thành phần.Các lựa chọn thay thế cho từ khóa chỉ thị "sử dụng" trong C#?

Có cách nào để sử dụng .dll bên ngoài mà không thêm tham chiếu dự án và tuyên bố sử dụng?

Tôi nhớ V6 được sử dụng để cho phép bạn tạo một đối tượng bằng chuỗi ProgId - Tôi không chắc đó là kỹ thuật tôi đang tìm kiếm, nhưng đó là ví dụ về ngôn ngữ không cần dự án tham chiếu để sử dụng dll.

EDIT: Here is a link to the conference. Xin lỗi tôi không có báo giá chính xác hoặc phút trong presenation, tôi sẽ theo bộ nhớ.

+1

Anh ấy có thực sự nói điều đó, hay đó là điều bạn hiểu về những gì anh ấy nói? –

+3

Một liên kết đến điều này sẽ hữu ích. Tôi muốn nghe những gì anh ấy thực sự nói. – tvanfosson

+6

Chỉ để tránh nhầm lẫn, Microsoft gọi nó là "chỉ thị" sử dụng. Câu lệnh using (từ khóa) bình thường sẽ đề cập đến câu lệnh được sử dụng bên trong các phương thức để tự động gọi Dispose trên các tài nguyên. – Ash

Trả lời

6

Nó không phải là sử dụng tuyên bố bản thân mà là xấu - đó là nếu bạn nhận được quá nhiều trong số họ.

Tuyên bố như using System; hiếm khi là vấn đề, nhưng nếu bạn có nhiều (tôi muốn nói nhiều hơn 3-6, tùy thuộc vào cái nào) trong cùng một tệp mã, có thể là chỉ báo khớp nối chặt chẽ.

Bạn cũng có thể áp dụng quy tắc chung tương tự cho số lượng tham chiếu trong chính dự án.

Giải pháp cho khớp nối chặt chẽ là lập trình cho giao diện và Dependency Injection (DI).

Cách ProgId để thực hiện những điều bạn có thể nhớ từ VB đơn giản là thực hiện COM. Về bản chất, bạn đã sử dụng ProgId đó để có được một tham chiếu đến một cá thể đã thực hiện giao diện mong muốn. Nhược điểm là điều này chỉ làm việc khi đối tượng COM đã được đăng ký toàn cầu. Hãy nhớ địa ngục dll?

Bạn vẫn có thể áp dụng nguyên tắc tương tự bằng cách sử dụng các hương vị nhất định của DI, chỉ bây giờ giao diện là loại .NET và không được định nghĩa trong IDL, và bạn cần một số loại DI Container để cung cấp việc triển khai cụ thể.

+1

Tôi muốn viết "nó ** có thể ** là dấu hiệu của khớp nối chặt chẽ" thay vì "nếu có thể là dấu ** cho khớp nối chặt **" –

+0

@Vinko Vrsalovic: Không, tôi không đồng ý: Nếu bạn có hai mươi câu bằng cách sử dụng, nó chắc chắn là một dấu hiệu * * của khớp nối chặt chẽ. –

+0

Sau đó nói như vậy: "nó là một dấu hiệu ** ** của khớp nối chặt chẽ" –

6

using chỉ là lối tắt cho không gian tên, chúng không phải là tham chiếu đến tệp bên ngoài. Do đó, điều này không thực sự có ý nghĩa. Dù sao, những gì người ta có thể làm là có một DLL giao diện (một DLL chỉ với các giao diện), để bạn tự động tải và sử dụng các assembly khác nhau và tạo các kiểu (thông qua sự phản chiếu) mà bạn có thể truyền đến các giao diện nổi tiếng. Đây là cách thích hợp để nới lỏng các tham chiếu bên ngoài trong khi vẫn giữ được lợi ích của ngôn ngữ được đánh máy mạnh và ràng buộc sớm.

Hãy xem các lớp AssemblyAppDomain để tải các hội đồng và Activator để tạo các trường hợp loại theo tên.

+6

Đồng ý. Anh chàng này nói rằng những câu nói 'sử dụng' rõ ràng là không rõ anh ta đang nói về cái gì. – Noldorin

+4

@Noldorin: Robert C. Martin không biết anh ta đang nói về cái gì ?! –

+1

Hoặc anh ta bị hiểu lầm. Ai là hoặc là sai không quan trọng nhiều, bởi vì "tin nhắn nhận được" là không có ý nghĩa. – Lucero

7

Tôi tin rằng Bob Martin thực sự đề cập đến ràng buộc sớm và muộn.

Trong .NET ràng buộc trễ có thể thông qua sự phản chiếu và cụ thể hơn là lớp Activator cho phép tạo kiểu trong một assembly ngoài bằng tên tập tin hoặc tên assembly.

Thông thường, việc sử dụng các chỉ thị (không phải báo cáo sử dụng) sẽ đi đôi với việc tham chiếu trực tiếp một hội đồng bên ngoài. I E. Bạn thêm một tham chiếu đến một assembly và sau đó thêm các chỉ thị bằng cách sử dụng để tránh cần phải phân cấp toàn bộ hệ thống phân cấp không gian tên khi bạn sử dụng các kiểu bên ngoài. Vì vậy, nếu bạn tìm thấy mã của bạn có một số lượng lớn các chỉ thị bằng cách sử dụng ở trên cùng, có thể bạn đang tham khảo trực tiếp nhiều loại khác và do đó tăng sự ghép nối/phụ thuộc của mã của bạn lên các loại này.

Tôi đoán đây là lý do tại sao Bob đề cập đến chúng là xấu. Câu trả lời cho câu hỏi "điều này thực sự xấu?" là một phụ thuộc rất chủ quan và bối cảnh.

Nói chung, việc tách khớp các thành phần hầu như luôn là mục tiêu tốt để thiết kế phần mềm. Điều này là bởi vì nó cho phép bạn thay đổi các phần của hệ thống của bạn với tác động tối thiểu trên phần còn lại của hệ thống. Có đọc một hoặc hai cuốn sách của Bob Martins, tôi cho rằng đây là những gì anh ta đang nhận được.

1

Bạn có thể làm những gì bạn đang đề cập đến thông qua sự phản ánh. Bạn có thể tải các hội đồng tại thời gian chạy, và phản ánh thông qua nó để có được các lớp học vv và gọi chúng tự động.

Cá nhân, tôi sẽ không thực hiện việc này để tránh ghép nối. Đối với tôi đó là một sử dụng xấu của sự phản ánh, và tôi sẽ thay vì thêm nó vào dự án và tham khảo nó, trừ khi có một lý do cụ thể tại sao không làm như vậy. Reflection cho biết thêm chi phí cho hệ thống, và bạn không có được lợi thế về an toàn thời gian biên dịch.

+0

Hơn nữa, "kỹ thuật" này * sẽ không * tránh ghép nối. Mã của bạn không phải là bất kỳ ít kết hợp với một DLL bên ngoài bởi vì bạn đang gọi nó tự động - nếu DLL không có, mã của bạn sẽ không hoạt động. – MusiGenesis

+1

Nó làm giảm khớp nối nếu bạn có một hội đồng giao diện và tải các đối tượng động có giao diện. Việc tiêm phụ thuộc cũng là một cách tiếp cận tốt. – kenny

+0

@Kenny: bạn hoàn toàn đúng trong trường hợp đó. Tôi đã làm cho nhiều điểm rằng nếu bạn chỉ cần loại bỏ một tài liệu tham khảo và thay vì tải nó tự động, bạn không cải thiện tình hình. – MusiGenesis

2

Bạn có thể sử dụng phản ánh:

// Load the assembly 
Assembly assembly = Assembly.LoadFrom(@"c:\path\Tools.dll"); 
// Select a type 
Type type = assembly.GetType("Tools.Utility"); 
// invoke a method on this type 
type.InvokeMember("SomeMethod", BindingFlags.Static, null, null, new object[0]); 
+4

Loại gọi này được gọi là trễ ràng buộc và nó không chỉ chậm và khá dễ bị lỗi, mà còn khá cồng kềnh trong các ngôn ngữ như C# mà không được thiết kế để hỗ trợ kết buộc muộn của hộp (ví dụ: thông qua phép thuật biên dịch). Nếu có thể, tôi sẽ tránh phương pháp này. – Lucero

+0

Tốt hơn nên sử dụng khung DI cho loại điều này, một cách trung thực. Tốt hơn cho noobish là tốt. – Will

Các vấn đề liên quan