Phụ thuộc tiêm: Tại thời điểm nào tôi được phép tạo một đối tượng mới?


13

Tôi đang cấu trúc lại một ứng dụng PHP và tôi đang cố gắng thực hiện việc tiêm phụ thuộc (DI) nhiều nhất có thể.

Tôi cảm thấy như mình đã nắm bắt tốt cách thức hoạt động của nó, và tôi chắc chắn có thể thấy các lớp học của mình trở nên gọn gàng và mạnh mẽ hơn rất nhiều.

Tôi đang tái cấu trúc để tôi có thể thêm một phụ thuộc thay vì tạo một đối tượng mới trong lớp, nhưng đến một lúc nào đó tôi sẽ phải tạo một số đối tượng, nghĩa là sử dụng newtừ khóa đáng sợ .

Vấn đề bây giờ tôi gặp phải là tại thời điểm nào tôi thực sự có thể tạo ra các đối tượng mới? Trông giống như tôi sẽ kết thúc ở một lớp cấp cao nhất, tạo ra vô số đối tượng mới vì không còn nơi nào để đi. Điều này cảm thấy sai.

Tôi đã đọc một số blog sử dụng các lớp của nhà máy để tạo tất cả các đối tượng và sau đó bạn đưa nhà máy vào các lớp khác. Sau đó, bạn có thể gọi các phương thức xuất xưởng và nhà máy tạo đối tượng mới cho bạn.

Mối quan tâm của tôi khi làm điều này là bây giờ các lớp học tại nhà máy của tôi sẽ là newmiễn phí cho tất cả! Tôi đoán điều này có thể ổn vì chúng là các lớp xuất xưởng, nhưng có một số quy tắc cần tuân thủ khi sử dụng mẫu nhà máy và DI, hoặc tôi sẽ đi khỏi dấu hiệu ở đây?



Tôi đề nghị IoC cho các dịch vụ và chính sách. Đối với các lớp mô hình hoặc trình trợ giúp tôi chỉ cần sử dụng new. Tất nhiên, có một vài điểm nhập cảnh mà bạn cần gọi vào bộ chứa IoC, nhưng không nên có nhiều điểm. Thông thường, bạn định cấu hình IoC một lần và sau đó yêu cầu một lớp được giải quyết theo yêu cầu. Trong trường hợp MVC đó thường là bộ điều khiển.
CodeInChaos

Lớp cấp cao nhất mà bạn đề cập là một phần của Thành phần gốc. Nó là xa sai.
Tỷ lệ Facio

Câu trả lời:


12

Sau khi có một chút loay hoay về điều này, có vẻ như (như đã đề cập trong một nhận xét ở trên) lớp cấp cao nhất mà tôi đang nói đến được gọi là Thành phần gốc .

Nó thực sự có vẻ là giải pháp được chấp nhận để thêm việc tạo tất cả các đối tượng trong Thành phần gốc này (hoặc tham chiếu một bộ chứa IoC từ đây).

Mối quan tâm ban đầu của tôi với điều này là lớp cấp cao nhất này cuối cùng sẽ là một mớ hỗn độn. Điều này đúng ở một mức độ nào đó, nhưng ưu điểm là cân nhắc nhược điểm. Ví dụ, tôi có thể thấy khả năng đọc, khả năng kiểm tra và khả năng bảo trì của tất cả các lớp khác của tôi đã được cải thiện.

Lớp cấp cao nhất có thể hơi lộn xộn, rải rác newset_property()nhưng tôi phải nói rằng tôi thực sự thích có tất cả mã này ở một nơi, thay vì nằm rải rác trên tất cả các lớp khác

Một trang hữu ích khác thảo luận về hiệu suất của phương pháp này tại đây


1
+1 vì tôi chưa bao giờ nghe về 'Thành phần gốc' trước đây.
c_maker

2

Một lớp Factory sẽ newrắc khắp nó. Nó sẽ tạo ra bất cứ đối tượng nào mà bạn yêu cầu và có thể là các phụ thuộc của đối tượng đó. Vì công việc của các nhà máy là khởi tạo đúng đối tượng cho bạn newtrong lớp này không phải là điều xấu.

DI là để bạn có một thiết kế lỏng lẻo. Bạn có thể thay đổi ứng dụng của mình bằng cách thay đổi sự phụ thuộc được cung cấp cho từng đối tượng. Làm cho ứng dụng của bạn linh hoạt, mở rộng và dễ kiểm tra.

Ở cấp độ cao nhất, bạn sẽ có mã sẽ khởi tạo một vài nhà máy, thiết lập kết nối với các dịch vụ và gửi phản hồi. Nó sẽ có một số lượng lớn các newcuộc gọi tĩnh hoặc để khởi tạo các đối tượng cần thiết cho ứng dụng của bạn. Đó sẽ là nơi thuộc về.


-2

Hai xu của tôi ở đây:

Tôi đang cấu trúc lại một ứng dụng php và tôi đang cố gắng thực hiện việc tiêm phụ thuộc nhiều nhất có thể

Bạn không nói nếu bạn đang sử dụng khung tiêm phụ thuộc. Tôi nghĩ bạn chắc chắn nên. Sử dụng thứ gì đó cung cấp cho bạn các tính năng bạn cần: /programming/9348376/guice-like-dependency-injection-frameworks-in-php .

