2010-03-26 34 views
23

Chỉ cố gắng giữ nguyên nguyên tắc IOC của tôi.IOC - Có nên sử dụng các lớp với các phương thức trợ giúp tĩnh được kết nối với IOC không?

Q1: Phương pháp tĩnh - Nên sử dụng các lớp có phương pháp trợ giúp tĩnh có được kết nối với IOC không?

Ví dụ: nếu tôi có lớp HttpUtils với một số phương pháp tĩnh, tôi có nên chuyển nó sang các lớp logic nghiệp vụ khác thông qua IOC không?

Thực hiện theo về các vấn đề này có thể là:

Q2: Singletons - Điều gì về những thứ như khai thác gỗ, nơi bạn thường có thể nhận được quyền truy cập vào nó thông qua một Logger.getInstance() gõ gọi. Bạn có thường để nguyên điều này và KHÔNG sử dụng IOC để tiêm logger vào các lớp kinh doanh cần nó?

Q3: Lớp tĩnh - Tôi chưa thực sự sử dụng khái niệm này, nhưng có bất kỳ hướng dẫn nào về cách bạn thường xử lý việc này nếu bạn đang chuyển sang phương pháp tiếp cận dựa trên IOC.

Xin cảm ơn trước.

Trả lời

30

Điều thú vị về IoC là các đối tượng được viết theo kiểu thường được tách riêng khỏi các chi tiết đó.

Hãy sử dụng lớp tiện ích như một ví dụ:

public class HttpUtils 
{ 
    public static void DoStuff(int someValue) 
    { 
     // ... 
    } 
} 

Trong một ứng dụng không IoC tập trung, bạn có thể sử dụng phương pháp trực tiếp:

public class Foo 
{ 
    public int Value { get; set; } 

    public void DoStuff() 
    { 
     HttpUtils.DoStuff(Value); 
    } 
} 

Tuy nhiên, các cặp vợ chồng định nghĩa của DoStuff trực tiếp thực hiện. IoC phấn đấu để ly dị những loại chi tiết, vì vậy thay vì chúng tôi xác định các hoạt động ngày của riêng mình:

public interface IDoesStuff 
{ 
    void DoStuff(int someValue); 
} 

Sau đó, chúng tôi rời khỏi phòng trong Foo để thực hiện thay đổi:

public class Foo 
{ 
    private readonly IDoesStuff _doesStuff; 

    public Foo(IDoesStuff doesStuff) 
    { 
     _doesStuff = doesStuff; 
    } 

    public int Value { get; set; } 

    public void DoStuff() 
    { 
     _doesStuff.DoStuff(Value); 
    } 
} 

này tách riêng Foo từ HttpUtils. Người triển khai khái niệm DoStuff bây giờ là một chi tiết cấu hình, và không phải là một phụ thuộc vốn có (vì nó là với phương thức tĩnh).

Lưu ý rằng Foo không có ý tưởng nếu số IDoesStuff của nó là đơn lẻ hay không. Thời gian đó là cũng là chi tiết cấu hình và không phải chi tiết vốn có của Foo.

Tóm lại, IoC và static thường có tỷ lệ cược, vì IoC khuyến khích thay đổi và static, theo định nghĩa, ngăn chặn nó. Khai báo các phụ thuộc của bạn trong các nhà xây dựng của bạn, và bạn sẽ thấy bạn hầu như không bao giờ có bạn sử dụng chức năng static.

+0

cảm ơn Bryan - Điều này có nghĩa là có thể có thêm một số chi phí của IOC xây dựng những thứ (ví dụ như logger) mọi lúc? Ngoài ra đối với các lớp loại utils, tôi tự hỏi điều này sẽ làm cho tái cấu trúc khó hơn khi bạn cấu trúc lại các hàm trợ giúp của bạn giữa các lớp trợ giúp của bạn? (Tôi đang sử dụng ReSharper bản thân mình) - cảm ơn – Greg

+0

Hầu hết các container IoC cho phép một số loại phạm vi. Bằng cách này, tôi có nghĩa là bạn chỉ ra cho dù đối tượng của bạn được tạo ra mỗi lần (nhà máy), tạo ra một lần cho mỗi bối cảnh (đơn vị công việc), hoặc một lần cho mỗi ứng dụng (singleton). Điều này có nghĩa là bạn có thể đăng ký logger sao cho nó chỉ được tạo một lần. –

+2

Cuối cùng bạn muốn loại bỏ các lớp tiện ích. Mỗi phương thức trên mỗi lớp đó có cùng các vấn đề liên kết như phương thức 'HttpUtils.DoStuff' ở trên. Vì lý do đó, bạn không muốn yêu cầu * bất kỳ * mã nào phụ thuộc trực tiếp vào các thành viên 'static'. Thay vào đó, lấy phần thân của 'HttpUtils.DoStuff', đặt nó đằng sau' IDoesStuff' và xóa hoàn toàn phương thức từ 'HttpUtils'. Bây giờ, bất kỳ lớp nào có thể được gọi là phương thức tĩnh có thể thay thế chấp nhận 'IDoesStuff' trong hàm tạo của nó. Viola: không cần thiết cho lớp tiện ích! –

6

