title: Object-oriented design: Giving too much responsibility to a value object
body: <p>I came across this design question in the book Cracking the Coding Interview:</p>
  
  <blockquote>
    <p>Imagine you have a call center with three levels of employees:
    fresher, technical lead (TL), 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().</p>
  </blockquote>
  
  <p><strong>Solution in the book</strong></p>
  
  <pre><code>public class CallHandler {
      static final int LEVELS = 3; // we have 3 levels of employees
      static final int NUM_FRESHERS = 5; // we have 5 freshers
      ArrayList&lt;Employee&gt;[] employeeLevels = new ArrayList[LEVELS];
      // queues for each call’s rank
      Queue&lt;Call&gt;[] callQueues = new LinkedList[LEVELS];
  
      public CallHandler() { ... }
  
      Employee getCallHandler(Call call) {
          for (int level = call.rank; level &lt; LEVELS - 1; level++) {
              ArrayList&lt;Employee&gt; employeeLevel = employeeLevels[level];
              for (Employee emp : employeeLevel) {
                  if (emp.free) {
                      return emp;
                  }
              }
          }
          return null;
      }
  
      // routes the call to an available employee, or adds to a queue
      void dispatchCall(Call call) {
          // try to route the call to an employee with minimal rank
          Employee emp = getCallHandler(call);
          if (emp != null) {
              emp.ReceiveCall(call);
          } else {
              // place the call into queue according to its rank
              callQueues[call.rank].add(call);
          }
      }
      void getNextCall(Employee e) {...} // look for call for e’s rank
  }
  
  class Call {
      int rank = 0; // minimal rank of employee who can handle this call
      public void reply(String message) { ... }
      public void disconnect() { ... }
  }
  
  class Employee {
      CallHandler callHandler;
      int rank; // 0- fresher, 1 - technical lead, 2 - product manager
      boolean free;
      Employee(int rank) { this.rank = rank; }
      void ReceiveCall(Call call) { ... }
      void CallHandled(Call call) { ... } // call is complete
      void CannotHandle(Call call) { // escalate call
          call.rank = rank + 1;
          callHandler.dispatchCall(call);
          free = true;
          callHandler.getNextCall(this); // look for waiting call
      }
  }
  
  class Fresher extends Employee {
      public Fresher() { super(0); }
  }
  class TechLead extends Employee {
      public TechLead() { super(1); }
  }
  class ProductManager extends Employee {
      public ProductManager() { super(2); }
  }
  </code></pre>
  
  <p>This solution is not very satisfying mainly because it involves passing a <code>CallHandler</code> object to <code>Employee</code>. I think <code>Employee</code> should be treated as a value object meaning its job should be mostly holding data without being aware of entities that contain the real business logic (like <code>CallHandler</code>). So I am interested in finding out what better ways there are to design this. I come from ActionScript background and in that I would probably use ActionScript's event model to send messages from <code>Employee</code> and listen to them in <code>CallHandler</code>.</p>