Update: A Bit of Guidance
I thought I'll provide a bit of help for this little challenge. I suspect people are looking at the problem from a wrong angle.
So here are a few more clues to solve this:
- Imagine, that one would need to change how the names are stored. For instance, one would like to store the first name and last name separately. Also store middle name(s) too, if any. Also, title would be needed to be stored. These shouldn't go inti a single string as now, but into multiple fields.
- Now how much effort would it be to implement this?
- How could have this been way less problem if the classes were designed differently?
- You can have the same thought process for the ID as well. What is we wanted it to contain letters too? How many times do we need to change this? How could have we done things better in the design to only need to change the ID one place only?
I hope this helps to see the flow of the design of the code below. Share you idea how it could have been done better. ;)
Instructions
This exercise is for anyone who would like to get better in object-oriented design.
I've provided a sample code, that has a problems with it. (I was focusing on one specific problem, however, other mistakes could have been made.) The sample code could have been written in C# or Python or Java or any object oriented language. In other words, look for design problems, not syntax or C++ specific errors.
Let's see who finds the problem.
Please, tell me
- what part of the code has a problem
- why it is a problem
- how would you fix it
Notes & Tips
- The code compiles and runs (using C++ compilation language)
- Do not get discouraged by the length. Just read though, try to understand what we're trying to do here and find what potential issue the implementation has.
The Code
The whole code can be downloaded from here, or just read below:
main.cpp
#include <iostream>
#include "Manager.h"
static void PrintHierarchy(const Company::Manager * manager)
{
std::cout << manager->GetName() << std::endl;
for (Company::TeamLead * teamLead : manager->GetTeamLeads())
{
std::cout << '\t' << teamLead->GetName() << std::endl;
for (Company::Programmer * programmer : teamLead->GetProgrammers())
{
std::cout << "\t\t" << programmer->GetName() << std::endl;
}
}
}
int main()
{
Company::Manager manager("Charles Manager", 0);
Company::TeamLead teamLead_A("Alpha Lead", 1);
Company::TeamLead teamLead_B("Bravo Lead", 2);
Company::Programmer programmer_A0("John Alpha", 3);
Company::Programmer programmer_A1("Jane Alpha", 4);
Company::Programmer programmer_A2("Jeffrey Alpha", 5);
Company::Programmer programmer_B0("Amos Bravo", 6);
Company::Programmer programmer_B1("Ane Bravo", 7);
Company::Programmer programmer_B2("Amy Bravo", 8);
Company::Programmer programmer_B3("Arthur Bravo", 9);
manager.Add(&teamLead_A);
manager.Add(&teamLead_B);
teamLead_A.Add(&programmer_A0);
teamLead_A.Add(&programmer_A1);
teamLead_A.Add(&programmer_A2);
teamLead_B.Add(&programmer_B0);
teamLead_B.Add(&programmer_B1);
teamLead_B.Add(&programmer_B2);
teamLead_B.Add(&programmer_B3);
PrintHierarchy(&manager);
return 0;
}
Programmer.h
#pragma once
#include <string>
namespace Company
{
class Programmer
{
private:
std::string _name;
unsigned int _id;
float _hoursWorked;
public:
Programmer(std::string name, unsigned int _id);
const std::string & GetName() const;
unsigned int GetId() const;
void Work(float hours);
};
}
Programmer.cpp
#include "Programmer.h"
namespace Company
{
Programmer::Programmer(std::string name, unsigned int id) :
_name(name),
_id(id),
_hoursWorked(0.0f)
{ }
const std::string & Programmer::GetName() const { return _name; }
unsigned int Programmer::GetId() const { return _id; }
void Programmer::Work(float hours) { _hoursWorked += hours; }
}
TeamLead.h
#pragma once
#include <string>
#include <vector>
#include "Programmer.h"
namespace Company
{
class TeamLead
{
private:
std::vector<Programmer *> _programmers;
std::string _name;
unsigned int _id;
float _hoursWorked;
public:
TeamLead(std::string name, unsigned int _id);
const std::string & GetName() const;
unsigned int GetId() const;
void Work(float hours);
void Add(Programmer * programmer);
const std::vector<Programmer *> & GetProgrammers() const;
};
}
TeamLead.cpp
#include "TeamLead.h"
namespace Company
{
TeamLead::TeamLead(std::string name, unsigned int id) :
_name(name),
_id(id),
_hoursWorked(0.0f)
{ }
const std::string & TeamLead::GetName() const { return _name; }
unsigned int TeamLead::GetId() const { return _id; }
void TeamLead::Work(float hours) { _hoursWorked += hours; }
void TeamLead::Add(Programmer * programmer) { _programmers.push_back(programmer); }
const std::vector<Programmer *> & TeamLead::GetProgrammers() const { return _programmers; }
}
Manager.h
#pragma once
#include <string>
#include <vector>
#include "TeamLead.h"
namespace Company
{
class Manager
{
private:
std::vector<TeamLead *> _teamLeads;
std::string _name;
unsigned int _id;
float _hoursWorked;
public:
Manager(std::string name, unsigned int _id);
const std::string & GetName() const;
unsigned int GetId() const;
void Work(float hours);
void Add(TeamLead * teamLead);
const std::vector<TeamLead *> & GetTeamLeads() const;
};
}
Manager.cpp
#include "Manager.h"
namespace Company
{
Manager::Manager(std::string name, unsigned int id) :
_name(name),
_id(id),
_hoursWorked(0.0f)
{ }
const std::string & Manager::GetName() const { return _name; }
unsigned int Manager::GetId() const { return _id; }
void Manager::Work(float hours) { _hoursWorked += hours; }
void Manager::Add(TeamLead * teamLead) { _teamLeads.push_back(teamLead); }
const std::vector<TeamLead *> & Manager::GetTeamLeads() const { return _teamLeads; }
}