Phụ thuộc tiêm: Làm thế nào để bán nó [đóng]


95

Hãy để tôi biết rằng tôi là một fan hâm mộ lớn của tiêm phụ thuộc (DI) và thử nghiệm tự động. Tôi có thể nói cả ngày về nó.

Lý lịch

Gần đây, nhóm của chúng tôi vừa có dự án lớn này được xây dựng từ đầu. Nó là một ứng dụng chiến lược với các yêu cầu kinh doanh phức tạp. Tất nhiên, tôi muốn nó phải đẹp và sạch sẽ, điều đó đối với tôi có nghĩa là: có thể duy trì và kiểm tra được. Vì vậy, tôi muốn sử dụng DI.

Sức cản

Vấn đề là ở đội của chúng tôi, DI là điều cấm kỵ. Nó đã được đưa lên một vài lần, nhưng các vị thần không chấp thuận. Nhưng điều đó không làm tôi nản lòng.

Di chuyển của tôi

Điều này nghe có vẻ lạ nhưng thư viện của bên thứ ba thường không được nhóm kiến ​​trúc sư của chúng tôi chấp thuận (nghĩ: "bạn sẽ không nói về Unity , Ninject , NHibernate , Moq hoặc NUnit , vì tôi sẽ cắt ngón tay của bạn"). Vì vậy, thay vì sử dụng một container DI thành lập, tôi đã viết một container cực kỳ đơn giản. Về cơ bản, nó kết nối tất cả các phụ thuộc của bạn khi khởi động, tiêm bất kỳ phụ thuộc nào (hàm tạo / thuộc tính) và loại bỏ bất kỳ đối tượng dùng một lần nào vào cuối yêu cầu web. Nó rất nhẹ và chỉ làm những gì chúng ta cần. Và sau đó tôi yêu cầu họ xem lại nó.

Phản hồi

Vâng, để làm cho nó ngắn. Tôi đã gặp phải sự kháng cự nặng nề. Đối số chính là, "Chúng ta không cần thêm lớp phức tạp này vào một dự án đã phức tạp". Ngoài ra, "Không giống như chúng tôi sẽ cắm vào các triển khai khác nhau của các thành phần". Và "Chúng tôi muốn giữ cho nó đơn giản, nếu có thể chỉ cần nhét mọi thứ vào một tổ hợp. DI là một sự phức tạp không cần thiết không có lợi ích".

Cuối cùng, câu hỏi của tôi

Làm thế nào bạn sẽ xử lý tình huống của tôi? Tôi không giỏi trình bày ý tưởng của mình, và tôi muốn biết mọi người sẽ trình bày lập luận của họ như thế nào.

Tất nhiên, tôi cho rằng giống như tôi, bạn thích sử dụng DI. Nếu bạn không đồng ý, xin vui lòng nói lý do tại sao để tôi có thể thấy mặt khác của đồng tiền. Sẽ rất thú vị khi thấy quan điểm của một người không đồng ý.

Cập nhật

Cảm ơn câu trả lời của mọi người. Nó thực sự đặt mọi thứ vào quan điểm. Thật tuyệt khi có một đôi mắt khác để cung cấp cho bạn thông tin phản hồi, mười lăm là thực sự tuyệt vời! Đây thực sự là những câu trả lời tuyệt vời và giúp tôi nhìn nhận vấn đề từ các khía cạnh khác nhau, nhưng tôi chỉ có thể chọn một câu trả lời, vì vậy tôi sẽ chỉ chọn một câu trả lời hàng đầu. Cảm ơn mọi người đã dành thời gian trả lời.

Tôi đã quyết định rằng đây có lẽ không phải là thời điểm tốt nhất để thực hiện DI và chúng tôi chưa sẵn sàng cho nó. Thay vào đó, tôi sẽ tập trung nỗ lực của mình để làm cho thiết kế có thể kiểm tra được và cố gắng trình bày thử nghiệm đơn vị tự động. Tôi biết rằng các bài kiểm tra viết là chi phí bổ sung và nếu có quyết định rằng chi phí bổ sung là không xứng đáng, cá nhân tôi vẫn sẽ xem đó là một tình huống có thể thắng vì thiết kế vẫn có thể kiểm tra được. Và nếu từng thử nghiệm hoặc DI là một lựa chọn trong tương lai, thiết kế có thể dễ dàng xử lý nó.


64
Âm thanh như bạn cần phải chuyển đến một công ty khác ...
Sardathrion

24
Sử dụng DI là (ít nhất là trong Java, C #, ...) gần như là kết quả tự nhiên của việc sử dụng các bài kiểm tra đơn vị. Công ty của bạn có sử dụng bài kiểm tra đơn vị không?
sebastiangeiger

27
Hoặc đơn giản là không tập trung vào DI. DI khác với "duy trì và kiểm tra". Khi có nhiều ý kiến ​​khác nhau về một dự án, bạn phải soạn thảo và đôi khi chấp nhận bạn không quyết định. Tôi, ví dụ, đã thấy các thảm họa được khuếch đại bởi sự đảo ngược của các điều khiển, DI và nhiều lớp khung làm cho những điều phức tạp trở nên đơn giản (tôi không thể tranh luận trong trường hợp của bạn).
Denys Séguret

34
"... Tôi có thể nói cả ngày về nó." Âm thanh như bạn cần phải ngừng ám ảnh về một cái gì đó bị lạm dụng thường xuyên hơn không phải vì sự tuân thủ giáo điều với một số giấy trắng trong ngày.

21
Từ âm thanh của nó, đồng nghiệp của bạn có những lý lẽ khách quan chống lại việc sử dụng các thùng chứa DI: chúng ta không cần phải thêm lớp phức tạp này vào một dự án đã phức tạp - họ có thể đúng không? Bạn có thực sự được hưởng lợi từ sự phức tạp thêm vào? Nếu vậy, điều đó nên có thể tranh luận. Họ cho rằng, DI DI là một sự phức tạp không cần thiết, không có lợi ích gì. Nếu bạn có thể thể hiện một lợi ích khách quan thì bạn sẽ giành được điều này khá dễ dàng, phải không? Kiểm tra được đề cập khá thường xuyên trong các ý kiến ​​khác; nhưng xét nghiệm về cơ bản không cần DI, trừ khi bạn cần giả (không phải là nhất định).
Konrad Rudolph

Câu trả lời:


62

Lấy một vài trong số các đối số truy cập:

"Chúng tôi muốn giữ cho nó đơn giản, nếu có thể chỉ cần nhét mọi thứ vào một tổ hợp. DI là một sự phức tạp không cần thiết không có lợi ích".

"Nó không giống như chúng ta sẽ cắm vào các triển khai khác nhau của các thành phần".

Những gì bạn muốn là cho hệ thống có thể kiểm tra được. Để dễ kiểm tra, bạn cần xem xét việc chế nhạo các lớp khác nhau của dự án (cơ sở dữ liệu, thông tin liên lạc, v.v.) và trong trường hợp này, bạn sẽ cắm vào các triển khai khác nhau của các thành phần.

Bán DI trên các lợi ích thử nghiệm mà nó mang lại cho bạn. Nếu dự án phức tạp thì bạn sẽ cần các bài kiểm tra đơn vị tốt, vững chắc.

Một lợi ích khác là, khi bạn đang mã hóa các giao diện, nếu bạn đưa ra một triển khai tốt hơn (nhanh hơn, ít bộ nhớ hơn, bất cứ thứ gì) của một trong các thành phần của bạn, sử dụng DI sẽ giúp dễ dàng trao đổi việc triển khai cũ hơn cho Mới.

Điều tôi đang nói ở đây là bạn cần giải quyết những lợi ích mà DI mang lại thay vì tranh luận về DI vì lợi ích của DI. Bằng cách khiến mọi người đồng ý với tuyên bố:

"Chúng tôi cần X, Y và Z"

Sau đó, bạn chuyển vấn đề. Bạn cần chắc chắn rằng DI là câu trả lời cho tuyên bố này. Bằng cách làm như vậy, đồng nghiệp của bạn sẽ sở hữu giải pháp thay vì cảm thấy rằng nó được áp đặt cho họ.


+1. Ngắn gọn và đến điểm. Thật không may, từ những lập luận được đưa ra bởi đồng nghiệp của Mel, anh ta sẽ gặp khó khăn trong việc thuyết phục họ rằng đáng để thử ngay cả - những gì Spoike nói trong câu trả lời của anh ta, vấn đề của mọi người hơn là vấn đề kỹ thuật.
Patryk Ćwiek

1
@ Trustme-ImaDoctor - Ồ tôi đồng ý rằng đó là vấn đề của mọi người, nhưng với phương pháp này, bạn đang thể hiện những lợi ích thay vì tranh luận về DI vì lợi ích của chính nó.
ChrisF

Đúng và tôi chúc anh ấy may mắn, cuộc sống của anh ấy với tư cách là một nhà phát triển sẽ dễ dàng hơn với khả năng kiểm tra thích hợp, v.v. :)
Patryk wiek

