質問

I find that fairly frequently in my code I do this (using Guice as my DI framework):

public class SomeObserver implements IObserver {
    @Inject
    SomeObserver(IObservable observable) {
        observable.subscribe(this);
    }
    // Snip
}

It occurred to me recently that, when testing, I am now required to pass at least a mock into my program, which is not necessarily the worst thing, but it does depend on at least binding a dependency to that IObservable interface. Another option would be to, in production, do this:

public class SomeModule extends AbstractModule {
    // snip

    @Provides
    protected SomeObserver provideSomeObserver(IObservable observable) {
        SomeObserver newObject = new SomeObserver();
        newObject.subscribe(observable);
    }
}

Then in testing, I don't have to even have a reference to the Observable. However, if I ever want to change the constructor, the module must change as well (which it doesn't in the first example).

Which is better? Or is there an even better third option?


Update: I want to talk about my use case a bit.

Consider a data processing application, where a data source is the Observable. I don't want the data source to know about other parts of the system (Separation of Concerns). The data is filtered into at least three different Observers, who work on independent tasks. I want to keep the data source swappable - for testing, separation of concerns, etc. reasons, so the data source just implements what I've defined to be a Subscribable<Observer> interface, and then you can just call .subscribe(this).

Then, I use dependency injection and modules to determine exactly how the wiring is going to be. This solution also allows me to decorate observables if I choose, using annotations to clarify the injections.

So, essentially, I'm using Dependency Injection to manage the wiring, which is exactly what I originally thought it was for; creating, say, an ObservationManager seems like a lot of boilerplate for little gain. But again, I may be missing something.

役に立ちましたか?

解決

It looks like you're kind of misusing dependency injection.

Dependency injection, as its name suggests, intends to resolve a problem with resolving class dependencies. But semantically observer and observable are not dependent on each other. They really should not be treated as dependencies.

Setting up observer-observable relationship is a separate task by itself, so ideally you should have a third entity which depends on observer and observable and sets up a relationship between them. Using event bus looks pretty orthogonal in this case because it still boils down to subscription, and subscription should be done somewhere.

In fact that you have noticed that it is weird to use mocks in this case is a signal that you're trying to use as a dependency something which is not a dependency at all. For normal dependencies (which are used by the class directly) it is perfectly OK to provide mock objects, they're intended exactly for that after all.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top