OOP Problem from Cracking the Code Interview
17 Dec 2014
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