4
+1 Tôi nghĩ đoạn cuối của bạn nên là đoạn đầu tiên. Đó là trung tâm của vấn đề. Nếu có thể Kiểm tra đơn vị được đẩy và chuyển đổi toàn bộ hệ thống sang mô hình DI được đề xuất, tôi cũng sẽ nói không với anh ta.
Andrew T Finnell

+1 thực sự rất hữu ích. Tôi sẽ không nói DI là một điều bắt buộc tuyệt đối để thử nghiệm đơn vị nhưng nó khiến mọi thứ trở nên dễ dàng hơn rất nhiều.
Mel

56

Từ những gì bạn đang viết, không phải bản thân DI là điều cấm kỵ, mà là việc sử dụng các thùng chứa DI, đó là một điều khác biệt. Tôi đoán bạn sẽ không gặp vấn đề gì với nhóm của mình khi bạn chỉ viết các thành phần độc lập có được các thành phần khác mà chúng cần thông qua, ví dụ, bởi nhà xây dựng. Đừng gọi nó là "DI".

Bạn có thể nghĩ rằng các thành phần như vậy không sử dụng container DI là tẻ nhạt, và bạn đã đúng, nhưng hãy cho nhóm của bạn thời gian để tự mình tìm ra điều đó.


10
+1 một cách giải quyết thực dụng cho sự bế tắc chính trị / giáo điều
k3b

32
Dù sao cũng đáng để xem xét kết nối tất cả các đối tượng của bạn bằng tay và chỉ giới thiệu một thùng chứa DI khi nó bắt đầu có lông. Nếu bạn làm điều này, họ sẽ không thấy các thùng chứa DI được thêm vào độ phức tạp - họ sẽ xem nó như là thêm đơn giản.
Phil

2
Vấn đề duy nhất là mô hình chuyển các phụ thuộc được ghép lỏng lẻo vào các phụ thuộc DI. IoC, hoặc việc sử dụng "thùng chứa" để giải quyết các phụ thuộc được kết nối lỏng lẻo, là DI tự động .
KeithS

51

Vì bạn đã hỏi, tôi sẽ đứng về phía đội của bạn chống lại DI.

Vụ kiện chống tiêm chích phụ thuộc

Có một quy tắc tôi gọi là "Bảo tồn sự phức tạp" tương tự như quy tắc trong vật lý gọi là "Bảo tồn năng lượng". Nó tuyên bố rằng không có số lượng kỹ thuật có thể làm giảm tổng độ phức tạp của một giải pháp tối ưu cho một vấn đề, tất cả những gì nó có thể làm là thay đổi sự phức tạp đó xung quanh. Các sản phẩm của Apple không phức tạp hơn Microsoft, họ chỉ đơn giản là chuyển sự phức tạp từ không gian người dùng sang không gian kỹ thuật. (Tuy nhiên, đó là một sự tương tự không hoàn hảo. Mặc dù bạn không thể tạo ra năng lượng, các kỹ sư có thói quen khó chịu khi tạo ra sự phức tạp ở mỗi lượt. Thực tế, rất nhiều lập trình viên dường như thích thêm sự phức tạp và sử dụng phép thuật, đó là do độ phức tạp định nghĩa mà lập trình viên không hiểu đầy đủ. Sự phức tạp dư thừa này có thể được giảm bớt.) Thông thường những gì có vẻ như giảm độ phức tạp chỉ đơn giản là chuyển sự phức tạp ở một nơi khác, thường là đến một thư viện.

Tương tự, DI không làm giảm sự phức tạp của việc liên kết các đối tượng máy khách với các đối tượng máy chủ. Những gì nó làm là lấy nó ra khỏi Java và chuyển nó thành XML. Điều đó tốt ở chỗ nó tập trung mọi thứ vào một (hoặc một vài) tệp XML, nơi dễ dàng thấy mọi thứ đang diễn ra và nơi có thể thay đổi mọi thứ mà không cần biên dịch lại mã. Mặt khác, điều đó thật tệ vì các tệp XML không phải là Java và do đó không có sẵn cho công cụ Java. Bạn không thể gỡ lỗi chúng trong trình gỡ lỗi, bạn không thể sử dụng phân tích tĩnh để theo dõi hệ thống phân cấp cuộc gọi của chúng, v.v. Đặc biệt, các lỗi trong khung DI trở nên cực kỳ khó phát hiện, xác định và sửa chữa.

Do đó, khó hơn nhiều để chứng minh một chương trình là chính xác khi sử dụng DI. Nhiều người cho rằng các chương trình sử dụng DI dễ kiểm tra hơn , nhưng kiểm tra chương trình không bao giờ có thể chứng minh sự vắng mặt của lỗi . (Lưu ý rằng bài báo được liên kết khoảng 40 tuổi và có một số tài liệu tham khảo phức tạp và trích dẫn một số thực tiễn lỗi thời, nhưng nhiều tuyên bố cơ bản vẫn đúng. Đặc biệt, P <= p ^ n, trong đó P là xác suất hệ thống không có lỗi, p là xác suất thành phần hệ thống không có lỗi và n là số lượng thành phần. Tất nhiên, phương trình này quá đơn giản, nhưng nó chỉ ra một sự thật quan trọng.) Sự cố NASDAQ trong quá trình IPO Facebook là một ví dụ gần đây, trong đóhọ tuyên bố họ đã dành 1.000 giờ để kiểm tra mã và vẫn không phát hiện ra các lỗi gây ra sự cố. 1.000 giờ là nửa năm, vì vậy không giống như họ đang lướt qua bài kiểm tra.

Đúng, hầu như không ai từng đảm nhận (huống chi là hoàn thành) nhiệm vụ chính thức chứng minh bất kỳ mã nào là chính xác, nhưng ngay cả những nỗ lực yếu trong chứng minh đã đánh bại hầu hết các chế độ kiểm tra để tìm lỗi. Những nỗ lực mạnh mẽ trong việc chứng minh, ví dụ L4.verified , luôn luôn phát hiện ra một số lượng lớn lỗi mà thử nghiệm không và có lẽ sẽ không bao giờ phát hiện ra trừ khi người kiểm tra đã biết chính xác bản chất của lỗi. Bất cứ điều gì làm cho mã khó kiểm tra hơn bằng cách kiểm tra đều có thể được xem là làm giảm khả năng lỗi sẽ được phát hiện , ngay cả khi nó làm tăng khả năng kiểm tra.