Vùng chứa IoC thường hữu ích khi tiêm đối tượng có trạng thái; hoặc các lớp hoặc các giao diện có nhiều hơn một triển khai thực hiện, ngay cả khi triển khai thứ hai là một mô hình cho mục đích thử nghiệm. Nếu cả hai điều này đều không đúng, bạn sẽ không đạt được gì bằng cách tiêm nó.thành ngữ phổ biến nhất trong những ngày này là để lớp của bạn được giao diện bởi một giao diện mà việc triển khai thực và giả có thể thực hiện cả hai.

1) Phương pháp tĩnh trên lớp trợ giúp - Không, chúng thường không được IoC tiêm. Thông thường họ là những tiện ích không quốc tịch.

Để sử dụng một ví dụ rất đơn giản, bạn không cần hai phiên bản của phương thức tiện ích được gọi là StringUtils.Reverse(). Bạn chỉ cần một, và bạn có thể dễ dàng viết các bài kiểm tra xung quanh nó bởi vì nó không có trạng thái hoặc phụ thuộc, do đó, hoàn toàn không có lợi ích để chế giễu nó ra. Ví dụ kiểm tra:

string reversedString = StringUtils.Reverse("input"); 
Assert.AreEqual("tupni", reversedString) 

Nếu tiện ích không phải là thực sự không quốc tịch (ví dụ phụ thuộc vào HttpContext.Current), sau đó bạn nên làm cho sự phụ thuộc rõ ràng bằng cách tiêm nó, và không thực hiện các tiện ích tĩnh.

2) Singletons: Thường thì có, đơn được tiêm. Nhưng một điều tốt về IoC là bạn lo lắng ít hơn về việc liệu chỉ có một thứ gì đó hay không. Bạn có được sự linh hoạt trong instancing bằng cách sử dụng IoC. Quyết định có một kiểu cụ thể là singleton hoặc instance mới mỗi lần trở thành một phần của cấu hình container IoC và không có gì khác trong mã cần phải thay đổi.

Vì vậy, singleton-hood dừng lại là một mối quan tâm riêng biệt phải được mã hóa vào lớp (và các lớp có nhiều mối quan tâm khi chúng không phải là xấu), và nó trở thành mối quan tâm của container IoC. Bạn không mã hóa lớp "như một singleton" với bất kỳ thứ gì đặc biệt như một hàm tạo riêng và phương thức public static GetInstance() nữa, bạn chỉ cần mã nó cho mối quan tâm chính, trong khi cấu hình của thùng chứa IoC chỉ định nếu nó là một singleton hay không, hoặc ở đâu đó ở giữa, như một ví dụ cho mỗi chủ đề.

3) Lớp tĩnh - là nơi tự nhiên cho phương pháp tĩnh. Cân nhắc tạo các phương thức mở rộng phương thức tĩnh khi thích hợp. Bạn không thể tiêm các lớp này, vì bạn không thể tạo chúng. Sử dụng các lớp tĩnh làm cho mã thủ tục không hướng đối tượng. Đây không phải là một điều xấu đối với các phương thức trợ giúp nhỏ, nhưng nếu phần lớn mã là như vậy, thì bạn không sử dụng các tính năng OO mạnh mẽ của nền tảng .Net.

2

Phương pháp tĩnh theo định nghĩa không cần một cá thể. DI/IOC nhằm thỏa mãn các giao diện với các lớp cụ thể và cho rằng lớp tĩnh của bạn cùng với các phương thức tĩnh của nó theo định nghĩa không thể thực hiện một giao diện hoặc mở rộng một lớp mà câu hỏi không có ý nghĩa. Không có điểm nào trong việc vượt qua lớp helper bởi vì người ta không cần cá thể để sử dụng các phương thức tĩnh. Mã của bạn sẽ luôn thực hiện cùng một phương thức trợ giúp tĩnh ngay cả khi không có một cá thể.

Trong ứng dụng được hỗ trợ IOC/DI, một ứng dụng sẽ xác định giao diện và có ít nhất một triển khai. Tất cả của nó về quản lý các trường hợp và phụ thuộc của họ.

0

Tiến trình tiến thoái lưỡng nan phát sinh khi các lớp tiện ích, nói, cần truy cập cơ sở dữ liệu. Trong khi trình truy cập db cần Ioc, do đó lớp tiện ích phải sử dụng Ioc, vì vậy nó không thể tĩnh.

Nhưng tôi thực sự muốn lớp tiện ích tĩnh nên dễ tiêu thụ. Tôi không muốn điền vào hàm tạo của mỗi lớp tiêu thụ, những người cần các lớp tiện ích.

Tiêu thụ chính các lớp có thể thậm chí không cần truy cập db. Vì vậy, tôi không muốn tiêm accessor db và chuyển nó vào các lớp tiện ích là tốt.

Bây giờ, không có giải pháp hoàn hảo nào.Một ngày nào đó tôi hy vọng chúng ta tiến thêm một bước nữa, ngoài việc xây dựng/tiêm tài sản, có "tiêm/cấu hình ngữ cảnh toàn cầu", hoặc "tiêm tĩnh", áp dụng Ioc ngoài tạo đối tượng.

Hãy nghĩ về, tại sao không?

+0

Đây có phải là câu trả lời hay chỉ là nhận xét về câu hỏi? –

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