Những lợi ích của việc sử dụng Dependency Injection và IoC Container là gì?


62

Tôi đang lên kế hoạch để nói chuyện về Dependency Injection và IoC Container, và tôi đang tìm kiếm một số đối số tốt để sử dụng nó.

Những lợi ích quan trọng nhất của việc sử dụng kỹ thuật này và các công cụ này là gì?


1
Xem ở đâyở đây để biết câu trả lời của StackOverflow và ở đây để có một bài viết đầy đủ về IoC. Và nếu bạn muốn tranh luận chống lại nó để so sánh, hãy vào đây trên SO.
Jesse C. Choper

14
không phải là một cái mông ... nhưng nếu bạn không biết tại sao nên sử dụng DI / IOC, tại sao bạn lại nói về nó? thua cược? ;-)
Steven A. Lowe

2
@Steven, ông chủ của anh ta có thể đã yêu cầu anh ta làm điều đó.

1
@Steven, tôi đã sử dụng DI mọi lúc (một số người sẽ nói quá thường xuyên :-D), tôi chỉ tìm kiếm một số đối số tốt để khiến người khác sử dụng nó.
Andy Lowry

2
Mọi người hiếm khi nói về việc lạm dụng DI. Nếu bạn trì hoãn mọi quyết định, bạn sẽ tạo mã OO tương đương với mã spaghetti. Có một thiết kế mạch lạc đòi hỏi rằng, tại một số điểm, một quyết định thực sự được đưa ra.
Macneil

Câu trả lời:


47

Quan trọng nhất, đối với tôi, là làm cho nó dễ dàng tuân theo Nguyên tắc Trách nhiệm duy nhất .

DI / IoC giúp tôi dễ dàng quản lý các phụ thuộc giữa các đối tượng. Đổi lại, điều đó giúp tôi dễ dàng phá vỡ chức năng kết hợp thành hợp đồng (giao diện) của chính nó. Do đó, mã của tôi đã được mô đun hóa nhiều hơn kể từ khi tôi biết về DI / IoC.

Một kết quả khác của điều này là tôi có thể dễ dàng nhìn thấy đường đến một thiết kế hỗ trợ Nguyên tắc Đóng mở . Đây là một trong những kỹ thuật truyền cảm hứng tự tin nhất (chỉ đứng sau thử nghiệm tự động). Tôi nghi ngờ tôi có thể tán thành những đức tính của Nguyên tắc Đóng mở đủ.

DI / IoC là một trong số ít những thứ trong sự nghiệp lập trình của tôi là "người thay đổi cuộc chơi". Có một khoảng cách lớn về chất lượng giữa mã tôi đã viết trước và sau khi học DI / IoC. Hãy để tôi nhấn mạnh rằng một số chi tiết. HUGE cải thiện chất lượng mã.


3
Tại sao Nguyên tắc đóng mở lại là một vấn đề lớn như vậy? Nếu bạn cảm thấy cần thay đổi API / giao diện, tại sao bạn không nên?
Arne Evertsson

@ArneEiftsson Nghe Robert C. Martin nói về Nguyên tắc Đóng mở. Bạn sẽ được giác ngộ.
Alternatex

@AmeEiftsson Mở-Đóng rất quan trọng khi mã của bạn được cung cấp (ví dụ như một sản phẩm thương mại) dưới dạng mô-đun để người khác sử dụng, vì nó giúp mã của bạn dễ sử dụng hơn mà không cần họ quay lại để thay đổi mã
James Ellis-Jones

2
DI không làm cho nó đơn giản để quản lý các phụ thuộc vì nó phức tạp hơn đáng kể so với việc tạo ra một phụ thuộc vào một lớp cụ thể. Tuy nhiên, nó cung cấp tính linh hoạt nhưng trừ khi bạn đang thực hiện kiểm tra đơn vị 'phù hợp', tính linh hoạt đó thường sẽ không cần thiết. Cả hai ưu điểm chính được mô tả cũng áp dụng cho Trình định vị dịch vụ, đơn giản hơn.
James Ellis-Jones

1
Tôi đã đánh giá thấp câu trả lời này nhiều năm trước; Dưới đây là một số lưu ý: 1) Trong thực tế, việc sử dụng DI rộng rãi có xu hướng hoạt động chống lại SRP, bởi vì các lập trình viên chỉ cần tiếp tục thêm các phương thức vào "bộ điều khiển", "dịch vụ", "DAO", v.v., thay vì tạo các lớp mới cho chức năng mới. Đó là những gì bạn thường thấy xảy ra trong các dự án Java và C # .NET sử dụng một số khung hoặc khung chứa DI. 2) Nguyên tắc đóng mở chỉ là ảo tưởng của Bertrand Meyer về tính hữu dụng của kế thừa lớp (thực hiện); nếu bạn tìm kiếm nó trong cuốn sách hơn 1400 trang của anh ấy, bạn sẽ thấy những gì tôi muốn nói - nó thực sự ngớ ngẩn.
Rogério

9

Các ví dụ thực sự mở mắt tôi đang thấy cách nó có thể dễ dàng kiểm tra các vật thể được tạo ra theo kiểu như vậy. Trước đó, tôi đã gặp khó khăn khi cố gắng cách ly các đối tượng để kiểm tra đơn vị. Tôi thường viết các bài kiểm tra để tương tác với một hệ thống lớn hơn nhiều. Điều này thực sự khó khăn vì toàn bộ hệ thống ít dự đoán hơn và dễ thay đổi hơn các thành phần riêng lẻ.