Hơn nữa DI không cần thiết để thử nghiệm . Tôi hiếm khi sử dụng nó cho mục đích đó, vì tôi thích kiểm tra hệ thống dựa trên phần mềm thực trong hệ thống hơn là một số phiên bản thử nghiệm thay thế. Mọi thứ tôi thay đổi trong kiểm tra là (hoặc cũng có thể) được lưu trữ trong các tệp thuộc tính hướng chương trình tới các tài nguyên trong môi trường kiểm tra thay vì sản xuất. Tôi thà dành thời gian để thiết lập một máy chủ cơ sở dữ liệu thử nghiệm với một bản sao của cơ sở dữ liệu sản xuất hơn là dành thời gian mã hóa cơ sở dữ liệu giả, bởi vì cách này tôi sẽ có thể theo dõi các vấn đề với dữ liệu sản xuất (vấn đề mã hóa ký tự chỉ là một ví dụ ) và lỗi tích hợp hệ thống cũng như lỗi trong phần còn lại của mã.

Phụ thuộc tiêm cũng không cần thiết cho đảo ngược phụ thuộc . Bạn có thể dễ dàng sử dụng các phương thức tĩnh của nhà máy để thực hiện Nghịch đảo phụ thuộc. Trên thực tế, đó là cách nó được thực hiện vào những năm 1990.

Trên thực tế, mặc dù tôi đã sử dụng DI trong một thập kỷ, nhưng ưu điểm duy nhất mà tôi thấy có sức thuyết phục là khả năng định cấu hình thư viện của bên thứ ba để sử dụng các thư viện bên thứ ba khác (ví dụ: thiết lập Spring để sử dụng Hibernate và cả hai để sử dụng Log4J ) và cho phép IoC thông qua proxy. Nếu bạn không sử dụng thư viện của bên thứ ba và không sử dụng IoC, thì sẽ không có nhiều điểm cho nó và nó thực sự làm tăng thêm sự phức tạp không đáng có.


1
Tôi không đồng ý, nó có thể làm giảm sự phức tạp. Tôi biết vì tôi đã làm nó. Tất nhiên, một số vấn đề / yêu cầu bắt buộc phức tạp, nhưng trên hết có thể loại bỏ nó bằng nỗ lực.
Ricky Clarkson

10
@Ricky, đó là một sự khác biệt tinh tế. Như tôi đã nói, các kỹ sư có thể thêm độ phức tạp và độ phức tạp đó có thể bị loại bỏ, do đó bạn có thể giảm độ phức tạp của việc triển khai, nhưng theo định nghĩa, bạn không thể giảm độ phức tạp của giải pháp tối ưu cho một vấn đề. Hầu hết những gì có vẻ như làm giảm sự phức tạp chỉ là chuyển nó sang một nơi khác (thường là thư viện). Trong mọi trường hợp, điều thứ yếu là điểm chính của tôi, đó là DI không làm giảm độ phức tạp.
Old Pro

2
@Lee, cấu hình DI trong mã thậm chí còn ít hữu ích hơn. Một trong những lợi ích được chấp nhận rộng rãi nhất của DI là khả năng thay đổi triển khai dịch vụ mà không cần biên dịch lại mã và nếu bạn định cấu hình DI trong mã thì bạn sẽ mất điều đó.
Old Pro

7
@OldPro - Cấu hình trong mã có lợi ích của an toàn kiểu và phần lớn các phụ thuộc là tĩnh và không có lợi ích từ việc được xác định bên ngoài.
Lee

3
@Lee Nếu các phụ thuộc là tĩnh, tại sao chúng không được mã hóa cứng ngay từ đầu, mà không có đường vòng qua DI?
Konrad Rudolph

25

Tôi rất tiếc phải nói rằng vấn đề bạn gặp phải, dựa trên những gì đồng nghiệp đã nói trong câu hỏi của bạn, là về bản chất chính trị chứ không phải là kỹ thuật. Có hai câu thần chú mà bạn nên ghi nhớ:

  • "Đó luôn là vấn đề của mọi người"
  • " Thay đổi là đáng sợ"

Chắc chắn, bạn có thể đưa ra rất nhiều lý lẽ phản biện với lý do và lợi ích kỹ thuật vững chắc, nhưng điều đó sẽ khiến bạn rơi vào tình huống tồi tệ với phần còn lại của công ty. Họ đã có lập trường rằng họ không muốn điều đó (vì họ cảm thấy thoải mái với cách mọi thứ đang hoạt động). Vì vậy, nó thậm chí có thể làm tổn thương mối quan hệ của bạn với các đồng nghiệp nếu bạn cứ kiên trì với nó. Hãy tin tôi vào điều này bởi vì nó đã xảy ra với tôi và cuối cùng đã khiến tôi bị sa thải vài năm trước (tôi còn trẻ và ngây thơ); đây là một tình huống bạn không muốn mắc phải.

Vấn đề là, bạn cần đạt được một số mức độ tin cậy trước khi mọi người sẽ đi xa hơn để thay đổi cách làm việc hiện tại của họ. Trừ khi bạn ở trong một vị trí mà bạn có nhiều niềm tin hoặc bạn có thể quyết định những loại việc này, chẳng hạn như có vai trò của một kiến ​​trúc sư hoặc lãnh đạo công nghệ, có rất ít bạn có thể làm để xoay chuyển các đồng nghiệp của mình. Sẽ mất rất nhiều thời gian với sự thuyết phục và nỗ lực (như thực hiện các bước cải tiến nhỏ) để có được sự tin tưởng để có được văn hóa công ty của bạn để quay vòng. Chúng ta đang nói về khoảng thời gian nhiều tháng hoặc nhiều năm.

Nếu bạn thấy rằng văn hóa công ty hiện tại không hoạt động với bạn thì ít nhất bạn cũng biết một điều khác để hỏi về cuộc phỏng vấn việc làm tiếp theo của bạn. ;-)


23

Đừng sử dụng DI. Quên đi.

Tạo một triển khai mô hình nhà máy GoF "tạo ra" hoặc "tìm thấy" các phụ thuộc cụ thể của bạn và chuyển chúng vào đối tượng của bạn và để nó ở đó, nhưng đừng gọi nó là DI và không tạo ra một khung tổng quát phức tạp. Giữ nó đơn giản và có liên quan. Đảm bảo các phụ thuộc và các lớp của bạn sao cho có thể chuyển sang DI; nhưng giữ cho nhà máy là chủ và giữ cho nó cực kỳ hạn chế về phạm vi.

Trong thời gian, bạn có thể hy vọng rằng nó sẽ phát triển và thậm chí một ngày chuyển sang DI. Hãy để khách hàng tiềm năng đi đến kết luận về thời gian của riêng họ và đừng thúc ép. Ngay cả khi bạn không bao giờ đạt được điều đó, ít nhất mã của bạn có một số ưu điểm của DI, ví dụ, mã có thể kiểm tra đơn vị.


3
+1 để phát triển cùng với dự án và "đừng gọi nó là DI"
Kevin McCormick

5
Tôi đồng ý, nhưng cuối cùng, đó là DI. Chỉ là không sử dụng container DI; nó chuyển gánh nặng cho người gọi thay vì tập trung nó ở một nơi. Tuy nhiên, sẽ là thông minh nếu gọi nó là "Phụ thuộc bên ngoài" thay vì DI.
Juan Mendes

5
Tôi thường nghĩ rằng để thực sự tìm hiểu khái niệm tháp ngà như DI, ​​bạn phải trải qua quá trình tương tự như các nhà truyền giáo đã làm để nhận ra rằng có một vấn đề cần giải quyết ngay từ đầu. Các tác giả thường quên điều này. Gắn bó với ngôn ngữ mẫu cấp thấp và nhu cầu về một thùng chứa có thể (hoặc không) xuất hiện do hậu quả.
Tom W

@JuanMendes từ phản hồi của họ Tôi nghĩ rằng việc phụ thuộc bên ngoài cụ thể là những gì họ phản đối vì họ không thích thư viện của bên thứ ba hoặc muốn mọi thứ trong một hội đồng (nguyên khối?). Nếu đó là sự thật thì việc gọi nó là "Phụ thuộc bên ngoài" không tốt hơn gọi DI từ điểm thuận lợi của họ.
Jonathan Neufeld

