Mẫu chống tiêm phụ thuộc hợp pháp duy nhất mà tôi biết là mẫu Định vị dịch vụ , là mẫu chống mẫu khi sử dụng khung DI cho nó.
Tất cả các mô hình chống được gọi là DI khác mà tôi đã nghe nói, ở đây hoặc ở nơi khác, chỉ là các trường hợp cụ thể hơn một chút về các mẫu chống OO / thiết kế phần mềm nói chung. Ví dụ:
Người xây dựng quá tiêm là vi phạm Nguyên tắc Trách nhiệm duy nhất . Quá nhiều đối số constructor chỉ ra quá nhiều phụ thuộc; quá nhiều phụ thuộc chỉ ra rằng lớp đang cố gắng làm quá nhiều. Thông thường lỗi này tương quan với các mùi mã khác, chẳng hạn như tên lớp dài bất thường hoặc mơ hồ ("người quản lý"). Các công cụ phân tích tĩnh có thể dễ dàng phát hiện khớp nối quá mức / liên tục.
Tiêm dữ liệu, trái ngược với hành vi, là một kiểu con của mô hình chống poltergeist , với 'geist trong trường hợp này là container. Nếu một lớp cần phải biết ngày giờ hiện tại, bạn không tiêm một DateTime
, đó là dữ liệu; thay vào đó, bạn đưa ra một sự trừu tượng hóa trên đồng hồ hệ thống (tôi thường gọi là của tôi ISystemClock
, mặc dù tôi nghĩ rằng có một cái chung hơn trong dự án SystemWrappers ). Điều này không chỉ đúng với DI; nó thực sự cần thiết cho khả năng kiểm tra, để bạn có thể kiểm tra các chức năng thay đổi theo thời gian mà không cần phải thực sự chờ đợi chúng.
Tuyên bố mỗi vòng đời như Singleton, đối với tôi, là một ví dụ hoàn hảo về lập trình sùng bái hàng hóa và ở mức độ thấp hơn là " đối tượng dừng " được đặt tên thông tục . Tôi đã thấy lạm dụng đơn lẻ nhiều hơn tôi quan tâm để nhớ, và rất ít trong số đó liên quan đến DI.
Một lỗi phổ biến khác là các loại giao diện dành riêng cho việc triển khai (có tên lạ như IOracleRepository
) được thực hiện chỉ để có thể đăng ký nó trong vùng chứa. Điều này tự nó đã vi phạm Nguyên tắc đảo ngược phụ thuộc (chỉ vì nó là một giao diện, không có nghĩa là nó thực sự trừu tượng) và thường bao gồm sự phình to giao diện vi phạm Nguyên tắc phân chia giao diện .
Lỗi cuối cùng tôi thường thấy là "sự phụ thuộc tùy chọn", mà họ đã làm trong NerdDinner . Nói cách khác, có một hàm tạo chấp nhận phép nội xạ phụ thuộc, nhưng cũng có một hàm tạo khác sử dụng triển khai "mặc định". Điều này cũng vi phạm DIP và có xu hướng dẫn đến vi phạm LSP , theo thời gian, các nhà phát triển, bắt đầu đưa ra các giả định xung quanh việc triển khai mặc định và / hoặc bắt đầu các trường hợp mới sử dụng hàm tạo mặc định.
Như người xưa vẫn nói, bạn có thể viết FORTRAN bằng bất kỳ ngôn ngữ nào . Dependency Injection không phải là một viên đạn bạc mà sẽ ngăn chặn các nhà phát triển từ Screwing lên quản lý phụ thuộc của họ, nhưng nó không ngăn chặn một số lỗi phổ biến / chống mẫu:
...và như thế.
Rõ ràng là bạn không muốn thiết kế một khung để phụ thuộc vào việc triển khai bộ chứa IoC cụ thể , như Unity hoặc AutoFac. Đó là, một lần nữa, vi phạm DIP. Nhưng nếu bạn thấy mình thậm chí nghĩ về việc làm một cái gì đó như vậy, thì bạn chắc chắn đã mắc một số lỗi thiết kế, bởi vì Dependency Injection là một kỹ thuật quản lý phụ thuộc mục đích chung và không gắn liền với khái niệm về bộ chứa IoC.
Bất cứ điều gì có thể xây dựng một cây phụ thuộc; có thể đó là một container IoC, có thể đó là một thử nghiệm đơn vị với một loạt các giả, có thể đó là một trình điều khiển thử nghiệm cung cấp dữ liệu giả. Khung của bạn không nên quan tâm và hầu hết các khung tôi từng thấy không quan tâm, nhưng họ vẫn sử dụng rất nhiều phép tiêm phụ thuộc để có thể dễ dàng tích hợp vào bộ chứa IoC của người dùng cuối.
DI không phải là khoa học tên lửa. Chỉ cần cố gắng tránh new
và static
ngoại trừ khi có lý do thuyết phục để sử dụng chúng, chẳng hạn như phương thức tiện ích không có phụ thuộc bên ngoài hoặc lớp tiện ích không thể có bất kỳ mục đích nào ngoài khung (trình bao bọc xen kẽ và khóa từ điển là những ví dụ phổ biến về điều này).
Nhiều vấn đề với khung IoC xuất hiện khi các nhà phát triển lần đầu tiên học cách sử dụng chúng và thay vì thực sự thay đổi cách họ xử lý các phụ thuộc và trừu tượng để phù hợp với mô hình IoC, thay vào đó, hãy cố gắng điều khiển bộ chứa IoC để đáp ứng mong đợi của họ phong cách mã hóa cũ, thường sẽ liên quan đến khớp nối cao và độ gắn kết thấp. Mã xấu là mã xấu, cho dù nó sử dụng các kỹ thuật DI hay không.