2

I'm writing a handy library (we'll call it Thinger) that goes off and fetches an XML document, does some X-Path query on it and does something helpful with the result of that. (What I'm actually doing is far too boring to bother you all with, this is just a simplified example.)

Because I'm a wise and lazy programmer I'm making use of two third-party components, one for fetching remote XML documents (we'll call it Fetcher) and one for running X-Path queries (we'll call it Querier).

My library provides a Thinger class, into which one must inject a Fetcher and a Querier. I could do this via setters or a constructor.

But then I think about the poor people using my library, who now have to think about injecting my dependencies when all they really want to do is call something like

new Fetcher()->fetch(someurl);

So far, I have written a static factory which instantiates a new Thinger, Fetcher and Querier, assembles them as appropriate and returns the Thinger.

That left me feeling slightly unclean.

Surely there's a better way?

EDIT

Most frameworks etc would probably get around this using a Dependency Injection Container or similar, but since I'm writing a fairly small third party library that seems like a bad approach.

3 Answers 3

7

As Dependency Inversion seems to get more and more popular, I would go for a dual approach.

  1. Design your components to be used with a Dependency Injection Container, if possible for use with an arbitrary one so you don't constrain your users in their choice.
  2. As a convenience option, also provide a factory(-method) for creating a Thinger with the default Fetcher and Querier.
1
  • 1
    I feel better about my factory method now, thanks.
    – Jez
    Commented May 10, 2013 at 16:49
4

What's wrong with providing a nice clean default implementation for the common scenario while allowing an injected version for people who want that flexibility?

As long as your default implementation doesn't put undo constraints on usage (like manually deleting the Fetcher and Querier) or your default implementation is only common for the minority, that seems perfectly fine.

1

Use an inversion of control container. In .NET this includes Castle Windsor or NInject

You can just specify which components you need in the constructor, and you can get an object like this

IThinger thinger = container.Resolve<IThinger>();
thinger.DoTheStuff();

The code above doesn't care about which implementation of IKing you have, what dependency must be injected, etc.

It doesn't need a lot of setup or complicated configuration. Normally, you need to write only one method or one file where you register all your services (like Thinger, Fetcher) and initialize the container with that registration

1
  • Hmmm... from what I've just been reading it seems like an inversion of control container is another name for a dependency injection container, which may well be the only viable solution. I'm really just keen to avoid the users of the library having to write any setup code. Seems like some sort of factory/DIC/IOCC is probably the way to go, though.
    – Jez
    Commented May 10, 2013 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.