5 ms·
The PersonnelRecord isn't OOP and exhibits a widespread misunderstanding: class PersonnelRecord { public: char* employeeName() const; int
by thangalin 5y ago
The PersonnelRecord isn't OOP and exhibits a widespread misunderstanding:
class PersonnelRecord {
public:
char* employeeName() const;
int employeeSocialSecurityNumber() const;
char* employeeDepartment() const;
protected:
char name[100];
int socialSecurityNumber;
char department[10];
float salary;
}
As written, PersonnelRecord class will inevitably lead to code duplication, tightly coupled classes, and other maintainability issues. An improvement that's still not OOP, but exposes a more flexible contract, resembles:
class Employee {
public:
Name name() const;
SocialSecurityNumber socialSecurityNumber() const;
Department department() const;
private:
Name name;
SocialSecurityNumber socialSecurityNumber;
Department department;
Salary salary;
}
OOP is more about the actionable messages that objects understand to carry out tasks on behalf of other objects. Wrapping immutable data exposed via accessors reaps few benefits. Rather, OOP strives to model behaviours that relate to the problem domain:
class Employee {
public:
void hire();
void fire();
void kill();
void raise( float percentage );
void promote( Position position );
void transfer( Department department );
private:
Name name;
SocialSecurityNumber socialSecurityNumber;
Department department;
Salary salary;
}
This allows for writing the following code:
employee.transfer( department );
I don't know how to "transfer" an employee given the code from the article, but it would not be nearly as elegant.
- vikingcaffiene 5y agoI dunno man... I think that giving an entity the ability to perform operations upon itself and thereby changing it, looks neat in these examples but scales poorly in a sufficiently commplex codebase. You could express exactly the same thing but get a lot more bullet proof code if you separate out the thing doing the action from the thing you are acting upon. You could have the thing doing the action return the updated version of the thing you wanted to do said operation upon and its unambiguous what has happened. So something like (psuedocode): transferredEmployee = employeeService.transfer(employee, department); IMO this forces a certain style of coding that ages better and requires keeping less stuff in your head. My two cents. Have a good one!
- thangalin 5y agoSure. Depends on the problem domain. One could equally write: xferEmployee = employee.transfer( department ) xferEmployee = company.transfer( employee, department ) xferEmployee = department.transfer( employee ) exEmployee = humanResources.fire( employee ) Or, using an event-based architecture: new EmployeeTransferEvent( employee, department ).publish()
- brewmarche 5y agoYour event approach reminded me of Eric Lippert’s blog post: https://ericlippert.com/2015/04/27/wizards-and-warriors-part-one/ https://ericlippert.com/2015/04/27/wizards-and-warriors-part... He also ends up with the commands/actions/events/rules (basically emphasize relation over object) as main types in an interesting[0] example of a rule-based game. One of my issues with “mainstream OOP” (at this point I’m not even sure what “real” OOP is) is that it apparently tempts people to base their models around objects and subjects not verbs. I’m not sure if it’s due to prevalent nominal type systems or due to how we traditionally teach class hierarchies (dogs/cats <- animals) but I think centering the model around predicates and relations works much better. [1] [0] Interesting because while it is a toy example it is one that could be real; not like examples with cars and animals. [1] Just reminded me a bit of Wittgenstein’s Tractatus; didn’t want to get too philosophical but I think the ontological views we have influence this kind of modelling a lot
- LudwigNagasena 5y agoWhy not department.transfer(employee) or workplace.transfer(employee, department_from, department_to)? I think that sometimes the most OOP way is just to write struct PersonnelRecord { char name[100]; int socialSecurityNumber; char department[10]; float salary; } and be done with it.