22

Tôi đã thấy các dự án đưa DI đến mức cực đoan để kiểm tra đơn vị và các đối tượng giả. Nhiều đến mức cấu hình DI trở thành ngôn ngữ lập trình với chính cấu hình cần thiết để có được một hệ thống chạy như mã thực tế.

Có phải hệ thống đang bị ảnh hưởng vì thiếu API nội bộ phù hợp không thể kiểm tra được? Bạn có hy vọng rằng việc chuyển đổi hệ thống sang mô hình DI sẽ cho phép bạn kiểm tra đơn vị tốt hơn không? Bạn không cần một thùng chứa để kiểm tra mã của bạn. Sử dụng mô hình DI sẽ cho phép bạn kiểm tra đơn vị dễ dàng hơn với các đối tượng Mock, nhưng không bắt buộc.

Bạn không cần phải chuyển toàn bộ hệ thống để tương thích DI cùng một lúc. Bạn cũng không nên tự ý viết bài kiểm tra Đơn vị. Mã tái cấu trúc khi bạn bắt gặp nó trong tính năng của bạn và vé làm việc lỗi. Sau đó, đảm bảo rằng mã bạn đã chạm vào có thể dễ dàng kiểm tra.

Hãy nghĩ về CodeRot như một căn bệnh. Bạn không muốn bắt đầu tự ý hack đi mọi thứ. Bạn có một bệnh nhân, bạn thấy một chỗ đau, vì vậy bạn bắt đầu sửa chữa chỗ đó và những thứ xung quanh nó. Khi khu vực đó sạch sẽ, bạn chuyển sang kế tiếp. Sớm hay muộn bạn sẽ chạm vào phần lớn mã và nó không yêu cầu thay đổi kiến ​​trúc "đồ sộ" này.

Tôi không thích việc thử nghiệm DI và Mock loại trừ lẫn nhau. Và sau khi thấy một dự án đã đi, vì không có từ nào hay hơn, điên rồ khi sử dụng DI, tôi cũng sẽ mệt mỏi mà không thấy được lợi ích.

Có một số nơi có ý nghĩa khi sử dụng DI:

  • Lớp truy cập dữ liệu để trao đổi chiến lược lấy dữ liệu kể chuyện
  • Lớp xác thực và ủy quyền.
  • Chủ đề cho giao diện người dùng
  • Dịch vụ
  • Điểm mở rộng plugin mà hệ thống của riêng bạn hoặc bên thứ ba có thể sử dụng.

Yêu cầu mỗi nhà phát triển biết tệp cấu hình DI ở đâu (tôi nhận thấy các thùng chứa có thể được khởi tạo thông qua mã, nhưng tại sao bạn lại làm như vậy.) Khi họ muốn thực hiện RegEx thật khó chịu. Ồ tôi thấy có IRegExCompiler, DefaultRegExCompiler và SuperAw đũaRegExCompiler. Tuy nhiên, không có nơi nào trong mã tôi có thể phân tích để xem Mặc định được sử dụng ở đâu và SuperAwgie được sử dụng.

Tính cách của riêng tôi sẽ phản ứng tốt hơn nếu ai đó chỉ cho tôi thứ gì đó tốt hơn, sau đó cố gắng thuyết phục tôi bằng lời nói của họ. Có điều gì đó để nói về ai đó sẽ dành thời gian và nỗ lực để làm cho hệ thống tốt hơn. Tôi không thấy rằng nhiều nhà phát triển quan tâm đủ để làm cho sản phẩm thực sự tốt hơn. Nếu bạn có thể tìm đến họ với những thay đổi thực sự trong hệ thống và chỉ cho họ cách nó làm cho nó tốt hơn và dễ dàng hơn cho bạn, điều đó đáng giá hơn bất kỳ nghiên cứu trực tuyến nào.

Tóm lại, cách tốt nhất để thực hiện thay đổi thành một hệ thống là từ từ làm cho mã bạn hiện đang chạm tốt hơn với mỗi lần chuyển. Sớm muộn gì bạn cũng có thể biến hệ thống thành thứ gì đó tốt hơn.


"Thử nghiệm DI và Mock là loại trừ lẫn nhau" Điều đó là sai, chúng cũng không bao gồm lẫn nhau. Họ chỉ làm việc tốt với nhau. Bạn cũng liệt kê các địa điểm DI là tốt, lớp dịch vụ, dao và giao diện người dùng - hầu như ở mọi nơi phải không?
NimChimpsky

@Andrew điểm hợp lệ. Tất nhiên, tôi sẽ không muốn nó đi quá xa. Tôi muốn kiểm tra tự động cho các lớp kinh doanh nhiều nhất, vì chúng tôi phải thực hiện các quy tắc kinh doanh rất phức tạp. Và tôi nhận ra rằng tôi vẫn có thể kiểm tra chúng mà không cần container, nhưng cá nhân tôi, việc sử dụng một container là hợp lý. Tôi thực sự đã làm một mẫu nhỏ cho thấy khái niệm này. Nhưng nó thậm chí không nhìn vào. Tôi đoán sai lầm của tôi là tôi đã không tạo ra một thử nghiệm cho thấy thử nghiệm / chế nhạo dễ dàng như thế nào.
Mel

Rất nhiều thỏa thuận! Tôi thực sự rất ghét các tập tin cấu hình DI và ảnh hưởng của nó đến việc theo dõi dòng chương trình. Toàn bộ sự việc biến thành "hành động ma quái ở khoảng cách xa" không có kết nối rõ ràng giữa các mảnh. Khi việc đọc mã trong trình gỡ lỗi trở nên dễ dàng hơn trong các tệp nguồn, có gì đó thực sự sai.
Zan Lynx

19

DI không yêu cầu Inversion xâm lấn các container Điều khiển hoặc khung mô phỏng. Bạn có thể tách mã và cho phép DI thông qua một thiết kế đơn giản. Bạn có thể thực hiện kiểm tra đơn vị thông qua các khả năng Visual Studio tích hợp.

Để công bằng, đồng nghiệp của bạn có một điểm. Sử dụng những thư viện đó không tốt (và vì họ không quen thuộc với chúng, sẽ có những khó khăn trong học tập) sẽ gây ra vấn đề. Cuối cùng, vấn đề mã. Đừng làm hỏng sản phẩm của bạn để kiểm tra.

Chỉ cần nhớ rằng sự thỏa hiệp là cần thiết trong các kịch bản này.


2
Tôi đồng ý DI không yêu cầu container IoC. mặc dù tôi sẽ không gọi nó là xâm lấn (ít nhất là việc thực hiện này) vì mã được thiết kế là bất khả tri của container (chủ yếu là tiêm xây dựng) và tất cả các công cụ DI xảy ra ở một nơi. Vì vậy, tất cả vẫn hoạt động mà không có bộ chứa DI - Tôi đưa vào các hàm tạo không tham số "tiêm" các triển khai cụ thể cho các hàm tạo khác với các phụ thuộc. Bằng cách đó tôi vẫn có thể dễ dàng chế giễu nó. Vì vậy, tôi đồng ý, DI thực sự đạt được bằng thiết kế.
Mel

+1 Để thỏa hiệp. Nếu không ai muốn thỏa hiệp, mọi người đều kết thúc đau khổ.
Tjaart

14

Tôi không nghĩ rằng bạn có thể bán DI nữa, vì đây là một quyết định giáo điều (hoặc, như @Spoike gọi nó là lịch sự hơn, mang tính chính trị ).

Trong Tình huống này, việc tranh luận với các thực tiễn tốt nhất được chấp nhận rộng rãi như các nguyên tắc thiết kế RẮN là không thể thực hiện được nữa.

