2010-03-21 39 views
16

Vì vậy, công ty của tôi sử dụng Castle Windsor IoC container, nhưng theo một cách mà cảm thấy "off":Chúng ta có đang sử dụng IoC một cách hiệu quả không?

  • Tất cả các kiểu dữ liệu đã được đăng ký trong mã, không phải là tập tin cấu hình.
  • Tất cả các loại dữ liệu đều được mã hóa cứng để sử dụng một triển khai giao diện. Trong thực tế, đối với gần như tất cả các giao diện nhất định, có và sẽ chỉ bao giờ được thực hiện một.
  • Tất cả các kiểu dữ liệu đã đăng ký đều có hàm khởi tạo mặc định, vì vậy Windsor không tạo biểu đồ đối tượng cho bất kỳ loại đăng ký nào.

Những người thiết kế hệ thống này nhấn mạnh container IoC làm cho hệ thống tốt hơn. Chúng tôi có hơn 1200 lớp học công khai, do đó hệ thống lớn của chúng tôi là loại mà bạn muốn mong đợi để tìm một khuôn khổ như Windsor. Nhưng tôi vẫn hoài nghi.

Công ty của tôi có sử dụng IoC hiệu quả không? Có một lợi thế cho các đối tượng mới với Windsor hơn các đối tượng mới với từ khóa new không?

Trả lời

23

Câu trả lời ngắn: Không, công ty của bạn không sử dụng DI hiệu quả.

Câu trả lời dài hơn một chút: Vấn đề chính là tất cả các lớp có nhà thầu mặc định. Khi đó là trường hợp, sau đó làm thế nào để bạn giải quyết phụ thuộc?

phụ thuộc Hoặc nhà thầu của bạn đã mã hóa cứng như thế này:

public Foo() 
{ 
    IBar bar = new Bar(); 
} 

Trong trường hợp mà bạn không thể thay đổi phụ thuộc mà không cần biên dịch lại ứng dụng đó.

Thậm chí tệ hơn, họ có thể sử dụng Static Service Locator anti-pattern:

public Foo() 
{ 
    IBar bar = Container.Resolve<IBar>(); 
} 

Một DI container sẽ giải quyết toàn bộ đồ thị phụ thuộc vào ứng dụng của Composition Root và thoát ra khỏi đường đi.

Nói chung tốt hơn nên sử dụng Công ước qua Cấu hình bằng cách sử dụng cách tiếp cận heuristic trong mã để định cấu hình vùng chứa. Cấu hình XML nên được dành riêng cho một vài trường hợp mà bạn cần để có thể cấu hình lại các phụ thuộc mà không biên dịch lại, mà chỉ nên là một tập con nhỏ. Tóm lại, tôi thấy không có vấn đề cố hữu với cấu hình container trong mã. Trong thực tế, đó là cách tiếp cận ưa thích.

Chỉ có một triển khai cho mỗi giao diện cũng không phải là vấn đề. Đó là một sự khởi đầu, và nếu ứng dụng được kết hợp lỏng lẻo, đó là cửa sổ mở liên tục của cơ hội. Sớm hay muộn bạn sẽ rất có khả năng giới thiệu các triển khai thay thế, nhưng bạn tốt nhất có thể làm điều này nếu các giao diện đã sẵn sàng và toàn bộ cơ sở mã tuân theo Liskov Substitution Principle.

+0

+1, + câu trả lời: có vẻ như bạn đã đóng đinh nó. Lúc đầu, tôi nghĩ IoC đã thêm một lớp không cần thiết của mã hóa, khi thực tế vấn đề thực sự là chúng ta không thực sự quản lý các phụ thuộc một cách chính xác.Và có, chúng tôi thực sự có một lớp tĩnh gọi là ServiceLocator, và về cơ bản nó được sử dụng như một sự thay thế cho các nhà xây dựng. Bài viết của bạn đã được chuyển tiếp xung quanh và tôi hy vọng sẽ thấy một số cải tiến trong tương lai không xa. Nhiều đánh giá cao :) – Juliet

+4

Mark quá khiêm tốn để đề cập đến nó, nhưng bạn cũng có thể kiểm tra các cuốn sách ông viết về chủ đề này rất: http://manning.com/seemann –

+0

+1 - câu trả lời này bao gồm các khía cạnh chính xác, tôi xóa câu trả lời của tôi – Sunny

3

Tất cả các loại dữ liệu được đăng ký trong mã chứ không phải tệp cấu hình.

