Too much dependencies may indicate that the class itself is doing too much. In order to determine if it's doing too much:
By looking at the actual dependencies, I don't see anything which would be indicative of bad things happening:
IDbContextFactory - creating the context for the database.
OK, we are probably inside a business layer where classes interact with data access layer. Looks fine.
IMapper - Mapping from entities to domain models.
It's difficult to tell anything without the overall picture. It might be that the architecture is wrong and the mapping should be done directly by the data access layer, or it may be that the architecture is perfectly fine. In all cases, it makes sense to have this dependency here.
Another choice would be to split the class in two: one dealing with mapping, the other one dealing with the actual business logic. This would create a de facto layer which will separate further the BL from the DAL. If mappings are complex, it could be a good idea. In most cases, though, it would just add useless complexity.
IClock - Abstracts DateTime.Now to help with unit tests.
It is probably not very useful to have a separate interface (and class) just to get the current time. I would simply pass the DateTime.Now
to the methods which require the current time.
A separate class may make sense if there is some other information, like the timezones, or the date ranges, etc.
IPerformanceFactory - measures the execution time for specific methods.
See the next point.
ILog - Log4net for logging.
Such transcendent functionality should belong to the framework, and the actual libraries should be interchangeable and configurable at runtime (for instance through app.config in .NET).
Unfortunately, this is not (yet) the case, which let you either pick a library and stick with it, or create an abstraction layer to be able to swap the libraries later if needed. If your intention is specifically to be independent of the choice of the library, go for it. If you're pretty sure that you'll continue using the library for years, don't add an abstraction.
If the library is too complex to use, a facade pattern makes sense.
ICollectionWrapperFactory - Creates collections (that extends IEnumerable).
I would assume that this creates very specific data structures which are used by the domain logic. It looks like a utility class. Instead, use one class per data structure with relevant constructors. If the initialization logic is slightly complicated to fit in a constructor, use static factory methods. If the logic is even more complex, use factory or a builder pattern.
IQueryFilterFactory - Generates queries based on input that will query db.
Why isn't that in the data access layer? Why is there a Filter
in the name?
IIdentityHelper - Retrieves the logged in user.
I'm not sure why is there a Helper
suffix. In all cases, other suffixes won't be particularly explicit either (IIdentityManager
?)
Anyway, it makes perfect sense to have this dependency here.
IFaultFactory - Create different FaultExceptions (I use WCF).
Is the logic so complex that it requires to use a factory pattern? Why is Dependency Injection used for that? Would you swap the creation of exceptions between production code and tests? Why?
I would try to refactor that into simple throw new FaultException(...)
. If some global information should be added to all the exceptions before propagating them to the client, WCF probably has a mechanism where you catch an unhandled exception and can change it and re-throw it to the client.
Measuring the quality by numbers is usually as bad as being paid by lines of code you write per month. You may have a high number of dependencies in a well-designed class, as you can have a crappy class using few dependencies.
Lots of dependencies make the logic more difficult to follow. If the logic is difficult to follow, the class is probably doing too much and should be split.
Best Answer
Dependency Injection simply helps define how one object knows about another dependent object. It is not going to help you reduce the overall complexity of the system. If you needed tens of import before DI, you will still need tens of imports after. The difference is that these imports will be in a location (class) that makes more sense (factory, builder, etc).
By allowing dependencies to be provided through a constructor or method you allow yourself the flexibility to supply a different, yet still valid, dependent object to your class and increase cohesion of said class by removing concerns.
There are several principles that are similar and are often used together: Dependency Injection (DI), Inversion of Control (IoC), and the Dependency Inversion Principle (DIP)
From this article http://martinfowler.com/articles/dipInTheWild.html