Ai đó có quyền lực chính trị nhiều hơn bạn đã đưa ra quyết định (có thể sai) về việc không sử dụng DI.

Mặt khác, bạn đã phản đối quyết định này bằng cách triển khai container của riêng bạn vì việc sử dụng một container được thiết lập đã bị cấm. Chính sách này của các đồng phạm mà bạn đã thử có thể khiến tình hình tồi tệ hơn.

Phân tích

Theo tôi, DI không có sự phát triển thử nghiệm (TDD) và thử nghiệm đơn vị không có lợi ích đáng kể nào vượt xa các chi phí phụ ban đầu.

Vấn đề này có thực sự là về

  • chúng tôi không muốn DI ?

hoặc đây là thêm về

  • Tdd / unittesting là một sự lãng phí tài nguyên ?

[Cập nhật]

Nếu bạn thấy dự án của mình từ những sai lầm kinh điển trong quan điểm quản lý dự án , bạn sẽ thấy

#12: Politics placed over substance.
#21: Inadequate design. 
#22: Shortchanged quality assurance.
#27: Code-like-hell programming.

trong khi những người khác nhìn thấy

#3: Uncontrolled problem employees. 
#30: Developer gold-plating. 
#32: Research-oriented development. 
#34: Overestimated savings from new tools or methods. 

chúng tôi hiện không làm bất kỳ thử nghiệm đơn vị nào trong nhóm của chúng tôi. Tôi nghi ngờ rằng tuyên bố cuối cùng của bạn là tại chỗ. Tôi đã đưa ra thử nghiệm đơn vị một vài lần nhưng không ai tỏ ra quan tâm thực sự đến nó và luôn có lý do tại sao chúng tôi không thể áp dụng nó.
Mel

10

Nếu bạn thấy mình cần phải "bán" một nguyên tắc cho nhóm của bạn, sau đó bạn có thể đã vài dặm xuống con đường sai.

Không ai muốn làm thêm, vì vậy nếu những gì bạn đang cố gắng bán cho họ giống như làm thêm, thì bạn sẽ không thuyết phục được họ bằng cách lập lại Lời cầu khẩn của lập luận. Họ cần biết rằng bạn đang chỉ cho họ một cách để giảm khối lượng công việc chứ không phải tăng nó.

DI thường được xem là sự phức tạp thêm bây giờ với lời hứa về sự phức tạp giảm tiềm năng sau này , có giá trị, nhưng không nhiều đối với những người đang cố gắng giảm khối lượng công việc trả trước của họ. Và trong nhiều trường hợp, DI chỉ là một lớp khác của YAGNI . Và chi phí cho sự phức tạp này không phải là không, nó thực sự khá cao đối với một nhóm không quen với kiểu mẫu này. Và đó là đô la thực sự được đưa vào một cái xô có thể không bao giờ mang lại bất kỳ lợi ích nào.

Đặt nó vào vị trí của nó
Đặt cược tốt nhất của bạn là sử dụng DI nơi nó rất hữu dụng, thay vì chỉ là nơi phổ biến. Ví dụ: nhiều ứng dụng sử dụng DI để chọn và định cấu hình cơ sở dữ liệu. Và nếu ứng dụng của bạn xuất xưởng với lớp cơ sở dữ liệu thì đó là một nơi hấp dẫn để đặt nó. Nhưng nếu ứng dụng của bạn vận chuyển với cơ sở dữ liệu vô hình người dùng tích hợp được tích hợp chặt chẽ vào mã, thì khả năng cần phải thay thế DB khi tiếp cận thời gian chạy bằng không. Và bán DI bằng cách nói, "nhìn này, chúng ta có thể dễ dàng làm điều này mà chúng ta sẽ không bao giờ muốn làm", có khả năng đưa bạn vào danh sách "anh chàng này có ý tưởng tồi" với sếp của bạn.

Nhưng giả sử thay vào đó bạn có đầu ra gỡ lỗi thường được phát hành IFDEF. Và mỗi khi người dùng gặp sự cố, nhóm hỗ trợ của bạn phải gửi cho họ bản dựng gỡ lỗi để họ có thể nhận được đầu ra nhật ký. Bạn có thể sử dụng DI ở đây để cho phép khách hàng chuyển đổi giữa các trình điều khiển nhật ký - LogConsolecho nhà phát triển, LogNullcho khách hàng và LogNetworkcho khách hàng có vấn đề. Một bản dựng thống nhất, cấu hình thời gian chạy.

Sau đó, bạn thậm chí không phải gọi nó là DI, thay vào đó nó chỉ được gọi là "Ý tưởng thực sự tốt của Mel" và bây giờ bạn đang ở trong danh sách ý tưởng tốt thay vì ý tưởng tồi. Mọi người sẽ thấy mô hình hoạt động tốt như thế nào và bắt đầu sử dụng nó ở nơi có ý nghĩa trong mã của họ.

Khi bạn bán đúng ý tưởng, mọi người sẽ không biết rằng bạn đã thuyết phục họ về bất cứ điều gì.


8

Tất nhiên, Inversion of control (IoC) có rất nhiều lợi ích: nó đơn giản hóa mã, thêm một số phép thuật đang thực hiện các nhiệm vụ điển hình, v.v.

Tuy nhiên:

  1. Nó thêm rất nhiều phụ thuộc. Ứng dụng hello world đơn giản được viết bằng Spring có thể nặng hàng chục MB và tôi chỉ thấy Spring được thêm vào để tránh một vài dòng của hàm tạo và setters.

  2. Nó bổ sung thêm phép thuật đã nói ở trên , điều khó hiểu đối với người ngoài (ví dụ: các nhà phát triển GUI cần thực hiện một số thay đổi trong lớp nghiệp vụ). Xem bài viết tuyệt vời Những bộ óc sáng tạo Đừng nghĩ giống nhau - Thời báo New York , trong đó mô tả cách hiệu ứng này được các chuyên gia đánh giá thấp .

  3. Nó cứng để theo dõi việc sử dụng các lớp. Các IDE như Eclipse có các khả năng tuyệt vời để theo dõi việc sử dụng các lớp hoặc các cách gọi phương thức đã cho. Nhưng dấu vết này bị mất khi có tiêm phụ thuộc và phản xạ được gọi.

  4. Việc sử dụng IoC thường không kết thúc bằng việc tiêm phụ thuộc, kết thúc bằng vô số proxy và bạn nhận được dấu vết ngăn xếp đếm hàng trăm dòng, 90% trong số đó là proxy và gọi qua phản chiếu. Nó rất phức tạp phân tích dấu vết ngăn xếp.

Vì vậy, bản thân tôi là một người hâm mộ tuyệt vời của Spring và IoC, gần đây tôi đã phải suy nghĩ lại về các câu hỏi ở trên. Một số đồng nghiệp của tôi là các nhà phát triển web được đưa vào thế giới Java từ thế giới Web được cai trị bởi Python và PHP và điều hiển nhiên đối với những thứ javaist là bất cứ điều gì rõ ràng hơn đối với họ. Một số đồng nghiệp khác của tôi đang thực hiện các thủ thuật (tất nhiên là không có giấy tờ) khiến cho lỗi rất khó tìm. Tất nhiên sự lạm dụng IoC làm cho mọi thứ nhẹ hơn đối với họ;)

Lời khuyên của tôi, nếu bạn buộc sử dụng IoC trong công việc của mình, bạn sẽ phải chịu trách nhiệm cho bất kỳ hành vi lạm dụng nào mà người khác sẽ thực hiện;)


+1 như với mọi công cụ mạnh mẽ, nó dễ bị sử dụng sai và bạn PHẢI hiểu khi KHÔNG sử dụng nó.
Phil

4

Tôi nghĩ rằng ChrisF là một cái gì đó đúng. Đừng bán DI trong chính nó. Nhưng bán ý tưởng về đơn vị thử nghiệm mã.