Theo loại dữ liệu tôi đoán bạn có nghĩa là các ràng buộc. Ví dụ: IFoo phải bị ràng buộc với Foo. Nếu đây là trường hợp, đó là tốt. Trong thực tế, điều này là tốt hơn nhiều trong nhiều mắt người (bao gồm tôi) hơn chỉ định các ràng buộc thông qua XML. Lợi ích tự nhiên ở đây là tại thời điểm kiểm tra biên dịch được thực hiện. Bạn sẽ không được lập trình bằng XML như họ nói.

Tất cả các loại dữ liệu đều được mã hóa cứng để sử dụng một triển khai giao diện. Trên thực tế, cho gần như tất cả các giao diện nhất định, có là và sẽ chỉ bao giờ là một thực hiện .

Bạn có chắc chắn không? Nếu vậy, này có thể là mùi. Tuy nhiên bạn đã tuyên bố đó là một ứng dụng lớn. Nếu có bất kỳ thử nghiệm đơn vị nào (hoặc kiểm tra tự động) đang diễn ra, việc có một giao diện cho mỗi triển khai là hoàn toàn hợp lệ.

Công ty của tôi có sử dụng IoC hiệu quả không? Có lợi thế gì khi new'ing đối tượng với Windsor so với new'ing đối tượng bằng từ khóa mới?

Có, từ những gì tôi có thể thu thập. Đối với bất kỳ hình thức kiểm tra tự động nào, việc tạo ra một sự phụ thuộc trong một đối tượng là một điều xấu phải làm. Bằng cách sử dụng một thùng chứa IOC, việc kết nối các lớp phức tạp có thể bị loại bỏ khi thực sự kết nối mã sản xuất với nhau. Điều này giúp đơn giản hóa ứng dụng và cho phép bạn làm nhà phát triển tập trung vào các tính năng và các tác vụ khác, thay vì đảm bảo toàn bộ điều thực sự xây dựng.

Ngoài ra, bằng cách đảo ngược kiểm soát của bạn, việc thực hiện thay đổi đối với các phần mô-đun của ứng dụng rất dễ dàng. Ví dụ, hãy tưởng tượng nếu bạn muốn chuyển đổi một mô-đun cho một phiên bản tốt hơn. Với các thùng chứa IOC, bạn chỉ cần sửa đổi một hoặc hai dòng liên kết.Nếu không có IOC, bạn phải tự di chuyển qua ứng dụng và đảm bảo rằng nó được kết nối nội bộ một cách chính xác.

Đây là câu hỏi hay liên quan đến điểm cuối cùng của bạn, trên why you should use IOC qua các phương pháp thủ công chuyển tiếp thẳng.

+0

Có, chúng tôi có rất nhiều bài kiểm tra. Và thực sự từ vẻ ngoài của nó, chúng tôi sử dụng IoC cho một số ít các loại ở một số nơi, và tiêm phụ thuộc thủ công ở những nơi khác. Vì vậy, ngay bây giờ mã của chúng tôi đang bị xử lý không phù hợp của phụ thuộc - lý tưởng tôi muốn sử dụng Windsor cho hầu hết hoặc tất cả các instantiations quan trọng, hoặc ruột nó hoàn toàn. Tôi không chắc chúng tôi sử dụng nó bao nhiêu trong thử nghiệm, tôi sẽ phải liên hệ lại với bạn về điều đó :) – Juliet

+1

Một hoặc khác theo ý kiến ​​của tôi. Thực tế bạn đang sử dụng một container IOC, ít nhất bạn nên sử dụng nó để nó đầy đủ nhất. Liên quan đến việc sử dụng một thùng chứa IOC để thử nghiệm, bạn có thể, nhưng bạn không phải. Trong thực tế, tôi không sử dụng IOC cho mã thử nghiệm đơn vị, ưu tiên cho việc giải phóng các phụ thuộc của tôi. – Finglas

0

Hai vấn đề đầu tiên của bạn không phải là vấn đề thực sự (Finglas mô tả lý do tại sao).

Tôi sẽ xem xét "Tất cả các kiểu dữ liệu đã đăng ký có hàm tạo mặc định" là một mã (giả sử lớp đang tải phụ thuộc trực tiếp từ vùng chứa IoC của bạn). Khi điều này xảy ra hoặc là 1) một điểm vào ứng dụng thích hợp để lấy đối tượng từ thùng chứa Ioc của bạn (vì bạn có thể cần phải khởi tạo IOC container đó), hoặc 2) một nơi bạn có thể sử dụng một nhà máy thay thế.

