Khi nào nên sử dụng DI và khi nào nên tự tạo trong Java


8

Tôi đã có một lượng OOP kha khá với nhiều ngôn ngữ khác nhau nhưng còn khá mới đối với Java.

Tôi đang đọc qua rất nhiều hướng dẫn trong đó số lượng lớn các đối tượng được tạo trong mã của một lớp và tôi đang cố gắng chạy qua chúng nhưng xây dựng các phiên bản của các lớp trong các hướng dẫn thực hiện Dependency Injection thay vì khởi tạo tất cả lớp mình.

Nhưng Java không giống như các ngôn ngữ khác mà tôi đã sử dụng trong đó khá nhiều thứ là một đối tượng. Nếu tôi thực sự tiêm tất cả mọi thứ thì kết quả sẽ rất lộn xộn và khó theo dõi.

Rõ ràng là bạn sẽ không tiêm các đối tượng String và tôi đoán có những đối tượng khác bạn sẽ không tiêm, nhưng tôi không chắc chắn đường kẻ sẽ đi đâu. Tại thời điểm nào thì DI dừng lại là điều đúng đắn và khi nào nó bắt đầu trở thành gánh nặng? Làm thế nào để bạn quyết định thực tế những gì để tiêm và những gì chỉ cần khởi tạo?

FYI, các hướng dẫn tôi đang làm là http://edn.embarcadero.com/article/31995http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html để xây dựng một ứng dụng khách đơn giản và người phục vụ. Mặc dù vậy, tôi không sao chép dòng cho dòng, tôi đang cố gắng tạo các lớp tương đương theo thông lệ tốt nhất


1
Câu hỏi này không phải là Java, nhưng nói về các cách để 'tiêm mọi thứ' theo những cách ít lộn xộn hơn: lập trình
viên.stackexchange.com / questions / 190120 / Lỗi

Câu trả lời:


4

Trong .Net (tương tự về vấn đề này, mọi thứ đều là đối tượng), tôi sử dụng DI chủ yếu với các đối tượng miền (thực thể, kho lưu trữ và dịch vụ) và các đối tượng ứng dụng (bộ điều khiển, mô hình xem), vì vậy repos / dịch vụ được đưa vào bộ điều khiển / xem mô hình và tương tự. Điều này có nghĩa là logic kinh doanh và ứng dụng của tôi hoàn toàn có thể kiểm tra được, đó là lý do chính khiến tôi sử dụng DI.

Về cơ bản các đối tượng mà bạn tiêm và tiêm vào, hầu hết là các đối tượng dành riêng cho giải pháp bạn đang xây dựng. Nếu một số đối tượng là "bản địa" đối với ngôn ngữ hoặc khung (như .Net), có lẽ không cần phải tiêm nó. Rất nhiều đối tượng cần chuỗi để thể hiện dữ liệu và về cơ bản, một chuỗi là "tính năng ngôn ngữ" không dành riêng cho miền của bạn. Điều tương tự cũng áp dụng cho liệt kê, danh sách, mảng và rất nhiều thứ khác không cần thay đổi khi bạn muốn chạy lớp riêng biệt với phần còn lại của hệ thống.

Điều quan trọng nhất để xem xét là khớp nối giữa các lớp miền / ứng dụng của bạn. Nếu một đối tượng không giới thiệu khớp nối chặt chẽ, thì việc tạo ra nó thường an toàn. Một trong những cách để kiểm tra khớp nối là thử chạy các phương thức trong một lớp riêng lẻ (về cơ bản là kiểm thử đơn vị). Những gì cần phải là DI-ed là tất cả các phụ thuộc mà bạn cần phải giả định, để đảm bảo rằng lớp bạn đang kiểm tra thực sự chạy tách biệt với hệ thống.


