views:

91

answers:

6

Let's say that I'm currently designing an application where I will need to use a global timing system (it's a cross-cutting concern). I'll need to access data from that global timing system from basically anywhere in my app and it's not like I can see that "this part of the application will need it while the other won't".

My question is.. should I design that as a kind Ambient Context (in this case, Singleton), or should I try to devise other way to accomodate for this?

I certainly don't feel it's correct to make all my classes have to get this global timing class passed to them by constructor injection. Lot's of time I would have to pass the reference really down the chain until some class eventually needs it. On the other hand, it would turn everything more clear from the reading stand point(it makes it clear what my classes' dependencies are).

How do people generally deal with this? Are there any other techniques around that can help with this? AOP maybe?

PS: The global timing system was just an idea I took from a book I'm currently reading. A logging system would be another good example of this kind of problem.

Thanks

A: 

If everybody needs it and it's a one of a kind (just like the log you mentioned), it's definitely a singleton.

Michael Clerx
A: 

I think you are right, that some types are just not appropiate for constructor injection; and some times you need to keep track of one context of some sort in a broader way than within a set of objects.

When I face this problem, I will often create a Singleton, but have the initialization logic call the dependency injection framework to do the actual instantiation. This leads to coupling on a specific static method (and some will oppose to this) - but at the same time I am free to change the implementation whenever I feel like it (and perhaps for some types have a different implementation in the test project, or something). And I get the benefit of not having to pass around a very common type between all the objects constructors.

Of course, you should only do this, when the type really is needed in a lot of places. Otherwise, use normal constructor injection. Exactly when "it's okay" is up to you to decide.

driis
"but have the initialization logic call the dependency injection framework to do the actual instantiation" that is indeed a good idea.
devoured elysium
A: 

A static singleton class is the way that I see this dealt with most of the time. Using logging as a more commonly seen cross-cutting concern, I always see my logging calls looking like this:

public class SomeClassThatDoesStuff
{
    private static readonly ILog log = 
          LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    public void DoStuff()
    {
         log.Info("Doing something");
    }
}

You're global time class would seem like a similar type of cross-cutting concern and I'd approach it the same way

I agree that doing it with DI is going to be tedious and not terribly pragmatic.

Dave White
+2  A: 

As you suggest, Aspect Oriented Programming (AOP) is designed with just this sort of thing in mind, so I'd certainly check that out.

While constructor injection does seem a hassle in this scenario, using an IOC container might help reduce your pain a bit. A singleton does seem to fit the bill well, but they bring issues with testability due to the staticness - but you can get round this by splitting it into two.

Grant Crofton
How is that about splitting it into 2?
devoured elysium
@devoured - it's something I read in Roy Osherove's 'Art of Unit Testing', about having the factory part of the singleton separate from the static part so you can replace it in tests to return what you like. This has a little about it: http://weblogs.asp.net/rosherove/archive/2007/06/10/tips-for-testable-code-and-for-testing-legacy-code.aspx
Grant Crofton
A: 

What I did with aop:


public abstract aspect AutoInjectAspect<T> {

    /**
     * Implemented by the concrete class to decide what value to return.
     * @param joinPoint
     * @return
     */
    abstract public T getInjectedValue(JoinPoint joinPoint);

    protected pointcut autoInjectField() : get(@AutoInject T *);

    /**
     * override the "get" of the otherwise null value with the 
     *   value to be injected
     * @return the injected field
     */
    T around(): autoInjectField() {
        return getInjectedValue(thisJoinPoint);
    }
}

And then made a concrete aspect:


public aspect SLF4jLoggerInjector extends AutoInjectAspect<Logger> {
    @Override
    public Logger getInjectedValue(JoinPoint joinPoint) {
        Class classInjected = joinPoint.getStaticPart()
                .getSignature().getDeclaringType();
        Logger logger = LoggerFactory.getLogger(classInjected);
        return logger;
    }
}

Then make a annotation "@AutoInject" and put that on the field you want to inject into.

That being said, you could also the IOC container route.

Jeff Walker
+1  A: 

Regardless of whether you implement it as a singleton I still recommend you pass it around by dependency injection. I also recommend you don't implement something as singleton yourself and defer to a DI framework giving you a singleton context that any first class IOC library will do.

Chris Marisic