-2

I have an abstraction that defines something like a command pattern,

interface Participant {
    void proceed();
}

Participants are grouped in a collection and are called all together. But each Participant in the group doesn't have to participate in a certain call due to certain conditions.

I wanted to add an allowance method to my abstraction. The idea is that the caller can ask the Participant if it should be called or not, before calling proceed().

Is this the right approach? Maybe that determining the conditions for the allowance could require very expensive calculations, that later would needed to be performed again in proceed(). If the implementation has to be stateless, it would not be possible to save the calculation between the two calls, and the performance would be impacted.

By the way, if this is an acceptable approach, I would need a clear name for the allowance function. I thought about canProceed() but I wanted to avoid repeating the name of the action, and a simple can() seemed vague to me. Are there usual naming conventions for this kind of function?

  • 1
    Hi lucasvc, your first question will be hard to answer, because a lot of context is missing. You might want to have a look at the chain of responsibility pattern and how it might fit your needs: stackoverflow.com/a/747993/844822 – Benni Jul 3 at 16:59
  • 1
    Hi lucasvc, your question is interesting but the title lead to think that you're interested in naming (which is highly subjective and out of scope). Reading your question shows that your main concern is how to manage the conditional triggering of your "commands". I edited your question to clarify. Don't hesitate to reject my edit if I misunderstood. By the way with allowance do you mean permission or feasibility ? – Christophe Jul 4 at 17:36
  • 1
    @Benni the chain of responsibility could indeed be a good idea, depending on the context and the intent. But the split of responsibility proposed by that pattern , i.e. that a handler shall find-out for itself if it fires or not, is in any case clearly the way to go – Christophe Jul 5 at 8:01
3

The problem

Lets look at the analogy with the Command pattern:

  • A Client creates objects of classes that that implement the Participant (similar to Command). For convenience, let's call one of these classes ConcreteParticipant.
  • The ConcreteParticipant object knows all the context, such as receiver to perform its duties and proceed() (similar to execute() in the command pattern). This context may be provided at construction or later, but before any invocation.
  • The invoker object is a little more complex, since it has a collection of Participant, This may be let's take for example ConcreteParticipant have all the necessary context (e.g. receiver in the command pattern) to perform the calculation of the conditions and proceed().
  • The conditions that say if the Participant must proceed() is not calculated by the invoker, but by the Participant itself.

Your initial approach

Your first approach is to expose the Participant condition determination and let the invoker do the filtering:

//PSEUDO CODE:  I'm not Java fluent...

interface Participant {
    void proceed();
    boolean isApplicable();  // but why?
}

// in the invoker:  

for (Participant p: participants) {
    if (p.isApplicable()) 
       p.proceed();
}

What's the benefit of such approach? If the Participant determines itself if the condition applies (and perhaps some are even unconditional) it makes no sense to let another class deciede.

Keep it simple!

According to the principle of least knowledge and sound separation of concerns, and unless there are reasons you forget to tell about, you should not expose the condition.

Instead, you should trust the participant to work only if necessary:

interface Participant {
    void proceed();
}
class ConcreteParticipant implements Participant {
    private bolean isApplicable() { ... }  // no longer explosed in the interface
    public void proceed() { 
        if (isApplicable()) {
            ...
        }
    }
}  
class ConcreteUnconditionalParticipant implements Participant {
    public void proceed() { 
        doItAnyway(); 
    }
}  

With this approach you no longer have any performance issue of redoing twice the same time-consuming operation: you may refactor the code without changing the interface:

class OtherConcreteParticipant implements Participant {
    private ComplexResult prepareCondition() { ...} 
    private bolean isApplicable (ComplexResult r) { ... }  // stateless :-) 
    public void proceed() { 
        ComplexResult r = prepareCondition(); 
        if (isApplicable(r)) {
            ... // here you may reuse r.  
        }
    }
}  

And you have no longer a naming issue either ;-)

Need tighter control?

If the invoker must do some bookkeeping, for example counting the number of participants that contributed, you could change slightly your interface:

interface TalkativeParticipant {
    boolean proceed();  // return true if it was active, and false if not applicable.
}

Note that this approach would also allow you more elaborate decisions on invoking participants:

  • you could easily stop the calls after the first participant did work.
  • or stop the calls after the first that did not work

Remark: The first result could also be achieved using a chain of responsibility pattern. But chain of responsibility would require each Participant to know its successor. THis is a very different situation than what you described. The collection of participants seems easier to manage.

| improve this answer | |
  • one solution i tend to prefer is to segregate the interface in multiple interfaces. by saying that a participant is someone that can prooced and some other term is a participant that cannot proceed. ie, the first one has the proceed method while the second one doesn't. this provides a more clear interface, and in languages like java it will literally not compile if you attempt to call proceed on an interface that does not have that method. in your example, prooced is ambigous as it may not prooced after all. tryToProoced would be more appropriate, but more convoluted. – Pedro Rodrigues Jul 5 at 19:26
  • 1
    @PedroRodrigues I think we have a different understanding of the question: here it’s not about what a class can do or not (in this case I’d fully agree with you), but about runtime conditions that make it possible or not to proceed. Think for example of the case where proceed() would do a division by something: the condition would be to check that the divisor is not null before doing the calculation. Since it’s runtime, the interface segregation wouldn’t help – Christophe Jul 5 at 19:38
  • We definitly had a diff understanding, I failed to properly understand the question, you didn't seem to. the null example I don't think is very good, but I think you could have used the divide by zero problem to the same effect. if that is so, the approach I'm providing would be to have the divide interface accept a type nonZeroNumber as the divisor. That is not t say that at some other level, you won't be checking for that number to be zero or not. is to say divide does division unconditionally and has an interface for that. The conditional is in to call divide or not. – Pedro Rodrigues Jul 5 at 19:49
  • @PedroRodrigues In fact, my point is exactly that: instead of making the interface more complex, I’d simply make proceed() reponsible to check if it can do the divide before doing the operation – Christophe Jul 5 at 19:54
  • If the solution just makes the code more complex is not a better solution tha is for sure. But I did understand your solution, I was just putting a different solution in perspective and not making an argument. no pun intended. – Pedro Rodrigues Jul 5 at 20:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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