Tại sao chúng ta cần khuôn khổ cho tiêm phụ thuộc? [đóng cửa]


42

Tôi đã đọc nhiều hơn về nguyên tắc Đảo ngược điều khiển và Tiêm phụ thuộc khi thực hiện nó và tôi khá chắc chắn rằng tôi hiểu nó.

Về cơ bản, có vẻ như là 'không khai báo các thành viên trong lớp của bạn' trong lớp '. Thay vào đó, các cảnh báo nên được truyền vào và được chỉ định thông qua hàm tạo; 'tiêm' vào lớp từ nguồn bên ngoài.

Nếu nó đơn giản, có vẻ như vậy, tại sao chúng ta cần các khung như mùa xuân hoặc guice thực hiện điều này với các chú thích? Tôi có thiếu một cái gì đó cơ bản ở đây? Tôi thực sự đấu tranh để hiểu việc sử dụng các khung Dependency Injection là gì.

Chỉnh sửa: Về bản sao có thể có, tôi tin rằng câu hỏi của tôi độc đáo hơn vì nó đang hỏi về các khung DI nói chung, không chỉ riêng Spring. Spring không chỉ là một khung DI, vì vậy có nhiều lý do mà ai đó muốn sử dụng Spring không liên quan đến DI.



11
Chúng rất hữu ích để chuyển lỗi vào thời gian chạy thay vì thời gian biên dịch.
Den

1
@den Tại sao chúng ta muốn làm điều đó? Điều đó dường như vi phạm thất bại nhanh chóng
NGƯỜI DÙNG NÀY CẦN GIÚP

Câu trả lời:


26

Chúng ta không cần các khuôn khổ. Hoàn toàn có thể thực hiện tiêm phụ thuộc bằng tay, ngay cả đối với một dự án tương đối lớn.

Mặt khác, sử dụng khung làm cho nó dễ dàng hơn, đặc biệt là dựa trên chú thích hoặc tự động phát hiện các phụ thuộc, vì nó làm cho quy trình đơn giản hơn: nếu tôi quyết định rằng tôi cần một phụ thuộc mới trong một lớp, tất cả những gì tôi phải làm là thêm nó cho hàm tạo (hoặc khai báo một setter) và đối tượng được thêm vào - Tôi không cần thay đổi bất kỳ mã khởi tạo nào.

Ngoài ra, các khung thường chứa các chức năng hữu ích khác. Ví dụ, Spring chứa một khung hữu ích để lập trình hướng theo khía cạnh, bao gồm phân định giao dịch khai báo (cực kỳ tiện dụng) và một loạt các triển khai bộ điều hợp giúp nhiều thư viện bên thứ 3 dễ tích hợp hơn.


8
Nhấn đinh trên đầu. Chúng tôi không cần chúng. Họ chỉ làm cho cuộc sống dễ dàng hơn cho các dự án lớn. Thành thật mà nói, tôi thấy rằng các khung công tác rắc rối hơn giá trị của chúng cho các dự án nhỏ hơn. Tôi khuyến khích OP không nhầm lẫn giữa Dependency Injection với các khung hỗ trợ nó.
RubberDuck

1
nói hay lắm. Và tại sao phải phát minh lại bánh xe khi người khác đã làm cho nó trở nên đẹp và tròn?
jwenting

Chính xác đó. Ngoại trừ tôi không cần thay đổi bất kỳ mã khởi tạo nào - tất nhiên, không có mã khởi tạo ;-)
Mathieu Guindon

Nó chỉ trông giống như các thư viện DI của bạn hút. Những người giỏi có thể đoán lớp để khởi tạo bằng phản xạ.
Florian Margaine

2
Bất cứ ai sử dụng sự phản chiếu để xử lý thời gian chạy đều làm sai. Phản xạ là một trong những công nghệ đó, chỉ vì bạn có thể làm điều gì đó không có nghĩa là bạn nên làm.
gbjbaanb

12
  1. Tại sao chúng ta cần DI (Dependency Injection) cả?

    Cơ chế DI tách sản xuất đối tượng khỏi tiêu thụ đối tượng. Các phụ thuộc mà một đối tượng cần được phân phối trong suốt từ bên ngoài. Ưu điểm của cơ chế là rõ ràng: Bạn có thể trao đổi phụ thuộc bất cứ lúc nào, ví dụ: sử dụng Đối tượng Null cho mục đích thử nghiệm.

  2. Làm thế nào được thực hiện?

    Có một số cách để đạt được mục tiêu:

    • Tiêm phụ thuộc thông qua tiêm xây dựng
    • Tiêm qua getter / setter
    • Giao diện tiêm
  3. Chúng ta có cần khung DI không?

    Không hoàn toàn không. Bạn chỉ có thể chuyển tất cả các trường hợp cho các đối tượng khác bằng tay. Nếu bạn có một ứng dụng nhỏ, không cần hộp đựng lò xo.

    Nhưng mặt khác, các khung công tác giúp bạn quản lý các đối tượng:

    • Họ giúp bạn kết nối các mối quan hệ đối tượng phức tạp. Bạn phải viết không có mã soạn sẵn, để tạo các thể hiện và chuyển chúng đến các đối tượng thích hợp

    • Chúng giúp bạn kiểm soát khi một đối tượng được tạo: bạn có thể tạo các cá thể trong khi bootstrapping ứng dụng, nhưng trong một số trường hợp, việc tạo lười biếng - chỉ khi cần - là tốt hơn

    • Chúng giúp bạn kiểm soát số lượng phiên bản được tạo: một phiên bản cho mỗi vòng đời ứng dụng hoặc một trường hợp cho mỗi yêu cầu (trong trường hợp bạn đang lập trình web)