Một cách khác để xem xét nó là lớp học hoặc phương pháp của bạn đang cố gắng làm gì? Ví dụ kinh điển là bạn muốn lưu một đối tượng. Logic trong lớp / phương thức đó phải là về việc lưu đối tượng, không tắt và thực hiện công việc tạo tấm kết nối, v.v., loại dịch vụ / tài nguyên đó có thể / nên được đưa vào.
Martijn Verburg

4

Đầu tiên, thật tốt khi sử dụng từ khóa mới! DI là một kỹ thuật tuyệt vời, nhưng có một sự cám dỗ để lạm dụng nó. Thời gian mà bạn có thể muốn sử dụng DI là:

  • Kiểm tra nhân đôi - Thông thường với các bài kiểm tra đơn vị bạn muốn mô phỏng / kiểm tra nhân đôi tài nguyên của bên thứ 3 vì bạn không muốn đưa tài nguyên của bên thứ 3 đó lên (ví dụ: Oracle DB đầy đủ). Ví dụ, thay vì tạo kết nối cơ sở dữ liệu mới với Oracle DB lớn, bạn có thể muốn thay thế kết nối đó bằng một kết nối thành HSQL (trong cơ sở dữ liệu bộ nhớ).

  • Khi bạn muốn kiểm soát phạm vi (~ tuổi thọ) của đối tượng đó và vòng đời đối tượng Java tự nhiên không hoạt động cho bạn. Nhiều khung công tác DI dựa trên Java cho phép bạn làm điều này.

  • Khi bạn muốn singletons.

  • Bất cứ lúc nào bạn nghĩ rằng bạn cần một Nhà máy, Bộ định vị dịch vụ hoặc tương tự. Điều này bao gồm nếu bạn cần các nhà máy khác nhau (hiếm, nhưng nó xảy ra).

Vào những lúc khác, chỉ cần tạo một đối tượng mới, trong thực tế, nếu nghi ngờ, hãy tạo một đối tượng mới - bạn luôn có thể DI nó khi bạn thấy nhu cầu sau :-).


Điểm đầu tiên của bạn có nghĩa là hoàn toàn bất cứ điều gì, vì vậy tôi không chắc bạn đã trả lời câu hỏi như thế nào. Và tôi đã thấy nhiều nơi sử dụng DI để tiêm Nhà máy, thay vì cố gắng xây dựng Nhà máy thông qua DI, cho đến nay là giải pháp tốt hơn, vì vậy tôi cũng nghi ngờ về điểm cuối cùng.
pdr

Chỉnh sửa để làm cho các điểm rõ ràng hơn một chút
Martijn Verburg

Tôi chưa bao giờ nghe cụm từ Kiểm tra nhân đôi, tôi nghĩ bạn có nghĩa là kiểm tra docs.oracle.com/javase/6/docs/api/java/lang/Double.html .
NimChimpsky

1
@NimChimpsky một bài kiểm tra kép là một thuật ngữ chung cho bất kỳ giả, sơ khai hoặc dự phòng khác. xunitpatterns.com/Test%20Double.html

0

Từ Wikipedia :

Mục đích chính của mẫu tiêm phụ thuộc là cho phép lựa chọn trong số nhiều triển khai của giao diện phụ thuộc nhất định trong thời gian chạy hoặc thông qua các tệp cấu hình, thay vì tại thời gian biên dịch. Mẫu này đặc biệt hữu ích để cung cấp các triển khai thử nghiệm còn sơ khai của các thành phần phức tạp khi thử nghiệm, nhưng thường được sử dụng để định vị các thành phần plugin hoặc định vị và khởi tạo

Bạn không cần phải tiêm chuỗi, bạn chỉ cần truyền chúng dưới dạng tham số cho phương thức có liên quan. Bạn không cần phải tiêm bất kỳ dữ liệu nào, appart từ config.

Kiểm tra đơn vị tốt giúp bạn bản địa hóa các lỗi và do đó bạn nên kiểm tra mã của mình một cách độc lập với các đơn vị mã khác. DI có thể giúp bạn đạt được điều này.


0

Nói chung, tôi thấy một lớp chỉ nên là newtừ một lớp khác.