Một cách tiếp cận để đưa một container DI vào kiến ​​trúc có thể là sau đó từ từ để các thử nghiệm thúc đẩy việc thực hiện thành một thứ phù hợp với kiến ​​trúc đó. Ví dụ: giả sử bạn đang làm việc trên bộ điều khiển trong ứng dụng ASP.NET MVC. Nói rằng bạn viết lớp như thế này:

public class UserController {
    public UserController() : this (new UserRepository()) {}

    public UserController(IUserRepository userRepository) {
        ...
    }

    ...
}

Điều đó cho phép bạn viết các bài kiểm tra đơn vị tách rời khỏi việc triển khai thực tế của kho lưu trữ người dùng. Nhưng lớp vẫn hoạt động mà không có thùng chứa DI để tạo nó cho bạn. Hàm tạo không tham số sẽ tạo nó với kho lưu trữ mặc định.

Nếu đồng nghiệp của bạn có thể thấy rằng điều này dẫn đến các bài kiểm tra sạch hơn nhiều, có thể họ có thể nhận ra rằng đó là một cách tốt hơn. Có lẽ bạn có thể khiến họ bắt đầu viết mã như vậy.

Khi họ đã nhận ra rằng đây là một thiết kế tốt hơn so với UserContoder biết về việc triển khai UserRep repository cụ thể, bạn có thể thực hiện bước tiếp theo và cho họ thấy rằng bạn có thể có một thành phần, thùng chứa DI, có thể tự động cung cấp các trường hợp bạn yêu cầu.


