Việc sử dụng DI / IoC có nên loại bỏ tất cả các lần xuất hiện của từ khóa mới của Cameron không?


21

Việc sử dụng Dependency Injection và Inversion of Control container có nên loại bỏ tất cả các lần xuất hiện của newtừ khóa "" khỏi mã của bạn không?

Nói cách khác, mọi đối tượng / phụ thuộc, dù đơn giản hay ngắn ngủi, đều được "đăng ký" trong bộ chứa IoC của bạn và đưa vào phương thức / lớp cần sử dụng chúng?

Nếu không, bạn sẽ vẽ ranh giới giữa các phụ thuộc / đối tượng nào được đăng ký trong bộ chứa IoC, so với những gì được tạo "nội tuyến" làm tham chiếu cụ thể, thông qua newtừ khóa?


Tôi cũng có suy nghĩ tương tự, dọc theo dòng chữ "là" mới "một từ có 4 chữ cái?"
Michael Easter

Câu trả lời:


27

Tránh giáo điều. Làm những gì cảm thấy đúng.

Tôi thích sử dụng "mới" cho các cấu trúc dữ liệu không có hành vi.

Nếu lớp học có hành vi, thì tôi nhìn vào phạm vi của hành vi đó. Nếu nó không quốc tịch và không có sự phụ thuộc, tôi nghiêng về phía "mới". Tôi chỉ bắt đầu tái cấu trúc đối với DI khi tôi cần thêm một phụ thuộc vào các tài nguyên trạng thái (như cơ sở dữ liệu hoặc tệp) hoặc cho các lớp khác có tài nguyên đó.


15
+1 cho "tránh giáo điều". Cách quá dễ dàng để rơi vào cái bẫy chỉ theo dõi các chuyển động mà không hiểu những gì đang xảy ra hoặc nơi nó nên được sử dụng đúng cách.
Wayne Molina

@Alex Tôi thích cái này. Một cách tiếp cận rất thực dụng. Thật thú vị, tôi sẽ thêm một số mã trong câu hỏi của mình cho thấy sự newphụ thuộc 'ed trong mã của riêng tôi đã nhắc câu hỏi của tôi. Đó là một lớp đơn giản không có chức năng hoặc "hành vi" mỗi lần, chỉ có các thuộc tính đơn giản.
CraigTP

11

Trong cuốn sách của mình , tôi cung cấp sự khác biệt giữa Phụ thuộc ổn định và dễ bay hơi . Điều quan trọng nhất là sử dụng DI với Phụ thuộc dễ bay hơi, nhưng thường thì bạn có thể đạt được sự kết nối lỏng lẻo hơn bằng cách trừu tượng hóa và tiêm Phụ thuộc ổn định.

Hãy nhớ rằng ứng dụng của DI không nên dựa vào DI Container . Trong trường hợp DI của Poor Man đang được sử dụng, không có newtừ khóa nào bị xóa - chúng chỉ được chuyển đến Root Root .

Một số người thực sự thích DI của Poor Man hơn DI Container. Chi phí bảo trì có thể cao hơn, nhưng bạn sẽ nhận được sự an toàn trong thời gian biên dịch. Như gần đây tôi nghe Dan North nói: " newlà cái mới new" :)

Điều này có nghĩa là gì đơn giản hơn là thay vì triển khai Root Root với DI Container, nó chỉ chứa một loạt các newcâu lệnh lồng nhau .


Đánh dấu, để mở rộng một chút về nhận xét Twitter của tôi , Lập trình viên là nơi thích hợp cho các câu hỏi về khái niệm, bảng trắng không xử lý một lỗi cụ thể trong quá trình triển khai.
Adam Lear

3
Stack Overflow có hơn 2000 câu hỏi trong thẻ tiêm phụ thuộc và rất nhiều câu hỏi giống như câu hỏi này. Lập trình viên có 23 câu hỏi trong cùng một thẻ. Dựa trên những con số này, một nhà phát triển nên đi đâu để có cơ hội nhận được câu trả lời cho câu hỏi như thế này?
Mark Seemann

1
Rất nhiều câu hỏi trước các lập trình viên hoàn toàn. Trang web này được tạo ra để loại bỏ các câu hỏi về khái niệm của SO và cung cấp cho họ một ngôi nhà chuyên dụng. Và chúng tôi vẫn đang phát triển. Đây là một công việc đang tiến triển, nhưng những câu hỏi lý tưởng không liên quan đến các vấn đề triển khai cụ thể sẽ được di chuyển ở đây. Chúng tôi làm những gì chúng ta có thể trong lúc này.
Adam Lear

3

"mới" không phải là một từ khóa bị cấm. Quy tắc cá nhân của tôi:

Tất cả "dịch vụ" (Tôi gọi một dịch vụ là một lớp được thiết kế để cung cấp một hoặc nhiều phương thức liên quan đến một và chỉ một điều; ví dụ: truy cập cơ sở dữ liệu, truy xuất / cập nhật dữ liệu liên quan đến một miền nhất định) được đăng ký trong bộ chứa IOC. Không có lớp nào phải đưa ra quyết định về cách có được việc triển khai một dịch vụ nhất định mà nó cần sử dụng. Do đó, bất cứ khi nào bạn cần sử dụng một dịch vụ hiện có, bạn nên cấu hình lớp của bạn và bộ chứa IOC để cung cấp cho bạn. Hãy tưởng tượng rằng bạn không biết cách triển khai của bạn hoạt động, đó có thể là một dịch vụ web, bạn không quan tâm.