Điều này là do một khi bạn đi vào con đường tiêm phụ thuộc, mọi đối tượng đang sử dụng newphải tiêm tất cả các phụ thuộc của các đối tượng mà nó tạo ra, điều đó có nghĩa là đối tượng cha mẹ cũng phải biết tất cả các phụ thuộc đó. Nếu Acó một sự phụ thuộc BCtạo ra các Athể hiện newthì Ctự động cần phải có một sự phụ thuộc vào B, ngay cả khi Ckhông bao giờ sử dụng Btrực tiếp. Đầu tiên, vi phạm sự phân tách các mối quan tâm, trừ khi Ccông việc duy nhất là tạo As. Mặt khác, nó tạo ra một vấn đề nếu bạn muốn thêm một phụ thuộc vào Avì tất cả những thứ tạo ra nó bây giờ cần phải thêm phụ thuộc đó. Họ thực sự không nên quan tâm đến điều đó. Tốt hơn là cóCtuyên bố một phụ thuộc vào AFactoryAFactorycó một phụ thuộc vào B. Sau đó, bạn có thể thêm phụ thuộc vào Atất cả những gì bạn muốn và chỉ AFactoryphải thay đổi.


-1

"Tại thời điểm nào DI dừng lại là điều đúng đắn phải làm, và khi nào nó bắt đầu trở thành gánh nặng? ..."

Trước hết tôi thích DI và sử dụng nó rất nhiều vì vậy đừng hiểu lầm tôi

DI rất tốt cho phía máy chủ nhưng các trò chơi thay đổi tất cả cùng nhau khi nói đến lập trình Gui. Ví dụ: tôi đã kết hợp Guice với một ứng dụng GUI hiện có được phát triển trong Swing

  • Bạn cần tái cấu trúc rất nhiều để loại bỏ những thứ như các nhà máy tĩnh, phụ thuộc lồng nhau, v.v.
  • Bạn cần lưu ý về cách DI container tạo / xử lý các đối tượng, ví dụ như nếu nó tạo ra các đối tượng háo hức khi khởi động thì bạn có thể gặp vấn đề về hiệu năng (có thể là bất kỳ ứng dụng nào, đặc biệt là trong các ứng dụng GUI có độ trễ 15-40 giây). Bạn có thể làm mờ cài đặt cung cấp DI container cho phép nó.
  • Để kết hợp DI vào một dự án hiện có, bạn cần một cuộc cách mạng hơn là tiến hóa

Làm thế nào để xử lý các phụ thuộc lồng nhau?

giả sử bạn cần truy cập một số phụ thuộc trong lớp học được lồng sâu , bạn có thể sử dụng DI theo một trong các cách sau:

  • Sửa đổi hàm tạo để có hàm tạo của hàm tạo (Vì vậy, chúng ta biết kết thúc với hàm tạo có nhiều tham số ...)?
  • Sử dụng tiêm trường (Đây không phải là giải pháp tốt vì chúng tôi đang phơi bày các lĩnh vực của mình)
  • Sử dụng phương thức tiêm setter (Vì vậy, chúng ta cần tạo các setters không cần thiết trong mã của mình)

Sẽ thế nào nếu bạn muốn tạo đối tượng bằng new () (vì đối tượng cần được tạo tại Runtime tùy thuộc vào một số tiêu chí) và muốn đăng ký nó vào container (Guice không xử lý các đối tượng được tạo bằng new (), đó là tốt chứ? Vì vậy, bây giờ bạn cần chuyển sự tập trung của bạn trở lại vào container hơn là phát triển các chức năng mới trong ứng dụng của bạn.

Những từ cuối cùng trong một số trường hợp sử dụng DesignPotypes + tư duy sáng tạo và thiết kế kiến ​​trúc tốt, bạn có thể tránh được tình trạng bão hòa trong đó gaine nhỏ và rắc rối là kết quả của việc giới thiệu DI

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.