Vấn đề bây giờ tôi gặp phải là tại thời điểm nào tôi thực sự có thể tạo ra các đối tượng mới? Trông giống như tôi sẽ kết thúc ở một lớp cấp cao nhất, tạo ra vô số đối tượng mới vì không còn nơi nào để đi. Điều này cảm thấy sai.

Bạn thường sử dụng cấu hình hoặc một điểm trung tâm để khởi tạo các đối tượng ban đầu tạo ứng dụng của bạn. Container sẽ tạo các đối tượng cho bạn.

Sau đó, bạn truy cập các đối tượng (dịch vụ, nhà cung cấp, bộ điều khiển ...) thông qua bộ chứa IoC. Nó sẽ minh bạch tạo một đối tượng cho bạn nếu cần hoặc cung cấp cho bạn một tham chiếu đến thể hiện hiện tại thích hợp.

Tất nhiên, bên trong việc triển khai các đối tượng cụ thể của bạn, bạn có thể khởi tạo các đối tượng khác mà bạn không cần DI (cấu trúc dữ liệu, loại tùy chỉnh, v.v.), nhưng đó là lập trình bình thường.

Tôi đã đọc một số blog sử dụng các lớp của nhà máy để tạo tất cả các đối tượng và sau đó bạn đưa nhà máy vào các lớp khác. Sau đó, bạn có thể gọi các phương thức xuất xưởng và nhà máy tạo đối tượng mới cho bạn.

Thông thường, bạn sử dụng Factory nếu bạn muốn khung IoC khởi tạo một số đối tượng IoC thông qua các nhà máy của bạn (điều này là cần thiết khi khởi tạo một đối tượng cụ thể đòi hỏi một số công việc phụ). Nếu bạn chỉ có thể tạo các đối tượng của mình bằng "Object mới ()" và đặt một số thuộc tính, bạn không nhất thiết muốn sử dụng mẫu Factory.

Nói cách khác, tôi muốn nói rằng việc sử dụng mẫu Factory cho một lớp hoặc nhóm lớp phụ thuộc vào cách bạn muốn mô hình hóa các lớp đó, chứ không phụ thuộc vào việc bạn có sử dụng DI hay không (trừ khi việc triển khai DI của bạn yêu cầu rõ ràng các nhà máy, điều này không bình thường).

Bạn cũng định cấu hình khung IoC của mình để sử dụng Factory khi bạn đang sử dụng lib của bên thứ 3 đã yêu cầu sử dụng Factory. Trong trường hợp này, bạn không kiểm soát được vấn đề này và bạn cần nói với bộ chứa IoC của mình: "này, khi tôi yêu cầu một trong những giao diện này, bạn phải sử dụng nhà máy này để cung cấp cho tôi một ví dụ thích hợp".

Mối quan tâm của tôi với việc này bây giờ là các lớp học tại nhà máy của tôi sẽ trở thành một thứ miễn phí mới! Tôi đoán điều này có thể ổn vì chúng là các lớp của nhà máy, nhưng có một số quy tắc cần tuân thủ khi sử dụng mô hình nhà máy và DI, hoặc tôi sẽ đi khỏi dấu hiệu ở đây.

Trong trường hợp này, có vẻ như bạn không cần sử dụng các mẫu Factory cho các đối tượng / dịch vụ / bộ điều khiển / bất cứ thứ gì và bạn chỉ cần cấu hình IoC của mình để khởi tạo lớp "mới" phù hợp và tiêm mọi thứ khác.

Tôi hy vọng nó sẽ giúp.


cảm ơn vì đã trả lời, nhưng chắc chắn container IoC là 'lớp cấp cao nhất' mà tôi đã đề cập. Nếu tôi chỉ có thể tạo các đối tượng trong đó, nó sẽ là một mớ hỗn độn.
Gaz_Edge

4
doing DI manually beats the whole purpose of using an Inversion of Control container- Nếu bạn có nghĩa là "... đang tập trung các phụ thuộc của bạn vào một tệp cấu hình" thì bạn đã đúng, bởi vì đó thực sự là một bộ chứa IoC. Mục tiêu thực sự của DI là tách rời và bạn có thể làm điều đó bằng cách cung cấp các phụ thuộc của bạn trong một phương thức xây dựng. Bạn hoàn toàn không cần một khung DI để làm điều đó.
Robert Harvey

mmm bạn không tạo đối tượng, bạn yêu cầu bộ chứa IoC cho chúng (từ bất cứ nơi nào bạn cần) hoặc bạn sử dụng phép tiêm trường / đối số để các lớp của bạn được tự động chèn các lớp thích hợp, luôn được tạo bởi bộ chứa IoC.
jjmontes

1
Tôi đồng ý rằng bạn cần một khung cho các ứng dụng rất lớn . Nhiều ứng dụng không lớn và không được hưởng lợi từ sự phức tạp bổ sung của việc sử dụng khung DI.
Robert Harvey

2
Tôi đã không nói rằng đó là. Tôi chỉ đơn giản nói rằng bạn không cần một container DI để làm điều đó.
Robert Harvey
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.