Tất cả các loại đậu hoặc mô hình sẽ được tạo bằng từ khóa "mới" hoặc với một nhà máy đã đăng ký IOC khi tôi cần chúng để bật một số thuộc tính mặc định. Ngoài ra còn có trường hợp cụ thể của các lớp tiện ích chỉ chứa các phương thức tĩnh (ví dụ: một dịch vụ tiện ích toán học). Nếu chúng hoàn toàn độc lập và không cần bất kỳ kết nối cơ sở dữ liệu hoặc dịch vụ nào đã đăng ký IOC, tôi sẽ loại chúng ra khỏi IOC và chúng sẽ được gọi là tĩnh. Tuy nhiên, nếu một lớp như vậy cần sử dụng dịch vụ đã đăng ký IOC hiện có, tôi thay đổi nó thành một lớp đơn và đăng ký nó trong IOC.


2

Tôi chỉ muốn thêm vào các câu trả lời hiện có được đưa ra, newlà hoàn toàn tốt để tạo các đối tượng là các đối tượng giá trị thuần túy (tức là chỉ có các thuộc tính / getters / setters). Xem Blog Thử nghiệm của Google để biết thêm chi tiết.


+1 cho liên kết. Điểm 9 trong bài đăng blog đó trả lời câu hỏi và cung cấp sự phân biệt thực tế giữa những gì nên và không nên new'ed
CraigTP

1

Rõ ràng phụ thuộc vào ngôn ngữ bạn sử dụng. Nếu ngôn ngữ của bạn buộc bạn sử dụng các đối tượng để thể hiện cả đối tượng và bản ghi thực tế (đối tượng giá trị, cấu trúc), thì câu trả lời rất có thể là không.

Nói hoàn toàn về các đối tượng "thực", không có gì sai khi tạo một thể hiện rõ ràng. Tuy nhiên, điều bạn phải ghi nhớ là tất cả các lớp nên tuân theo nguyên tắc trách nhiệm duy nhất. Nó không phải là trách nhiệm của một lớp để chọn người thực hiện một dịch vụ mà nó dựa vào. Tuy nhiên, có những lớp người có trách nhiệm rất lớn, tức là cung cấp cho người thực hiện một số dịch vụ nhất định. Một IoC có thể là lớp như vậy. Trong thực tế, bất kỳ loại nhà máy là một lớp như vậy.

Vì vậy, để tóm tắt: Chỉ những lớp như vậy mới trực tiếp khởi tạo đối tượng, ai có trách nhiệm chọn lớp nào để khởi tạo.
Bạn có thể thấy các tiêu chí này hữu ích: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator


1

Một từ: Không.

Thêm từ: tiêm phụ thuộc là chính xác đó. Đó là một phương tiện để bạn giới thiệu các tài nguyên mà một đối tượng khác phụ thuộc vào, nhưng không nên biết các chi tiết phức tạp của, từ một nguồn khác. Sử dụng DI không có nghĩa là KHÔNG CÓ trong chương trình của bạn nên biết cách tạo bất kỳ đối tượng nào khác; trên thực tế, tôi cho rằng rất khó khả thi đối với một chương trình không tầm thường để tránh hoàn toàn từ khóa "mới" (hoặc các lựa chọn thay thế dựa trên phản xạ). Tuy nhiên, DI có nghĩa là các đối tượng không nên biết cách tạo các đối tượng phức tạp đòi hỏi nhiều sự phụ thuộc sẽ kết hợp chặt chẽ đối tượng này với đối tượng khác, không nên có tất cả kiến ​​thức liên kết chặt chẽ này.

Tôi sẽ nghiên cứu hai lý thuyết chính về thiết kế phần mềm O / O, GRASP và RẮN. GRASP sẽ bảo bạn nghiên cứu mục đích của đối tượng và tự hỏi: "Đối tượng này có chịu trách nhiệm tạo ra các đối tượng mới thuộc loại này không? Đó có phải là một phần của 'mô tả công việc' của đối tượng này không?" RẮN tiến thêm một bước: "S" là viết tắt của "Nguyên tắc trách nhiệm duy nhất", nói rõ rằng một đối tượng nên có một công việc và nó phải là đối tượng duy nhất trong chương trình thực hiện công việc cụ thể đó.

Vì vậy, GRASP thường khuyến khích bạn xem qua các lớp hiện có để tạo các đối tượng mới này và tìm một lớp có nhiệm vụ tạo đối tượng này phù hợp với những gì đối tượng đã làm, trong khi duy trì mức độ "gắn kết" mong muốn của bạn. RẮN sẽ cho bạn biết rằng sự gắn kết là chìa khóa; nhiệm vụ tạo ra các đối tượng này nên được giao cho một số nhà máy nên được đưa vào lớp của bạn. Tôi nghĩ rằng bạn sẽ thấy, vì sự phức tạp của chương trình của bạn tiếp tục phát triển, việc tuân thủ một trong hai phương pháp này, với sự sẵn sàng tái cấu trúc, sẽ dẫn đến các kiến ​​trúc rất giống nhau.

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.