views:

31

answers:

1

We have many long-running processes that each require dozens of steps. Each step is relatively complex in its own right, so we broke those steps into their own classes. We are using DI/IoC (StructureMap) to help us make the whole thing testable. This has been working great, but we find ourselves with oodles of dependencies in our controlling classes.

For example, on of our larger routines processes client 401k file uploads. This has almost 70 discrete steps. Each logical group of steps is in its own class, 14 in all. Each of those are pretty small and manageable, but the class that organizes the whole affair has a ton of dependencies (i.e. we have a bunch of God classes):

    public Client401kProcessor (IValidator uploadValidator, 
        IGeneralLedgerExporter glExporter, 
        IDataMapper dataMapper,
        IFinanceRepository financeRep,
        //...9 more
        IClientFileAuditor auditor)
    {
        _uploadValidator = uploadValidator;
        //... etc
    }

This particular class only has a couple public functions, making it very easy to use:

    public void ProcessClientFile(Guid savedFileId)
    {
        var clientUpload = _financeRep.FetchClientFile(savedFileId);
        _uploadValidator.Validate(clientUpload);
        _dataMapper.MapToStagedArea(clientUpload);
        _dataMapper.FlagAsStaged(clientUpload.Id);
        //...
        _auditor.RecordChanges(client.Id);
    }

I feel like we must be missing something. It's pretty straightforward to test, understand, and write the above code ... but .NET folks have been telling us that we have too many dependencies. How would we reduce these dependencies and still make the code easy to test/maintain?

A: 

As Aren says in his comments, you can introduce an aggregating service - a middle man that takes care of the coordination for a set of dependencies. The first question you have to ask yourself before doing this is what the responsibility of the class with all those dependencies is. Is it really having a single responsibility?

Read Jeffrey Palermos blog post on the "constructor over injection" code smell and follow the discussions and the follow up posts it caused. Mark Seeman posted a couple of follow ups, including "Refactoring to Aggregate Services", which is a good read in your case.

In your specific case, the ProcessClientFile method could perhaps be extracted into a ClientFileProcessor class, or a couple of classes if the file processing consists of several logical steps with discreet responsibilities.

PHeiberg