HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMajor

Modelling a Call Center

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
callcentermodelling

Problem

This is the requirement I have (from the book: Cracking the Coding Interview)


Imagine you have a call center with three levels of employees: fresher, technical lead (TL), and product manager (PM). There can be multiple employees, but only one TL or PM. An incoming telephone call must be allocated to a fresher who is free. If a fresher can't handle the call, he or she must escalate the call to technical lead. If the TL is not free or not able to handle it, then the call should be escalated to PM. Design the classes and data structures for this problem. Implement a method getCallHandler().

And this is my implementation:

public interface CallAllocator {
    public Employee getCallHandler() throws NoEmployeeInTheHouseException;
    void setTL(TechnicalLead technicalLead);
    void setPM(ProductManager productManager);
    void addFresher(Fresher fresher);
}


Implementation for the interface:

```
public class CallAllocatorImpl implements CallAllocator {

private TechnicalLead technicalLead;
private ProductManager productManager;
private List freshers = new ArrayList();

@Override
public Employee getCallHandler() throws NoEmployeeInTheHouseException {

if (freshers.isEmpty() && technicalLead == null && productManager == null) {
throw new NoEmployeeInTheHouseException();
}

if (!freshers.isEmpty()) {
Employee fresher = freshers.get(new Random().nextInt(freshers.size()));
if (fresher.getCanHandle()) {
return fresher;
}
}

if (technicalLead != null && technicalLead.getCanHandle()) {
return technicalLead;
}

if (productManager != null && productManager.getCanHandle()) {
return productManager;
}

throw new NoEmployeeInTheHouseException();

}
@Override
public void setTL(TechnicalLead technicalLead) {
this.technicalLead = technicalLead;
}
@Override

Solution

Firstly, I'm not sure you're actually implementing the requirement as it's written. The description says:

An incoming call must be allocated to a fresher who is free. If a fresher can't handle the call, he or she must escalate to technical lead.

This sounds like if there are no free freshers, the call shouldn't be handled at all (an exception thrown?), rather than skipping to the TL. This sort of makes sense as a real world requirement: it may be preferable for a caller to have to call back a bit later if there are no freshers available, rather than to waste the technical lead's time with a call that a fresher should be able to handle. Whatever calls this could, for example, plan to catch that exception and do addCallToUnhandledCallQueue() or whatever.

This also goes a bit more to the meat of the question, which I believe is trying to get you to answer with the chain-of-responsibility pattern. In this pattern each object (in this case an Employee) responsible for processing a command (in this case a call) contains logic to check whether it is capable of processing a given command, and if not, also knows the next object in the chain to call.

One benefit from this pattern is adherence to the open/close principle. As you'll see below, doing something like adding a new employee type or changing the structure a bit is unlikely to require you to fiddle around with if{...} else{...} logic in getCallHandler(). Additionally, it means that Employees only need to know about their immediate boss, rather than some master class having to know and persist the entire employee structure (which would fast become unpleasant, especially if you need to add other methods which also require knowing this structure).

A meta-benefit, given that this is apparently to be approached as an interview question, is that if somebody asked me this in an interview, I'd be pretty sure they'd want me to talk about this pattern, so even if for whatever reason you ultimately decide there's a better solution, it's important to understand this one if only to be able to describe intelligently why you reject it.

So using this pattern, your getCallHandler(Call call) method would look something like this:

Employee fresher = getAnyFreeFresher(); //Should throw if there are none
return fresher.handle(call);


Then the Employee class would look something like:

public class Employee{
    private Employee boss;

    private bool canHandle(Call call){
    //...
    }

    public Employee handle(Call call){
        if(canHandle(call)){
            return this;
        }
        if(boss == null){
            //Nobody in the chain could handle, throw
        }
        return boss.handle(call);
    }
}


That's a very rough outline, there's detail to fill in on how bosses are set, and you'd probably want employee types to inherit from Employee to implement canHandle, etc.

Code Snippets

Employee fresher = getAnyFreeFresher(); //Should throw if there are none
return fresher.handle(call);
public class Employee{
    private Employee boss;

    private bool canHandle(Call call){
    //...
    }

    public Employee handle(Call call){
        if(canHandle(call)){
            return this;
        }
        if(boss == null){
            //Nobody in the chain could handle, throw
        }
        return boss.handle(call);
    }
}

Context

StackExchange Code Review Q#43087, answer score: 20

Revisions (0)

No revisions yet.