JBerczel's Notes on learning Web Development

OOP Problem from Cracking the Code Interview

This is a practice problem to think about object oriented design. I wasn’t sure how far to go wtih the solution. I have a basic working solution and an example. Feel free to solve and compare, or simply discuss.

Question

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 handle it, then the call should be escalated to PM. Design the classes and data structures for this problem. Implement a method getCallHandler().

My Solution

class CallHandler
  attr_reader :product_manager, :tech_lead, :freshers, :calls

  def initialize(args={})
    @product_manager = args[:product_manager]
    @tech_lead       = args[:tech_lead]
    @freshers        = args[:freshers]
    @calls           = []
  end

  def get_call_handler
    employees_by_rank.find { |emp| emp.free? }
  end

  def employees_by_rank
    [freshers.shuffle, tech_lead, product_manager].flatten
  end

  def route_incoming(call)
    employee = get_call_handler
    if employee
      employee.take(call)
    else
      calls << call
    end
  end

  def display_status
    puts "CALL STATUS\n----------"
    employees_by_rank.each_with_index do |emp,i|
      printf("%d. %15s: %5s: %s\n", i+1, emp.title, emp.name, emp.status)
    end
    puts
  end
end

class Employee
  attr_reader :name, :title
  attr_accessor :status

  def initialize(name, title)
    @name         = name
    @title        = title
    @status       = :free
  end

  def take(call)
    self.status   = :busy
    call.employee = self
    call.status   = :on_phone
  end

  def end(call)
    self.status = :free
    call.status = :answered
  end

  def free?
    status == :free
  end
end

class Call
  attr_accessor :employee, :status

  def initialize(name, message)
    @caller  = name
    @message = message
    @status  = :on_hold
  end
end

An Example

employee1 = Employee.new('John', 'Product Manager')
employee2 = Employee.new('Jim', 'Tech Lead')
employee3 = Employee.new('James', 'Fresher')
employee4 = Employee.new('Joe', 'Fresher')

call_center = CallHandler.new(
                product_manager:  employee1,
                tech_lead:        employee2,
                freshers:         [employee3, employee4] )

call1 = Call.new("Mr T", "My WoW account isn't working.")
call2 = Call.new("Mr Kim", "Issue with login...")

call_center.route_incoming(call1)
call_center.route_incoming(call2)

call_center.display_status
employee3.end(call1)
call_center.display_status

Output

CALL STATUS
----------
1.         Fresher: James: busy
2.         Fresher:   Joe: busy
3.       Tech Lead:   Jim: free
4. Product Manager:  John: free

CALL STATUS
----------
1.         Fresher:   Joe: busy
2.         Fresher: James: free
3.       Tech Lead:   Jim: free
4. Product Manager:  John: free