3

Ưu điểm của tiêm phụ thuộc là:

  1. Mã của bạn sạch sẽ và dễ đọc hơn.
  2. Các mã được ghép lỏng lẻo.
  3. Có thể tái sử dụng nhiều hơn khi các triển khai được cấu hình trong tệp XML, nó có thể được sử dụng trong một ngữ cảnh khác.
  4. Mã có thể dễ dàng kiểm tra với việc thực hiện giả khác nhau.

1

Tôi nghĩ rằng lợi ích thực tế là chính trị nhiều hơn là kỹ thuật. DI chỉ đơn giản là một thay thế cho mẫu Định vị dịch vụ , không có gì hơn. Chính nó, nó không làm cho việc tuân theo các nguyên tắc như SRP hoặc OCP trở nên dễ dàng hơn hoặc tách lớp. Những người trả lời khác ở đây đang nhầm lẫn các khái niệm và kỹ thuật khác nhau, IMO.

Bạn có thể đạt được các mục tiêu tương tự liên quan đến độ gắn kết cao và khớp nối thấp bằng cách sử dụng Bộ định vị dịch vụ hoặc chỉ đơn giản là khởi tạo trực tiếp các phụ thuộc bất cứ khi nào có thể áp dụng (hầu hết thời gian).

Bây giờ, tôi biết nhiều người sẽ không đồng ý với ý kiến ​​này. Tôi sẽ vui mừng thảo luận về các ví dụ cụ thể.


2
Nhưng trực tiếp gọi một bộ định vị dịch vụ hoặc khởi tạo một phụ thuộc cụ thể thường làm khó các phụ thuộc của bạn, hoặc ít nhất là nơi các phụ thuộc của bạn đến từ đâu. Điều đó dường như đánh bại mục đích của DI. Bạn vẫn phải tiêm định vị dịch vụ, quá.
Matt H

Việc sử dụng Trình định vị dịch vụ không làm khó bất cứ điều gì ngoại trừ việc sử dụng chính Trình định vị dịch vụ, thường không được "tiêm". Khởi tạo một lớp triển khai cụ thể là hoàn toàn tốt trong trường hợp bạn không cần cấu hình bên ngoài (ví dụ, các lập trình viên thường khởi tạo trực tiếp lớp ArrayList thay vì sử dụng DI - sẽ quá mức cần thiết).
Rogério

1
Bạn đề cập đến "khớp nối thấp" và sau đó bạn nói rằng bộ định vị dịch vụ không có tác động đến mức độ khớp nối của ứng dụng. Tương tự như vậy để khởi tạo các cộng tác viên trực tiếp trên mã, tôi không thể nghĩ ra một cách hoàn hảo hơn để ghép một đối tượng với các phụ thuộc của nó. Làm thế nào để bạn kiểm tra đơn vị cả hai kịch bản? Tôi, tôn trọng, hoàn toàn không đồng ý với tất cả những gì bạn nói.
Clint Eastwood

@Jonathan Bạn nên đọc bài viết giới thiệu DI rồi; tác giả kết luận bằng cách nói DI và ServiceLocator là "gần tương đương", với "cạnh nhẹ" cho cái sau. Sự kết hợp quan trọng là giữa một thành phần và các thành phần khác có thể có nhiều triển khai; ServiceLocator là một dịch vụ cơ sở hạ tầng chỉ có một triển khai, vì vậy nó ổn. Lưu ý tôi đã viết "khởi tạo phụ thuộc bất cứ khi nào có thể áp dụng "; Tất nhiên, nếu bạn cần tách cấu hình khỏi sử dụng, bạn sẽ không làm điều đó.
Rogério

1
@Jonathan Về thử nghiệm đơn vị, thật hoang đường khi các cộng tác viên bắt đầu ngăn chặn việc tạo ra các thử nghiệm như vậy; có những công cụ nhạo báng nổi tiếng thực hiện công việc cách ly một lớp khỏi việc triển khai phụ thuộc, cho dù chúng có được tiêm hay không.
Rogério

-1

Khi DI được sử dụng để phơi bày các đối tượng bên trong cho mục đích thử nghiệm, mẫu đã bị lạm dụng.


1
bạn có ý nghĩa gì bởi "các đối tượng bên trong"?. trong OOP thực (lưu ý rằng có lẽ chỉ 1% lập trình viên biết điều đó thực sự có nghĩa là gì), có những đối tượng giao tiếp với nhau bằng cách gửi tin nhắn (tức là gọi phương thức). Theo nghĩa đó, mỗi đối tượng phải có một trách nhiệm duy nhất, không có các đối tượng "quan trọng" hơn các đối tượng khác ... mỗi đối tượng đều có một nhiệm vụ duy nhất và họ hợp tác để đạt được chức năng do toàn hệ thống cung cấp. Điều quan trọng là kiểm tra mọi đối tượng theo cách cô lập để chúng tôi biết rằng chúng tôi đã không bỏ lỡ bất kỳ trường hợp nào, đó là điều DI thực sự giỏi.
Clint Eastwood

Tôi quên mất rồi.
thomas-peter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.