Tôi không thích tiêm phụ thuộc vào hàm tạo.Một giải pháp thay thế khả thi để tiêm phụ thuộc?
Tôi tin rằng nó làm tăng độ phức tạp của mã và giảm khả năng bảo trì, và tôi muốn biết nếu có bất kỳ giải pháp thay thế khả thi nào.
Tôi không nói về khái niệm phân tách triển khai khỏi giao diện và có cách giải quyết động (đệ quy) một tập hợp các đối tượng từ giao diện. Tôi hoàn toàn ủng hộ điều đó. Tuy nhiên, cách xây dựng truyền thống dựa trên cách làm điều này dường như có một vài vấn đề.
1) Tất cả các thử nghiệm phụ thuộc vào các nhà thầu.
Sau khi sử dụng DI rộng rãi trong một MVC dự án 3 C# so với năm ngoái, tôi thấy mã của chúng tôi đầy những điều như thế này:
public interface IMyClass {
...
}
public class MyClass : IMyClass {
public MyClass(ILogService log, IDataService data, IBlahService blah) {
_log = log;
_blah = blah;
_data = data;
}
...
}
Vấn đề: Nếu tôi cần một dịch vụ khác trong việc thực hiện của tôi, tôi phải thay đổi nhà xây dựng; và điều đó có nghĩa là tất cả các bài kiểm tra đơn vị cho giai đoạn nghỉ học này.
Ngay cả các thử nghiệm không liên quan gì đến chức năng mới yêu cầu ít nhất là tái cấu trúc để thêm các tham số bổ sung và chèn một giả vào đối số đó. Điều này có vẻ như một vấn đề nhỏ, và các công cụ tự động như trợ giúp resharper, nhưng nó chắc chắn gây phiền nhiễu khi một thay đổi đơn giản như thế này gây ra hơn 100 thử nghiệm để phá vỡ. Thực tế nói rằng tôi đã nhìn thấy những người làm những điều câm để tránh thay đổi các nhà xây dựng hơn là cắn đạn và sửa chữa tất cả các bài kiểm tra khi điều này xảy ra.
2) Các phiên bản dịch vụ được truyền đi xung quanh không cần thiết, tăng độ phức tạp của mã.
public class MyWorker {
public MyWorker(int x, IMyClass service, ILogService logs) {
...
}
}
Tạo một thể hiện của lớp này nếu chỉ có thể nếu tôi bên trong một bối cảnh mà các dịch vụ được có sẵn và đã tự động được giải quyết (ví dụ. Controller) hoặc, không hạnh phúc, bằng cách thông qua các ví dụ dịch vụ xuống nhiều chuỗi các lớp trợ giúp.
tôi thấy mã như này tất cả các thời gian:
public class BlahHelper {
// Keep so we can create objects later
var _service = null;
public BlahHelper(IMyClass service) {
_service = service;
}
public void DoSomething() {
var worker = new SpecialPurposeWorker("flag", 100, service);
var status = worker.DoSomethingElse();
...
}
}
Trong trường hợp ví dụ này là không rõ ràng, những gì tôi đang nói về là đi qua các trường hợp giao diện DI giải quyết xuống qua nhiều lớp từ không có lý do khác với ở lớp dưới cùng, chúng cần thiết để tiêm vào một cái gì đó.
Nếu một lớp không phụ thuộc vào một dịch vụ, nó phải có sự phụ thuộc vào dịch vụ đó. Ý tưởng này có sự phụ thuộc 'tạm thời' khi một lớp không sử dụng dịch vụ nhưng chỉ đơn giản là chuyển nó theo ý kiến của tôi là vô nghĩa.
Tuy nhiên, tôi không biết giải pháp nào tốt hơn.
Có điều gì mang lại lợi ích của DI mà không có những vấn đề này không?
Tôi đã dự tính sử dụng khuôn khổ DI bên trong các nhà thầu thay vì điều này giải quyết một vài vấn đề:
public MyClass() {
_log = Register.Get().Resolve<ILogService>();
_blah = Register.Get().Resolve<IBlahService>();
_data = Register.Get().Resolve<IDataService>();
}
Có bất cứ nhược điểm để làm điều này?
Nó có nghĩa là các bài kiểm tra đơn vị phải có 'kiến thức trước' của lớp để ràng buộc mocks cho các loại chính xác trong quá trình thử nghiệm init, nhưng tôi không thể thấy bất kỳ nhược điểm nào khác.
NB. Ví dụ của tôi là trong C#, nhưng tôi đã vấp vào các vấn đề tương tự trong các ngôn ngữ khác quá, và đặc biệt là ngôn ngữ với sự hỗ trợ dụng cụ ít trưởng thành hơn là những nhức đầu lớn.
nếu bạn đặt nó bên trong hàm tạo, bạn tạo phụ thuộc vào thành phần di được sử dụng. nếu bạn truyền các giao diện cho constructor, bạn có thể thay đổi thành phần di cho phép nói Autofac với NInject hoặc Castle etc. Vì vậy, nếu bạn thực sự chắc chắn bạn sẽ không bao giờ thay đổi thành phần di được sử dụng và tiếp tục cho phép nói Autofac đây là một giải pháp rất khả thi. –