1

I have a current situation where I have to design calls to multiple webservices, coming from different companies, let's say EnrollFacebook, EnrollGoogle, EnrollYelp, EnrollBing.

I need to build different options that bundle this enrolls, for instance:

  • PlanA: EnrollFacebook, EnrollGoogle, EnrollBing
  • PlanB: EnrollGoogle
  • PlanC: EnrollYelp, EnrollBing
  • PlanD: EnrollFacebook, EnrollGoogle, EnrollYelp, EnrollBing

Later on, if I need to build a PlanE, I want to be able to build using the different units (aka enrolls, and plug google with yelp or whatever).

I'm investigating about a design pattern that helps me covering this, since every enroll is an independent unit, not knowing others enrolls. However if any of the unit fails, I have to call all the deenroll related to all success enrolls.

Do you know a pattern that suit my needs? I was reading about Pipeline or Mediator but not sure if this actually cover what I describe.

Update: I've read this post Choosing the right Design Pattern, but however this does not help since I know what my problem is and I just trying to find an existing solution for this problem since this seems a very common problem, I don't want to reinvent the wheel if there are good designs out there.

2
  • 1
    Possible duplicate of Choosing the right Design Pattern
    – gnat
    Apr 14, 2017 at 18:02
  • 3
    Assume there isn't a design pattern to do this. How would you go about solving it? Once you have that worked out, implement it.
    – Becuzz
    Apr 14, 2017 at 19:55

2 Answers 2

1

The chain of responsibity seems to be a good candidate for this at first sight:

  • a handler could have an optional successor, thus creating the kind of variable chain that you describe
  • the concrete handler class would implement an enrollX client
4
  • The problem with chain of responsibility is that every unit must know the following, while in my case each unit is and independent logic that does not know the next Apr 14, 2017 at 19:05
  • I was thinking of having the independent logic implemented in the concrete handler class, but objects instantiating these classes would be elements of a specific plan (i.e. Knowledge of the follower would be local to a single plan, e.g. a kind of linked list)
    – Christophe
    Apr 14, 2017 at 19:31
  • Not sure if I follow you, do you mean that a concrete Plan would contain a list of strategies? And each concrete plan will gather the logic for a full enroll or deenroll process? Apr 14, 2017 at 19:54
  • Sorry if i was not clear enough: each concrete plan would start with a first enroll handler object, that would point to its successor handler ibject, and so on. The connection between the handler objects would be created dynamically when building a concrete plan (with the builder pattern? Or ad-hoc). So a handler instantiating a same enrollB class could very well in one plan have a successor and in another, not
    – Christophe
    Apr 14, 2017 at 20:05
-1

I would suggest you to use dependency injection. Have an XML file define various Enroll elements and Plan elements.

<config>
    <plan name="PlanC">
        <enroll refId="EnrollYelp" order="0" attr1="val1" attr2="val2"/> 
        <enroll refId="EnrollBing" order="1" attr1="val1" attr2="val2"/> 
    </plan>
    <plan name="PlanA">
        <!-- more child enroll elements -->
    </plan>
    <enroll name ="EnrollGoogle" attr="val">
    </enroll>
    <enroll name ="EnrollYelp" attr="val">
    </enroll>
</config>

(You need to create a schema defining above structure)

Now the code part. (I am going to use Java for describing things)

In the code, you can have an Enroll class and Plan class. The plan class has two queues: enrollQueue and deenrollQueue

class Plan{
    Queue<Enroll> enrollQueue;
    Queue<Enroll> deEnrollQueue;
    // Other variables and methods follow
}

Have enroll and deenroll methods defined in Enroll class:

class Enroll{
    String name;
    //other variables
    private boolean enroll(){
         // enroll logic might be based on attributes present in XML --
         // -- which were read by factory class and assigned into variables of this class.
         // return boolean indicating success of failure
    }
    private boolean deEnroll(){
         // enroll logic might depend on variables of this class which depend on attributes in XML element
         // return boolean indicating success of failure
    }
}

Also have a Factory class which reads the xml file defined above and creates the Plan elements. In your entrypoint/main/controller class, create the plans based on xml

List<Plan> planList = PlanFactory.readPlansFromXML();

Now for each plan in the planList, perform the core task

for(Plan plan:planList){
    // get enroll queue for the plan
    // for each element in enroll queue
        // remove element from enroll queue and add it to deEnroll queue
        // execute enroll() for the element
        // if enroll() fails, execute deEnroll() for each element in deEnroll queue and break to next plan
        // if enroll() is successful, continue the loop with next element in enrollQueue
}   

Since all the plans and all the enrolls are defined in XML, you can easily define new Enrolls and new Plans just by editing the XML without any changes to the code.

6
  • What is wrong with changing the code? Your answer is not the simplest solution. Apr 15, 2017 at 19:59
  • @Frank OP clearly mentioned he wants to build more plans later. Which one is easier->adding new classes everytime an enroll or a plan is added&changing the classes everytime a plan is updated vs making changes to an XML file.? You may read more about benefits of DI. "Your answer is not the simplest solution"<- that's debatable and it's for OP to decide. When there's another answer which seems simpler, we can compare. I don't think the downvote is fair
    – RajatJ
    Apr 16, 2017 at 2:40
  • Are you talking about a million classes? Clearly classes, provided they are not third-party (and hence actually need your solution), are a simpler solution and easier to debug. Apr 17, 2017 at 16:31
  • are you saying Dependency Injection is fit for use only in case there are a million classes? or only in case there are third-party classes?
    – RajatJ
    Apr 17, 2017 at 18:05
  • Dependency Injection is definitely needed for third party classes. Any other use is questionable. I used the phrase "a million classes" simply to illustrate that the overengineering you prescribe is not only solving a problem that does not exist yet, it may never exist in the future; i.e. adding a few classes is no burden compared to the added complexity of DI. Apr 17, 2017 at 22:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.