Nếu dự án của bạn có kích thước phù hợp - nếu bạn cảm thấy cần phải viết mã soạn sẵn ít hơn - hoàn toàn có ý nghĩa khi sử dụng khung (DI-). Có nhiều ưu điểm hơn khuyết điểm.


2
Bạn có thể sử dụng các thư viện DI mà không cần sử dụng một khung công tác nào cả.
Florian Margaine

5

Với mùa xuân, chủ yếu là vấn đề thuận tiện.

Nếu bạn có lớp TopLevelxây dựng lớp MiddleLevelxây dựng lớp LowLevelvà bạn nhận ra rằng bạn cần một tham số hàm tạo mới LowLevel, bạn cũng phải thêm nó vào TopLevelMiddleLevelđơn giản là khi MiddleLevelđến lúc xây dựng LowLevelgiá trị sẽ có sẵn để nó có thể được chuyển đến hàm tạo của nó. Với mùa xuân, bạn chỉ cần thêm một chú thích.

Ngoài ra, với lò xo, có thể xác định các phụ thuộc trong tệp cấu hình bên ngoài thay vì xml và điều này được cho là cung cấp cho bạn khả năng tạo một hệ thống mới với hệ thống dây hoàn toàn khác "không thay đổi bất kỳ mã nào". (IMHO điều này hoàn toàn sai hướng, bởi vì thay đổi xml không khác nhiều so với thay đổi mã và thực tế, mã thường có kiểm tra lỗi và kiểm tra loại tốt hơn nhiều so với xml.)

Một điều nữa là nhiều người sợ các nhà xây dựng; họ không hiểu họ, họ không thích họ, họ không muốn sử dụng chúng.


3
Chủ yếu là đồng ý, đặc biệt là với nhận xét XML. IMHO, sợ các nhà xây dựng có lẽ là một lý do tồi để sử dụng khung DI.
Robert Harvey

2
IMHO, sợ các nhà xây dựng là một lý do tốt để tránh xa lập trình. C -: =
Mike Nakis

5
Nhưng làm thế nào đây là một lợi thế so với một nhà máy (tĩnh hoặc khác)? (Có lợi thế là một tùy chọn bạn có thể sử dụng khi thích hợp trong khi mùa xuân dường như là tất cả hoặc không có gì xa lạ)
Richard Tingle

@RichardTingle Spring có thể đại diện cho một lợi thế chủ yếu nhờ vào tất cả những thứ khác ngoài DI, bởi vì rõ ràng, bạn có thể đạt được DI theo nhiều cách khác, các nhà máy tĩnh là một. . .
Mike Nakis

Đây là một ví dụ về những gì DI không. Không nên tạo MiddleLevel, nhưng không nên tạo nó , nhưng nên nhận nó khi xây dựng TopLevellàm đối số cho hàm tạo. Tương tự như vậy MiddleLevelsẽ nhận được một LowLeveltrong constructor của nó.
Rõ ràng

1

Vài năm trước tôi đã viết một chương trình để giám sát các trang web, portlets web, thậm chí một số bảng cơ sở dữ liệu nhất định, tại một công ty tôi từng làm việc. Tôi muốn nó đủ linh hoạt để người dùng có thể chỉ định màn hình nào sẽ chạy và với các tham số nào (url, đăng nhập, tiêu chí thành công, v.v.). Vì vậy, tôi đã viết nó để đọc từ một tệp XML và sử dụng phản chiếu Java để khởi tạo các lớp được chỉ định và sử dụng các phương thức setter để đặt các tham số đã chỉ định.

Sau đó tôi thấy rằng mùa xuân sẽ làm điều tương tự cho bạn, và nhiều hơn nữa.

Vì vậy, trong trường hợp của tôi, tôi thấy rằng

  1. Sử dụng khung tiêm phụ thuộc giúp chương trình linh hoạt và giúp dễ dàng xác định cách thức hoạt động của nó (trong các tham số được xác định rõ ràng trong khóa học).

  2. Sử dụng khung DI của bên thứ ba giúp bạn không phải phát minh lại bánh xe.


4
Bạn có thể giải thích thêm về lý do tại sao xác định lớp cụ thể nào sẽ sử dụng tốt hơn trong xml hơn là trong tệp java. Đó là điều tôi chưa bao giờ hiểu.
Richard Tingle

1
Đó không phải là viên đạn ma thuật, nhưng một lợi thế của việc sử dụng các tệp cấu hình là, ít nhất là về mặt lý thuyết, chúng dễ chỉnh sửa hơn mã. Ngoài ra, chúng có thể được thay đổi bởi người dùng đang chạy chương trình của bạn nhưng không có quyền truy cập vào mã nguồn của bạn. Trong ví dụ tôi đã đưa ra chương trình tiêm phụ thuộc thô của mình, đôi khi tôi sẽ thay đổi tệp cấu hình XML để tôi có thể thay đổi cách chương trình chạy mặc dù tôi là người đã viết nó. Nếu bạn không cần cấu hình bên ngoài, có thể dễ dàng hơn để làm điều đó với mã. Tôi đã có một công việc khác, nơi chúng tôi đã làm tất cả DI trong mã và nó hoạt động tốt.
Paul J Abernathy
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.