Có một hàm tạo mặc định điền vào các phụ thuộc không được khuyến khích. Lý do bạn đang sao chép kiến ​​thức về cách tạo lớp. Lý tưởng nhất là mỗi lớp không nên biết nơi chứa IoC của bạn - đó là công việc của điểm vào ứng dụng của bạn.

Có vẻ như việc sử dụng IoC ở công ty bạn không phải là tổng thể xấu.

1

tôi chắc chắn rằng những người khác sẽ gửi câu trả lời chi tiết hơn nhưng đây là những gì tôi đã có:

Tất cả các kiểu dữ liệu đã được đăng ký trong mã, không phải là tập tin cấu hình.

Có xu hướng trong (at least some) Khung công tác IoC/Dependency Injection để đăng ký phụ thuộc của bạn bằng cách sử dụng mã thay vì Cấu hình XML. Lợi ích chính là bạn biết tại thời gian biên dịch nếu một cái gì đó có dây sai hay không. Ví dụ: nếu bạn quyết định thêm/xóa đối số hàm tạo thì mã của bạn sẽ không thực sự biên dịch khi cấu hình của bạn không đồng bộ (và nó vẫn giữ lỗi chính tả như là ngoại lệ tham chiếu null ngẫu nhiên khi chạy).

Tất cả các loại dữ liệu đều được mã hóa cứng để sử dụng một triển khai giao diện. Trong thực tế, đối với gần như tất cả các giao diện nhất định, có và sẽ chỉ bao giờ được thực hiện một.

Tôi không thực sự chắc chắn ý bạn là gì bởi "một triển khai giao diện". Nếu bạn có nghĩa là giao diện là downcast cho các đối tượng thực hiện chúng, thì đó chắc chắn không phải là kosher. Nếu không thì có một lợi ích để mã hóa cho một giao diện thay vì thực hiện cụ thể. Một trong những chính rõ ràng là có khả năng sử dụng các đối tượng giả ủng hộ giao diện cho biết trong thử nghiệm đơn vị. Lập trình cho một giao diện (theo lý thuyết) buộc bạn phải làm cho mã của bạn được kết hợp lỏng lẻo hơn, có thể giúp kiểm tra. Nó cũng mở ra một số tùy chọn thiết kế thực sự thú vị như thế này Build a generic typesafe DAO with Hibernate and Spring AOP.

Tất cả các loại dữ liệu đã đăng ký đều có hàm tạo mặc định, do đó Windsor không biểu thị đối tượng cho bất kỳ loại đăng ký nào.

Điều này cũng không hẳn là điều xấu. Tôi nghĩ nói chung quy tắc của ngón tay cái là nếu một phụ thuộc là rất quan trọng cho lớp của bạn để thực hiện chức năng của nó, sau đó tiêm constructor nên được sử dụng. Nếu không (ghi nhật ký có lẽ là ví dụ được sử dụng nhiều nhất về điều này) thì việc tiêm thuộc tính là một lựa chọn thích hợp hơn. Mặc dù tôi không quen thuộc với Castle Windsor, tôi biết ít nhất một số container Java IoC không hỗ trợ việc xây dựng các phiên bản đầu tiên (nếu ai đó quen thuộc hơn với Castle Windsor có thể bình luận về điều này, điều đó thật tuyệt vời).Nếu Castle Windsor không có tính năng này trong các phiên bản trước đó, điều đó cũng có thể dẫn đến thiết kế mà bạn đang thấy trong hệ thống của mình.

Theo như sử dụng IoC và gọi new ở mọi nơi, điều đó cũng tùy thuộc vào cách sử dụng. Một vài dự án tôi đã làm việc dựa trên rất nhiều vào IoC (Spring in Java và Autofac in .NET), kết nối tất cả các phụ thuộc của tôi ở một nơi cho phép chúng tôi thử nghiệm khá nhanh chóng và dễ dàng với cấu trúc và cấu trúc đối tượng.

+0

+1 về lợi ích thời gian biên dịch của cấu hình so với xml - Tôi bỏ lỡ điều đó trong bình luận của tôi – Sunny

+0

Castle Windsor hỗ trợ phép xây dựng –

+0

@Frank Schwieterman Tôi đã tìm kiếm xem nó có hỗ trợ việc xây dựng tiêm bây giờ =) không. Tôi có nghĩa là nó đã hỗ trợ xây dựng tiêm từ việc ăn xin hoặc là nó một tính năng đã được thêm vào trong một phiên bản sau này. – R0MANARMY

Các vấn đề liên quan