Là tiêm phụ thuộc bằng tay là một thay thế tốt hơn cho thành phần và đa hình?


13

Đầu tiên, tôi là một lập trình viên cấp mới; Trên thực tế, tôi đang hoàn thành bằng AS với dự án capstone cuối cùng vào mùa hè. Trong công việc mới của tôi, khi không có dự án nào để tôi thực hiện (họ đang chờ để lấp đầy đội ngũ với nhiều tuyển dụng mới), tôi đã được tặng sách để đọc và học hỏi trong khi tôi chờ đợi - một số sách giáo khoa, những cuốn khác không quá nhiều (như Code Complete). Sau khi xem qua những cuốn sách này, tôi đã chuyển sang internet để tìm hiểu càng nhiều càng tốt, và bắt đầu tìm hiểu về RẮN và DI (chúng tôi đã nói về một số nguyên tắc thay thế của Liskov, nhưng không nhiều ý tưởng RẮN khác). Vì vậy, như tôi đã học, tôi ngồi xuống để học tốt hơn và bắt đầu viết một số mã để sử dụng DI bằng tay (không có khung DI trên các máy tính phát triển).

Điều đó là, khi tôi làm điều đó, tôi nhận thấy nó cảm thấy quen thuộc ... và có vẻ như nó rất giống với công việc tôi đã làm trong quá khứ bằng cách sử dụng thành phần của các lớp trừu tượng sử dụng đa hình. Tôi có đang thiếu một bức tranh lớn hơn ở đây không? Có điều gì về DI (ít nhất là bằng tay) vượt xa điều đó không? Tôi hiểu khả năng có cấu hình không phải là mã của một số khung DI có một số lợi ích lớn khi thay đổi mọi thứ mà không phải biên dịch lại, nhưng khi thực hiện bằng tay, tôi không chắc liệu nó có khác gì so với đã nêu ở trên không ... Một số cái nhìn sâu sắc về điều này sẽ rất hữu ích!

Câu trả lời:


21

Ý tưởng cơ bản trong DI chỉ đơn giản là đẩy các phụ thuộc vào các đối tượng, thay vì để chúng kéo các phụ thuộc từ bên ngoài. Điều này cũng được gọi là "đảo ngược kiểm soát" trước đó. Điều này cho phép một người kiểm soát các phụ thuộc tốt hơn nhiều, và - cuối cùng nhưng không kém phần quan trọng - để viết mã dễ kiểm tra đơn vị.

Các khung DI chỉ được xây dựng dựa trên ý tưởng này và (một phần) tự động hóa phần thường tẻ nhạt của các phụ thuộc đối tượng nối dây với nhau. Điều này có thể yêu cầu một lượng mã đáng kể trong một dự án lớn hơn khi được thực hiện bằng tay.

Để xác định các phụ thuộc, ngoài các tệp cấu hình bên ngoài, ngày nay cũng có thể sử dụng các chú thích mã, ví dụ như trong các ngôn ngữ như Java và C #. Những điều này có thể mang lại điều tốt nhất của cả hai thế giới: phụ thuộc hệ thống dây theo kiểu khai báo, nhưng ngay trong chính mã, nơi nó thuộc về logic. Đối với tôi, khả năng thay đổi các phụ thuộc mà không cần phải biên dịch lại là không có giá trị, vì nó hiếm khi được thực hiện trong cuộc sống thực (ngoài một số trường hợp đặc biệt), nhưng đưa ra sự phân tách phụ thuộc thường xuyên từ các lớp và các đối tượng được xác định trong mã .

Để trở lại câu hỏi tiêu đề của bạn, DI không phải là một thay thế cho thành phần cũng như đa hình; sau khi tất cả, nó được thực hiện bởi hai.


1
Dependency Injection (DI) là một hình thức đảo ngược điều khiển (IoC).
Matthew Flynn

@MatthewFlynn, thực sự. Để tham khảo: martinfowler.com/articles/injection.html
Péter Török

1
Đó là tài liệu tham khảo của tôi. Anh ấy nói về "các thùng chứa nhẹ" mới thực hiện đảo ngược quyền kiểm soát, đó là điều đã từng phổ biến vì người nghe sự kiện UI là một dạng của IoC. Anh ta đặt tên cho đối tượng ràng buộc mà Spring và các container IoC khác thực hiện như Dependency Injection để phân biệt nó với hình thức Inversion of Control khác.
Matthew Flynn

