2
\$\begingroup\$

For the following problem statement, I design following classes. Can you please tell me if this is the correct implementation or if there can be a better one?

Let's say there is 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.

using System;
using System.Linq;
using System.Collections.Generic;

namespace TestNS
{
    public class Employee
    {
        public string Name { get; set; }
        public bool IsFree { get; set; }
        public Employee Manager { get; set; }
    }

    public class Call
    {
        public Employee AllocatedTo { get; set; }

        public bool HandleCall()
        {
            AllocatedTo.IsFree = false;
            bool isHandled = false;

            // Write custom logic to handle the call & set the value of isHandled

            if (isHandled)
            {
                AllocatedTo.IsFree = true;
            }

            return isHandled;
        }

        public void Escalate()
        {
            AllocatedTo = AllocatedTo.Manager;
            HandleCall();
        }
    }

    public class CallManager
    {
        List<Employee> fresherList = new List<Employee>();
        public void CreateEmployeeList()
        {
            Employee PM = new Employee() { Name = "PM1", IsFree = true };

            Employee TL = new Employee() { Name = "TL1", IsFree = true };
            TL.Manager = PM;

            fresherList = new List<Employee>();
            fresherList.Add(new Employee() { Name = "F1", Manager = TL, IsFree = true });
            fresherList.Add(new Employee() { Name = "F2", Manager = TL, IsFree = true });
            fresherList.Add(new Employee() { Name = "F3", Manager = TL, IsFree = true });
            fresherList.Add(new Employee() { Name = "F4", Manager = TL, IsFree = true });
            fresherList.Add(new Employee() { Name = "F5", Manager = TL, IsFree = true });
            fresherList.Add(new Employee() { Name = "F6", Manager = TL, IsFree = true });
        }

        private Employee FindFreeEmployee()
        {
            Employee e = null;
            foreach (Employee emp in fresherList)
            {
                if (emp.IsFree)
                {
                    e = emp;
                    break;
                }
            }

            return e;
        }

        public void ReceiveAndAllocateCall(Call call1)
        {
            call1.AllocatedTo = FindFreeEmployee();
            call1.HandleCall();
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Your scenario can perfectly take advantage of Chain Of Responsibility Design Pattern. Have a look at it and see if its perfect for you problem. You can find many examples of implementation in .NET. \$\endgroup\$ – Vibhore Tanwer Aug 30 '13 at 9:50
  • \$\begingroup\$ I think "CallManager` is a very bad name, it does not describe what the class does ("manage" can mean almost anything). There is a method named "..AllocateCall", this is closer to the true purpose of the class. Perhaps CallAllocator or CallRouter would be better names. \$\endgroup\$ – MattDavey Aug 30 '13 at 10:50
2
\$\begingroup\$
  1. I like the Employee class with the built-in Manager chain.
  2. I think Call class should be "dumb" like the Employee. The methods seem like call processing - what the CallManager should be doing.
  3. Id say part of the "call handing process" is in the CallManager and part of it is in Call class. Broken apart like this it's hard to discern/follow the flow of a call-handling.
  4. Should you implement queues? A queue of Calls to model lots of calls coming in before they can get allocated.
  5. The code has allocation and "isFree" as 2 separate things. This suggests to me that we could have a Employee.CallQueue for allocated calls, then set IsFree = false when he picks up the phone.
  6. Also an Employee.CallQueue of assigned calls. The code suggests that allocation and handling are 2 separate things
  7. In ReceiveAndAllocateCall.FindFreeEmployee() could return null so we need code to handle that. Maybe that when the call goes into a waiting queue.

public class CallManager {
     . . .

    // call processing
    call1.AllocatedTo = FindFreeEmployee();

    // what to do if AllocatedTo is null?

    call1.AllocatedTo.IsFree = false;
    call1.IsHandled = false; 

    // I see `IsHandled` as a `Call` property. It will persist if we 
    // pass it to the manager. As is, `IsHandled` disappears when `HandleCall()` ends and we don't know if the call is handled anymore.

    while (! call1.IsHandled) {
     // Write custom logic to handle the call & set the value of isHandled
     if (! call1.isHandled) {
         if (call1.AllocatedTo.Manager != null) { call1.AllocateTo = AllocateTo.Manager
         }else{ break;}
      }
    } // while

    // if IsHandled == false still, what to do? Hang up and send them a lollypop I guess.
  • The 1st line, calling FindFreeEmployee() might best be done outside of, or somewhere else in CallManager Imagine a complex process for deciding how to pair calls to employees. Then pass that pair into CallManager, and all call manager does is process the call. - Separation of Responsibilities.
| improve this answer | |
\$\endgroup\$

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.