Tuyệt quá! Tôi hiện đang làm điều này bởi vì tôi thực sự muốn thử nghiệm đơn vị tự động, ngay cả khi tôi không thể nhận được DI. Tôi quên đề cập rằng các bài kiểm tra đơn vị cũng không được thực hiện trong nhóm của chúng tôi :( vì vậy nếu tôi sẽ là người đầu tiên.
Mel

2
Trong trường hợp đó, tôi muốn nói rằng đó là vấn đề thực sự ở đây. Tìm gốc của kháng chiến để kiểm tra đơn vị, và tấn công đó. Hãy để DI nói dối ngay bây giờ. Kiểm tra là quan trọng hơn IMHO.
Christian Horsdal

@ChristianHorsdal Tôi đồng ý, tôi muốn nó được ghép lỏng lẻo để cho phép thử nghiệm / thử nghiệm dễ dàng.
Mel

Ý tưởng đó thực sự rất tuyệt ... Bán tuyệt vời để thử nghiệm
bunglestink

2

Có lẽ điều tốt nhất để làm là lùi lại và tự hỏi tại sao bạn muốn giới thiệu container DI? Nếu đó là để cải thiện khả năng kiểm tra thì nhiệm vụ đầu tiên của bạn là đưa nhóm mua vào thử nghiệm đơn vị. Cá nhân tôi sẽ quan tâm nhiều hơn đến việc thiếu các bài kiểm tra đơn vị hơn là thiếu một container DI.

Được trang bị một bộ hoặc bộ kiểm tra đơn vị toàn diện, bạn có thể tự tin thiết lập về việc phát triển thiết kế của mình theo thời gian. Không có họ, bạn phải đối mặt với một cuộc đấu tranh ngày càng khốc liệt để giữ cho thiết kế của bạn phù hợp với các yêu cầu phát triển, một cuộc đấu tranh mà cuối cùng nhiều đội thua cuộc.

Vì vậy, lời khuyên của tôi sẽ là thử nghiệm và tái cấu trúc đơn vị vô địch đầu tiên sau đó, lần lượt giới thiệu DI và cuối cùng là các container DI.


2

Tôi đang nghe một số no-nos lớn từ nhóm của bạn ở đây:

  • "Không có thư viện của bên thứ ba" - AKA "Không được phát minh ở đây" hoặc "NIH". Điều đáng sợ là, bằng cách triển khai thư viện của bên thứ ba và do đó làm cho cơ sở mã phụ thuộc vào nó, thư viện sẽ có lỗi, hoặc lỗ hổng bảo mật hoặc thậm chí chỉ là một giới hạn mà bạn cần khắc phục, bạn trở nên phụ thuộc vào thứ ba này bên để sửa thư viện của họ để mã của bạn hoạt động. Trong khi đó, vì chương trình "của bạn" đã thất bại một cách ngoạn mục, hoặc bị hack hoặc không làm những gì họ yêu cầu, bạn vẫn phải chịu trách nhiệm (và các nhà phát triển bên thứ ba sẽ nói rằng công cụ của họ là "như hiện tại ", Sử dụng có nguy cơ của riêng bạn).

    Đối số là mã giải quyết vấn đề đã tồn tại trong thư viện của bên thứ ba. Bạn đang xây dựng máy tính của bạn từ đầu? Bạn đã viết Visual Studio? Bạn đang tránh các thư viện tích hợp trong .NET? Không. Bạn có mức độ tin tưởng vào Intel / AMD và Microsoft và họ luôn tìm thấy lỗi (và không phải lúc nào cũng sửa chúng nhanh chóng). Thêm thư viện của bên thứ ba cho phép bạn nhanh chóng có được một cơ sở mã duy trì hoạt động mà không phải phát minh lại bánh xe. Và đội ngũ luật sư của Microsoft sẽ cười vào mặt bạn khi bạn nói với họ rằng một lỗi trong thư viện mã hóa .NET khiến họ phải chịu trách nhiệm về sự cố hack khách hàng của bạn phải chịu khi sử dụng chương trình .NET của bạn. Mặc dù Microsoft chắc chắn sẽ nhảy vào để sửa các lỗ hổng bảo mật "0 giờ" trong bất kỳ sản phẩm nào của mình,

  • "Chúng tôi muốn nhét mọi thứ vào một cụm" - thực ra, bạn không. Trong .NET ít nhất, nếu bạn thực hiện thay đổi đối với một dòng mã, toàn bộ tổ hợp chứa dòng mã đó phải được xây dựng lại. Thiết kế mã tốt dựa trên nhiều tập hợp mà bạn có thể xây dựng lại một cách độc lập nhất có thể (hoặc ít nhất là chỉ phải xây dựng lại các phụ thuộc, không phải phụ thuộc). Nếu họ THỰC SỰ muốn phát hành một EXE chỉ là EXE (có giá trị trong một số trường hợp nhất định), thì có một ứng dụng cho điều đó; ILMerge.

  • "DI là điều cấm kỵ" - WTF? DI là cách thực hành tốt nhất được chấp nhận trong bất kỳ ngôn ngữ O / O nào với cấu trúc mã "giao diện". Làm thế nào để nhóm của bạn tuân thủ các phương pháp thiết kế GRASP hoặc RẮN nếu chúng không liên kết lỏng lẻo giữa các phụ thuộc giữa các đối tượng? Nếu họ không làm phiền, thì họ sẽ duy trì nhà máy mì spaghetti làm cho sản phẩm trở nên phức tạp. Bây giờ, DI tăng độ phức tạp bằng cách tăng số lượng đối tượng và trong khi nó làm cho việc thay thế một cách thực hiện khác dễ dàng hơn, nó làm cho việc thay đổi giao diện trở nên khó khăn hơn (bằng cách thêm một lớp đối tượng mã phải thay đổi).

  • "Chúng tôi không cần thêm lớp phức tạp này vào một dự án đã phức tạp" - Họ có thể có một điểm. Một điều quan trọng cần xem xét trong bất kỳ sự phát triển mã nào là YAGNI; "Bạn không cần Gonna". Một thiết kế được thiết kế R SOL RÀNG ngay từ đầu là một thiết kế được làm RẮN "dựa trên niềm tin"; bạn không biết liệu bạn có cần sự thay đổi dễ dàng mà các thiết kế RẮN cung cấp hay không, nhưng bạn có linh cảm. Trong khi bạn có thể đúng, bạn cũng có thể rất sai; một thiết kế rất RẮN cuối cùng có thể được xem là "mã lasagna" hoặc "mã ravioli", có quá nhiều lớp hoặc khối kích cỡ cắn khiến việc thay đổi dường như trở nên khó khăn vì bạn phải tìm hiểu rất nhiều lớp và / hoặc theo dõi như một ngăn xếp cuộc gọi phức tạp.

    Tôi ủng hộ quy tắc ba lần: Làm cho nó hoạt động, làm cho nó sạch sẽ, làm cho nó RẮN. Khi bạn lần đầu tiên viết một dòng mã, nó chỉ phải hoạt động và bạn không nhận được điểm cho các thiết kế tháp ngà. Giả sử đó là một lần và làm những gì bạn phải làm. Lần thứ hai bạn nhìn vào mã đó, có lẽ bạn đang muốn mở rộng hoặc tái sử dụng nó và đó không phải là lần đầu tiên bạn nghĩ nó sẽ xảy ra. Tại thời điểm này, làm cho nó thanh lịch và dễ hiểu hơn bằng cách tái cấu trúc nó; đơn giản hóa logic phức tạp, trích xuất mã lặp đi lặp lại thành các vòng lặp và / hoặc các cuộc gọi phương thức, thêm một vài nhận xét ở đây và ở đó cho bất kỳ loại bùn nào bạn phải để lại, v.v. Lần thứ ba bạn nhìn vào mã đó có lẽ là một vấn đề lớn. Bây giờ bạn nên tuân thủ các quy tắc RẮN; tiêm phụ thuộc thay vì xây dựng chúng, trích xuất các lớp để giữ các phương thức ít gắn kết với "thịt" của mã,

  • "Không giống như chúng tôi sẽ thực hiện các triển khai khác nhau" - Bạn, thưa ngài, có một nhóm không tin vào các bài kiểm tra đơn vị trên tay bạn. Tôi khẳng định rằng không thể viết một bài kiểm tra đơn vị, chạy một cách cô lập và không có tác dụng phụ, mà không thể "chế nhạo" các đối tượng có những tác dụng phụ đó. Bất kỳ chương trình không tầm thường đều có tác dụng phụ; nếu chương trình của bạn đọc hoặc ghi vào DB, mở hoặc lưu tệp, giao tiếp qua mạng hoặc ổ cắm ngoại vi, khởi chạy chương trình khác, vẽ các cửa sổ, xuất ra bàn điều khiển hoặc sử dụng bộ nhớ hoặc tài nguyên bên ngoài "hộp cát" của quá trình, nó có Một tác dụng phụ. Nếu nó không có những thứ này, thì nó làm gì và tại sao tôi nên mua nó?

    Công bằng mà nói, kiểm thử đơn vị không phải là cách duy nhất để chứng minh một chương trình hoạt động; bạn có thể viết các bài kiểm tra tích hợp, mã cho các thuật toán đã được chứng minh bằng toán học, v.v. Tuy nhiên, kiểm thử đơn vị cho thấy rất nhanh, với các đầu vào A, B và C, đoạn mã này tạo ra X (hoặc không), và do đó mã hoạt động đúng (hoặc không) trong một trường hợp cụ thể. Các phép thử đơn vị có thể chứng minh với độ tin cậy cao rằng mã hoạt động như mong đợi trong mọi trường hợp và chúng cũng cung cấp một cái gì đó mà bằng chứng toán học không thể; một minh chứng rằng chương trình VẪN hoạt động theo cách nó được dự định. Một bằng chứng toán học của thuật toán không chứng minh rằng nó đã được thực hiện một cách chính xác, và nó cũng không chứng minh bất kỳ thay đổi nào được thực hiện đúng và không phá vỡ nó.

Tóm lại là, nếu đội này không thấy bất kỳ giá trị nào trong những gì DI sẽ làm, thì họ sẽ không ủng hộ và tất cả mọi người (ít nhất là tất cả các đàn anh) phải mua một thứ gì đó để thay đổi thực sự xảy ra. Họ đang tập trung vào YAGNI. Bạn đang tập trung rất nhiều vào thử nghiệm RẮN và tự động. Đâu đó ở giữa là sự thật.


1

Hãy cẩn thận thêm các tính năng bổ sung (như DI) vào dự án khi không được phê duyệt. Nếu bạn có kế hoạch dự án với giới hạn thời gian, bạn có thể rơi vào một cái bẫy không có đủ thời gian để hoàn thành các tính năng được phê duyệt.

Ngay cả khi bạn không sử dụng DI ngay bây giờ, hãy tham gia vào thử nghiệm để bạn biết chính xác những kỳ vọng để thử nghiệm tại công ty của bạn là gì. Sẽ có một dự án khác và bạn sẽ có thể đối chiếu các vấn đề với thử nghiệm của dự án hiện tại so với DI.

Nếu bạn không sử dụng DI, bạn có thể sáng tạo và làm cho mã của mình DI- "sẵn sàng". Sử dụng một hàm tạo không tham số để gọi các hàm tạo khác:

MyClassConstructor()
{
    MyClassConstructor(new Dependency)
    Property = New Dependent Property
}

MyClassConstructor(Dependency)
{
    _Dependency = Dependency
}

0

Tôi nghĩ một trong những mối quan tâm lớn nhất của họ thực tế lại ngược lại: DI không làm cho dự án trở nên phức tạp. Trong hầu hết các trường hợp, nó đang giảm rất nhiều phức tạp.

Chỉ cần nghĩ rằng không có DI, bạn sẽ có được đối tượng / thành phần phụ thuộc nào bạn cần? Thông thường đó là bằng cách tra cứu từ một kho lưu trữ, hoặc nhận được một singleton, hoặc tự khởi tạo.

2 cái trước liên quan đến mã bổ sung trong việc định vị thành phần phụ thuộc, trong thế giới DI, bạn không làm gì để thực hiện tra cứu. Sự phức tạp của các thành phần của bạn trong thực tế là giảm.

Nếu bạn đang tự khởi động bản thân trong một số trường hợp không phù hợp, nó thậm chí còn tạo ra sự phức tạp hơn. Bạn cần biết cách tạo đối tượng một cách chính xác, bạn cần biết giá trị nào để khởi tạo đối tượng thành trạng thái khả thi, tất cả những điều này tạo thêm độ phức tạp cho mã của bạn.

Vì vậy, DI không làm cho dự án trở nên phức tạp, nó làm cho nó đơn giản hơn, bằng cách làm cho các thành phần đơn giản hơn.

Một đối số lớn khác là, bạn sẽ không triển khai thực hiện khác nhau. Vâng, đúng là trong mã sản xuất, không có nhiều triển khai khác nhau trong mã sản xuất thực. Tuy nhiên, có một nơi chính cần thực hiện khác nhau: Mock / Stub / Test Double trong bài kiểm tra đơn vị. Để làm cho DI hoạt động, trong hầu hết các trường hợp, nó phụ thuộc vào mô hình phát triển dựa trên giao diện, đến lượt nó làm cho việc chế giễu / khai thác trong các thử nghiệm đơn vị có thể. Ngoài việc thay thế triển khai, "thiết kế hướng giao diện" còn giúp thiết kế sạch hơn và tốt hơn. Tất nhiên bạn vẫn có thể thiết kế với giao diện mà không cần DI. Tuy nhiên, các bài kiểm tra Đơn vị và DI đang thúc đẩy bạn áp dụng các thực hành đó.

Trừ khi "các vị thần" trong công ty của bạn nghĩ rằng: "mã đơn giản hơn", "kiểm tra đơn vị", "mô đun hóa", "trách nhiệm duy nhất", v.v ... là tất cả những gì họ chống lại, không nên có lý do gì để họ từ chối sử dụng DI.


Về lý thuyết, điều đó thật tuyệt, nhưng trong thực tế, việc thêm một thùng chứa DI là độ phức tạp bổ sung. Phần thứ hai trong cuộc tranh luận của bạn cho thấy tại sao nó đáng để làm việc, nhưng nó vẫn hoạt động.
schlingel

Trong thực tế từ kinh nghiệm trong quá khứ của tôi, DI đang GIẢM thay vì sự phức tạp. Vâng, nó có thêm một số bổ sung vào hệ thống, góp phần vào sự phức tạp. Tuy nhiên với DI, độ phức tạp của các thành phần khác trong hệ thống giảm đi rất nhiều. Cuối cùng, sự phức tạp trong thực tế giảm. Đối với phần thứ hai, trừ khi họ không thực hiện bất kỳ bài kiểm tra đơn vị nào, thì đó KHÔNG phải là công việc phụ. Không có DI, bài kiểm tra đơn vị của họ chủ yếu sẽ khó viết và duy trì. Với DI, nỗ lực giảm đi rất nhiều. Vì vậy, trên thực tế, đó là GIẢM CÔNG VIỆC (trừ khi họ không và không tin tưởng các bài kiểm tra đơn vị)
Adrian Shum

Tôi nên nhấn mạnh một điều: DI trong phản hồi của tôi không có nghĩa là bất kỳ khung DI hiện có nào. Nó chỉ là phương pháp trong việc thiết kế / phát triển các thành phần trong ứng dụng của bạn. Bạn có thể hưởng lợi rất nhiều nếu mã của bạn được điều khiển bởi giao diện, các thành phần của bạn hy vọng các phụ thuộc sẽ được chèn thay vì tra cứu / tạo. Với thiết kế như vậy, ngay cả khi bạn đang viết một số "trình tải" dành riêng cho ứng dụng thực hiện nối dây các bộ phận (không có mục đích chung DI fw), bạn vẫn được hưởng lợi từ những gì tôi đã đề cập: giảm độ phức tạp và giảm công việc trong thử nghiệm đơn vị
Adrian Shum

0

"Chúng tôi muốn giữ cho nó đơn giản, nếu có thể chỉ cần nhét mọi thứ vào một tổ hợp. DI là một sự phức tạp không cần thiết không có lợi ích".

Lợi ích của nó là thúc đẩy thiết kế các giao diện và cho phép dễ dàng chế giễu. Do đó tạo điều kiện cho thử nghiệm đơn vị. Kiểm thử đơn vị đảm bảo mã đáng tin cậy, mô-đun và dễ bảo trì. Nếu ông chủ của bạn vẫn duy trì một ý tưởng tồi, thì bạn không thể làm gì được - đó là cách tốt nhất được chấp nhận trong ngành mà họ đang tranh cãi.

Yêu cầu họ thử viết một bài kiểm tra đơn vị với khung DI và thư viện chế giễu, họ sẽ sớm học cách yêu thích nó.


Nhân đôi hoặc tăng gấp ba số lượng các lớp trong hệ thống của bạn bây giờ là những gì tôi thấy hữu ích. Điều này tương tự như cuộc tranh luận về việc cố gắng đạt được phạm vi Kiểm tra đơn vị 100% bằng cách viết một bài kiểm tra duy nhất cho mỗi phương pháp hoặc viết Bài kiểm tra đơn vị có ý nghĩa.
Andrew T Finnell

Tôi không hiểu, bạn nghĩ thử nghiệm đơn vị là một ý tưởng tốt? Nếu bạn làm, bạn cũng chế nhạo đối tượng? Điều này dễ dàng hơn với giao diện và DI. Nhưng đó dường như là những gì bạn đang tranh cãi.
NimChimpsky

Nó thực sự là vấn đề gà và trứng. Các giao diện / DI và kiểm tra đơn vị có liên quan chặt chẽ với nhau, thật khó để thực hiện cái này mà không có cái kia. Nhưng tôi tin rằng thử nghiệm đơn vị là một con đường tốt hơn và dễ dàng hơn để bắt đầu với một cơ sở mã tồn tại. Dần dần tái cấu trúc mã bùn cũ thành các thành phần gắn kết. Sau đó, bạn có thể lập luận rằng việc tạo đối tượng nên được thực hiện với khung DI thay vì newing ở mọi nơi và viết các lớp nhà máy vì bạn có tất cả các thành phần này.
Spoike

0

Bạn có làm việc với những người này trong bất kỳ dự án nhỏ hơn, hoặc chỉ một dự án lớn? Thật dễ dàng để thuyết phục mọi người thử một cái gì đó mới trong một dự án thứ cấp / đại học hơn là nhóm / công ty bánh mì và bơ. Những lý do chính là nếu nó thất bại, chi phí loại bỏ / thay thế nó nhỏ hơn rất nhiều và việc đưa nó đi khắp mọi nơi trong một dự án nhỏ sẽ tốn ít công sức hơn nhiều. Trong một cái lớn hiện có, bạn có một chi phí trả trước lớn để thực hiện thay đổi ở mọi nơi cùng một lúc hoặc một giai đoạn mở rộng trong đó mã là hỗn hợp của cách tiếp cận cũ / mới thêm ma sát vì bạn phải nhớ cách mỗi lớp được thiết kế làm việc.


0

Mặc dù một trong những điều thúc đẩy DI là thử nghiệm đơn vị, nhưng tôi tin rằng nó thêm lớp phức tạp trong một số trường hợp.

  • Tốt hơn để có một chiếc xe khó kiểm tra, nhưng dễ sửa chữa hơn xe dễ kiểm tra và khó sửa chữa.

  • Ngoài ra, đối với tôi, nhóm thúc đẩy DI chỉ trình bày ý tưởng của họ thông qua ảnh hưởng rằng một số phương pháp thiết kế hiện có là xấu.

  • nếu chúng ta có một phương thức làm 5 chức năng khác nhau

    DI-People nói:

    • không tách rời mối quan tâm. [vấn đề đó là gì? họ đang cố gắng làm cho nó trông tệ đi, mà theo logic và lập trình thì tốt hơn hết là bạn nên biết những gì đang làm chặt chẽ để tránh xung đột và kỳ vọng sai lầm và để thấy tác động của mã thay đổi dễ dàng, bởi vì chúng tôi không thể làm cho tất cả các bạn các đối tượng không liên quan với nhau 100% hoặc ít nhất chúng tôi không thể đảm bảo điều này {trừ khi tại sao kiểm tra hồi quy lại quan trọng?}]
    • Phức tạp [Họ muốn giảm độ phức tạp bằng cách tạo thêm năm lớp nữa để xử lý một hàm và lớp bổ sung (Container) để tạo lớp cho hàm cần thiết bây giờ dựa trên các cài đặt (XML hoặc Từ điển) ngoài triết lý "để có mặc định / hoặc không "thảo luận, ...] sau đó họ chuyển sự phức tạp sang vùng chứa và đến cấu trúc, [với tôi trông giống như việc di chuyển phức tạp từ nơi này sang nơi khác với tất cả sự phức tạp của các đặc điểm ngôn ngữ để xử lý việc này. ]

Tôi tin rằng tốt hơn là tạo ra mẫu thiết kế riêng của chúng tôi phù hợp với nhu cầu kinh doanh hơn là chịu ảnh hưởng của DI.

có lợi cho DI, nó có thể giúp ích trong một số trường hợp, ví dụ: nếu bạn có hàng trăm triển khai cho cùng một Giao diện phụ thuộc vào bộ chọn và các triển khai này khác nhau rất nhiều về logic, trong trường hợp này tôi sẽ sử dụng các kỹ thuật tương tự DI hoặc DI. nhưng nếu chúng ta có một vài triển khai cho cùng một giao diện thì chúng ta không cần 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.