Rất tiếc - Tôi đã bỏ lỡ "thực sự." Tôi nghĩ rằng bạn đang mâu thuẫn với tôi ... Xin lỗi.
Matthew Flynn

Đoạn cuối của bạn làm cho tôi cảm thấy tốt hơn một chút; toàn bộ thời gian tôi đang thực hiện dự án học tập nhỏ của mình, tôi cứ tự nhủ: "cảm giác này giống như đa hình ..". Thật không may, .Net và c # trong công việc của tôi đã hết hạn một cách khủng khiếp, nhưng từ khi nhìn vào nó, liệu Unity có được xây dựng trong khung c # mà bạn đang nói đến không?
Drake Clarris

22

Bài viết hay nhất tôi từng đọc về chủ đề này là của James Shore . Tôi đã làm " DI by Hand " từ lâu, như một phần của sự trừu tượng và đa hình. Vì vậy, sau khi tôi bước vào thế giới chuyên nghiệp và tôi nghe thấy thuật ngữ đó bị ném xung quanh, tôi có một sự mất kết nối lớn giữa những gì tôi nghĩ từ đó có nghĩa và ý nghĩa thực sự của nó:

"Dependency Injection" là một thuật ngữ 25 đô la cho khái niệm 5 xu.

Đó là từ bài viết của Shore, đã xóa tất cả mọi thứ cho tôi. Ví dụ:

Được

class Engine {public abstract void start()}
class V8 extends Engine {...}
class V6 extends Engine {...}

Thay vì viết:

class Car
{
    private Engine engine;
    public Car()
    {
        this.engine = new V6();
    }

    public void start()
    {
        this.engine.start();
    }
}

Bạn viết một cái gì đó như thế này:

class Car
{
    private Engine engine;
    public Car(Engine a)
    {
        this.engine = a;
    }

    public void start()
    {
        this.engine.start();
    }
}

...

Car F = new Car(new V8());

Và điều này ngăn cản Cartrường hợp phải xử lý các Enginechi tiết cụ thể . Một chiếc xe chỉ cần một động cơ, nó không quan tâm cái nào miễn là nó thực hiện chức năng Động cơ cơ bản. Đó là, Carlớp của bạn không bị ràng buộc với sự phụ thuộc thực hiện cụ thể; đó là "tiêm" ở nơi khác, có khả năng trong thời gian chạy.

Ví dụ về Xe cụ thể này sử dụng loại phụ của DI được gọi là "Con constructor Injection", điều này chỉ có nghĩa là sự phụ thuộc đã được bàn giao như một đối số của hàm tạo. Bạn cũng có thể sử dụng một setEngine(Engine a)phương pháp cho "Setter tiêm", v.v., nhưng những kiểu phụ này có vẻ mang tính mô phạm đối với tôi.

Tuy nhiên, xa hơn một chút, nhiều khung DI cung cấp bản tóm tắt để kết nối một loạt những thứ được tham chiếu trừu tượng hơn với nhau.

Đó là nó.


0

Tôi không phải là một chuyên gia vì tôi chỉ bắt đầu sử dụng DI trong vài năm qua, nhưng một vài trong số các chủ đề / chức năng hữu ích của các thùng chứa DI mà tôi nhận thấy là (mà tôi không nghĩ là sản phẩm của thành phần / đa hình (nhưng tôi có thể đứng để được sửa chữa về điều đó):

  • trung tâm của việc tạo đối tượng
  • cung cấp singletons trên cơ sở mỗi chủ đề
  • kỹ thuật định hướng khía cạnh như đánh chặn

0

Ngoài DI, còn có một cấu hình thành phần lớp tại ứng dụng gốc (thay vì cấu hình bằng xml). Không cần bất kỳ khung DI hoặc IoC nào, mặc dù chúng có thể thu gọn cấu hình thành phần lớp, đặc biệt đối với các dự án lớn. Điều này là do khung DI thường đi kèm với bộ chứa triển khai các tính năng bổ sung, như hệ thống dây tự động, giúp cấu hình thành phần lớp. Bạn có thể đọc mục blog của tôi để rút ra sự hiểu biết của tôi về chủ đề này.

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.