Subject-oriented programming, problem with object-oriented programming with examples in Python
September the 2th, 2014
First problem with object-oriented programming
Let's say we're writing a payroll software. We're dealing with enterprises, employees and pay slips, so we have at least these objects. We have a set of employees associated to each enterprise, and a set of pay slips associated to each employee. In Python, this is something like:
class Enterprise: ...stuff like administrative identification
class Employee: ...stuff like name and address
class PaySlip: .... stuff like amount paid.
Now, let's say that we need to compute some synthesis for the IRS, and another one for social services. Let's further say that this is driven by the "Enterprise" object. We add methods like getIRSData and getSocialServiceData to classes Enterprises, Employee and PaySlip to gather the data, possibly using some private methods like _computeIRSPercentage (private to, say, the PaySlip module) to help in the calculation.
Now the city wants its own dashboard, with the number of people living inside and outside the city, so does the county with the number of people using a car to go to work vs the number of people using a bike. We add getCityDashboard to every class, and getCountyDashboard.
Now, using object oriented programming, we have encapsulated the specifics of the various computations of each category of object inside the object's class, but we have two problems:
- Without additionnal work, methods like getCityDashboard can access the entirely unrelated method _computeIRSPercentage that was supposed to be private, so clearly we aren't good on encapsulation.
- As our system mature and we add more and more modules, each class becomes a bag of unrelated stuff whose the only common point is that they manipulate the data of the Employee class (or Enterprise, or PaySlip).
At some point we may use the versioning system to know what code lines were added when we created the county stuff. Now what if someone else has to modify this code ? She has to go through all the classes to modify the code (speaking of version control, at the risk of interfering with someone else modification).
Now we can draw our inspiration from subject oriented programming. We still have to add methods to the various classes, but using Python structure, we put every new concern into its own file / module, and we "hook" the corresponding code into the classes by importing the corresponding functions. Thus, we have for example:
def getEnterpriseData():... def getEmployeeData():... def getPaySlipData():...
and also a file SocialService.py, CityDashBoard.py, CountyDashBoard.py with the same kind of methods.
In Enterprise.py, we now have:
class Enterprise: .... from IRS import getEnterpriseData as getIRSData
class Employee: .... from IRS import getEmployeeData as getIRSData
and so on, you get the point.
By doing, we have grouped together the code for one particular "mission" (or "subject"), the private helper functions of IRS are not visible from the SocialService any longer, as should be the case. Furthermore, it someone works on the SocialService code, there are less chances that it interferes with someone working on the CountyDashBoard. There are also more chances that the modification for the county dash board will be restricted to CountyDashBoard, which is what we expect, rather than spreaded over Enterprise / Employee / PaySlip, which give us absolutely no clue of what was intended since this would be the case for almost any modification in our scheme.
Next time, we'll see if it's always a good method to use classes, or if tag plus a dispatch table may not be a better solution in some cases, unlike what popular object-oriented culture might teach us.