mercredi 25 juillet 2018

Constructor over-injection and Facade Service concept

I have a pretty simple interface which manages the update of business proposals, specifically during a nightly batch process each record is submitted here (but it might be used in other scenarios). This interface is used inside an EJB 2.0 Bean, which fetches records and "cycles" them. Beware names are translated from Italian to English so pardon possible errors. I also simplified some concepts.

public interface ProposalUpdateService {
    void updateProposal(final ProposalFirstType proposal);
    void updateProposal(final ProposalSecondType proposal);
}

The implementation of this interface has quite a lot of dependencies:

public class ProposalUpdateDefaultService implements ProposalUpdateService {
    private final ComplexService complexService;
    private final OtherComplexService otherComplexService;

    private final ProposalStep<Proposal> stepOne;
    private final ProposalStep<Proposal> stepTwo;
    private final ProposalStep<ProposalTypeTwo> stepThree;
    private final ProposalStep<Proposal> stepFour;

    public ProposalUpdateDefaultService(
            final ComplexService complexService,
            final OtherComplexService otherComplexService,
            final YetAnotherComplexService yetAnotherComplexService,
            final SimpleService simpleService,
            final OtherSimpleService otherSimpleService,
            final YetAnotherSimpleService yetAnotherSimpleService,
            final Converter<ProposalTypeOne, ComplexServiceType> converterProposalTypeOne,
            final Converter<ProposalTypeTwo, OtherComplexServiceType> converterProposalTypeTwo) {
        this.complexService = complexService;
        this.otherComplexService = otherComplexService;

        stepOne = new StepOne(yetAnotherComplexService);
        stepTwo =
                new StepTwo(
                        complexService,
                        otherComplexService,
                        yetAnotherComplexService,
                        converterProposalTypeOne,
                        converterProposalTypeTwo);
        stepThree =
                new StepThree(
                        simpleService,
                        otherSimpleService,
                        yetAnotherSimpleService);
        stepFour = new StepFour();
    }

    ...

As you can see this class encapsulate the update of a Proposal object, and this process is splitted in four phases. Those four phases my be arranged differently between different types of Proposal.

Here is the highly simplified implementation of those two updateProposal methods:

@Override
public void updateProposal(final ProposalTypeOne proposal) {
   stepOne.process(proposal);
   stepTwo.process(proposal);

   if (...) {
      stepFour.process(proposal);
   }
}

@Override
public void updateProposal(final ProposalTypeTwo proposal) {
   stepOne.process(proposal);
   stepTwo.process(proposal);
   stepThree.process(proposal);
   stepFour.process(proposal);
}

The two private fields

private final ComplexService complexService;
private final OtherComplexService otherComplexService;

are used for helper private methods.

As you can see this class just organize and delegate work, however it does depend on too many other classes. The same could be said for certain ProposalStep(s).

Would you accept this number of dependencies?
How would you refactor to simplify?

I've read about the Facade Service concept as a way to redure dependencies, and how I should group cluster of dependencies toghether, but here I don't really understand what to do.

I may group the Converter(s) and the Service(s) which uses them, but they'll be too many anyway.

Aucun commentaire:

Enregistrer un commentaire