views:

28

answers:

1

Hi,

We are using StructureMap as our Dependency Injection (DI) framework while we are creating a layered library. Our goals are to:

  • Make it easy for us to Unit Test classes (and using mock classes instead of the real dependencies) while we develop and maintain the library.
  • Make it easy for the library user to:
    • Customize the library behavior by implementing an interface them selfs and configuring the library to use their implementation instead of our own.
    • Unit Test their implemented classes (it's the same goal we have internally, but we want it to be fulfilled for the library user as well).

By layered library, we mean that we are building two DLL`s:

  1. The core library. It should be usable from any .NET application, be it a Console application or an MVC one.
  2. A WebForms library. It includes the core library but also provides WebForms Control`s to make life easier for WebForms users.

Our questions:

  1. Where should we call the code to map interfaces with concrete classes for the core library? It has no single entry point, there are numerous classes which may be instantiated first.

    Currently we force the user to call DependencyHandler.Init() before doing any other library call. Is there a nicer way, like a piece of code which gets executed after loading the DLL so that we won't force the user to write one line of boiler-plate code?

  2. Which is the recommended way to let library users change an interface implementation into their own type? Currently the user may retrieve the Registry by StructureMap.Configuration.DSL.Registry theRegistry = DependencyHandler.Instance().GetConfiguration() and then change things by for example theRegistry.For<IFoo>().Use<MyOwnFooImplementation>(); Would it be nicer to use XML? And if so, where should we put said XML? We choose the programmatic approach as Visual Studio will be able to give the user some help.

  3. If the current approach in 2 above is used, the library user is required (at least now) to add a Reference to StructureMap.DLL as well as to our DLL. Could we remove that burden from the user, maybe by using XML for dependency setup instead?

  4. Is there a nice central location in WebForms we should use, which solves problem 1 for the WebForms library DLL?

  5. How do you recommend we structure things for production and test?

    The current idea is to use DI in all places necessary to enable Unit Testing where we and supposedly our users want it, as well as enabling the users to change the library behavior by providing their own implementations.

    To test things, we and the library users will have to create mock classes to replace dependencies we want to break away. The idea is that we use the normal configuration but override the classes we want to mock instead of using their normal implementation. Is that a good way to proceed?

+1  A: 

It's important to note that in order to provide an API from which others can isolate their code you need to make sure that they can depend on abstractions rather than concrete implementations. That is, as long as the classes that you exposes that "do stuff" either implements an interface (usually best), inherits from an abstract class which defines the interface or have all their public members as virtual (usually worst) I, as a consumer of your API, is able to isolate my code from your concrete implementations. In other words, you using an IoC-container in it self isn't key to providing a testable API. But making your classes non-static and as implementations of abstractions is. Using a container has many other benefits though. For instance you will probably have a much easier time testing the various classes in your API yourselves :)

  1. There is no single entry point, but to use your API I would instantiate one or several classes right? Each of those classes could have constructors which require the client to provide concrete implementations of the abstractions on which the class is dependent. To avoid forcing clients to specify which implementations to use you could also provide parameterless constructors which use the default implementations.

  2. It depends, but anything from your approach to a simple DSL for wiring up the API to configuration files can be fine. In general though, as I said before, clients probably wont be very interested in changing the implementations that your classes depend upon as long as they themselves can isolate their own code from your "top-level" classes.

  3. Application start is probably a good place for this. The Web Forms library could be an HttpModule or you could provide default boot strapping and instruct clients to make any changes that they need to make in the application start event in global.asax.

  4. Sounds good. Like I said before, I think the most important thing is that your classes and their methods aren't static (and preferably not singletons) and that their interfaces is defined in an abstract way, thus enabling people to provide use other concrete implementations for testing.

I might have misunderstood a few things, but I hope my answers might help at least a little :)

Joel Abrahamsson