Skip to content

The Payroll Machine.

Or, as some would say, the story of how some complexity might be necessary sometimes. Or, yet another edition of Looking at the Wrong Abstraction.

The difficult solution

Imagine you need to develop an application that calculates a company’s payroll. Let’s assume that we have three different roles within the company (Developer, Systems Architect, Development Manager, and since this is a modern cool and hip company that does scrum, a Product Owner), and that different roles have different salaries.

The simplest approach

Well, you could argue that it does not actually matter too much, when calculating the payroll, if an employee is a Developer or a Systems Architect. So, one sensible approach might be to model all employees as instances of a class like this:

Now, calculating the payroll is just a matter of doing something like this:

Real life sucks. Or requirements change

I bet you have been there a thousand times. Your app is all app and running, processing data full steam ahead, doing what is expected to do, and doing it well, when suddenly… requirements change.

In this case, the CTO demands a new feature: he should be able to assign multipliers to specific employees, so he can modify their salaries temporarily.

The flexible solution. Or, the mega-awesome although apparently slightly over-engineered solution, that after some consideration, happens to be just awesome and not over-engineered at all

First, I’ll show you all the codez. The I’ll discuss all the codez.

Now, there are different kinds of Employees. To me, that means that each of those “kinds” has to be modelled by a different class. Why? Because they represent different behaviours. As you know, a PO does not do the same things a Developer does.

However, it is true that I am only interested in part of the behaviour of those different kinds of Employees. That is already abstracted by the interface!

Is there repetition? Yes, apparently, but I wouldn’t call it repetition, I would call it specialisation. If there is something else to be taken into account when calculating a salary (for example, manage,went might have part of their salaries payable in shares dividends and whatnot), the specific class that models a PO can implement that specific behaviour.

Also, this solution improves encapsulation. The responsibility of calculating each employee’s salary is well encapsulated, and is completely opaque to the calculatePayroll method.

Summary

Often times, a flexible solution requires more code than a simple one. Well, that’s life, I guess: if you want something done properly, you will need to put some serious work into it. It does not matter if it is installing a new fridge in your kitchen, or writing a new method in your code.

But the key here, again, is that being able to identify the right abstractions makes a huge difference in the scalability, modularity and cleanness of your code.

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *