Вопрос

This is going to be a tough question to describe, but here goes.

We are using the Delphi Spring Framework. (http://code.google.com/p/delphi-spring-framework/)

Let's say I have UnitA that declares InterfaceA which is implemented by ClassA.

Similarly, I have UnitB that declares InterfaceB which is implemented by ClassB.

Both registered their interface and their class with the Spring Container in their respective initialization sections.

InterfaceA has a dependency on InterfaceB, but because we are using Spring, UnitA doesn't have UnitB in its uses clause. In other words, we've done our job -- we've decoupled UnitA and UnitB, but we still are able to have InterfaceA depend on InterfaceB.

However, given the above scenario, we need to make sure that both UnitA and UnitB are included in the project so that the dependencies can be resolved.

Imagine, now, that we start a new project. That new project uses UnitA, but the developer doesn't realize that if one is to use UnitA, one also has to include UnitB in the project. There will be no compiler error, because the dependency is resolved at run time, not compile time.

And herein lies the question: What is the right way to ensure that this dependency on UnitB is known before the app gets deployed?

We can foresee a situation in a complex app where, despite thorough testing, a given code path isn't executed possibly for a long time, and this missing dependency isn't discovered before deployment.

We've implemented a system where each interface resolution call is accompanied by a Requires call that checks and raises an exception at startup, ensuring we'll see the error. But we are wondering if there is a "best practice" or standard way to detect this or otherwise deal with this issue.

Added: Is this an issue in Java and other languages?

Это было полезно?

Решение

I'm a little confused. Its the use of interfaces that gives you loose coupling not an IoC container. Its only natural that UnitA would use UnitB if that's where InterfaceB is declared.

The implementations of the interfaces is a different story. Those would need references to the interfaces they implement and any interfaces they make use of but should not have references to any other implementations.

I've not used Spring for Delphi but I'm familiar with other IoC containers. If it behaves similarly then you are registering an interface along with an implementation of it. When you call resolve you are passing in either the interface's name or some other information (type info) about the interface and expecting the IoC container to return a reference to the interface you requested. Which implementation is behind that interface is determined by which ones were registered and what rules are in place for resolving the request.

If the interface you requested was never registered you get an exception. Some IoC containers can resolve entire chains of dependencies with a single call.

You're asking for a way to determine at build time whether a dependency will be resolved at runtime but the dependencies aren't registered until runtime. I don't think that can be guaranteed no matter what tool you use.

UnitA should include UnitB in its uses clause. The implementations of the interfaces in UnitA and UnitB could and probably should be located in units separate from A and B, especially if there is more than one implementation of each interface.

The developer that uses UnitA in a project would be then be forced to include UnitB in the project as well. If they are using test driven development in the new project they would find out pretty quickly that they need to provide implementations (even if they are only mocks) for both InterfaceA and InterfaceB for their tests to pass.

Quite frankly, if a critical dependency is overlooked and the project gets deployed without it then the tests weren't thorough enough. Unit tests might not catch this but this is exactly what a suite of integration tests would normally catch.

I would recommend something like Fit or Fitnesse for integration testing (though I'm not sure how mature the Fit4Delphi project is). The tests can be written by anyone who can write a word document or edit a wiki and the developer just has to write classes that allow the tests to drive the production code. If setup correctly you can run most of the integration tests against the actual release version of the project.

Другие советы

You need to use a dependency management solution like Maven or Ivy. Once you do this, you will be able to say that UnitA depends on UnitB and once someone adds the UnitA as a dependency, the tool (either Maven or Ivy) will be forced to download the dependency and include it in your project.

Maven itself has an Eclipse plugin that is able to detect even if you already have the other project at your current workspace.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top