4 ms·
You need to read up on Anemic Domain Model (https://martinfowler.com/bliki/AnemicDomainModel.html https://martinfowler.com/bliki/AnemicDomainModel.html). I see
by lmilcin 6y ago
You need to read up on Anemic Domain Model (https://martinfowler.com/bliki/AnemicDomainModel.html https://martinfowler.com/bliki/AnemicDomainModel.html).
I see a lot of chaos in your post.
Model is a model. Model is there to represent an aspect or aspects of a real system (https://en.wikipedia.org/wiki/Conceptual_model https://en.wikipedia.org/wiki/Conceptual_model). An object called "Employee" is a "model", a representation of certain aspect of an actual employee.
Object oriented programming is about using objects -- models (representations of aspects) of actual systems, actors, objects, etc. In OOP you build the model from operations that define the object. The fields are not part of the interface, the operations are. That's why everybody says to make fields public (but for some reason not everybody remembers why).
So a method call fire() on an object Employee is more "object oriented" than having HREmployeeService.fireEmployee(employeeId) to set field employedTo directly on EmployeeDAO.
- nimblegorilla 6y agoI think OOP is great, but one weakness is that a lot of abstract concepts don't really map to objects. And then people have flamewars about where to put those concepts. In the real world most employees would never fire themselves and HR would update things like payroll which the employee isn't allowed to change. Your example makes more sense as a justification for keeping a service layer.
- lmilcin 6y agoAs with almost everything, when you try to stretch an analogy or use a single tool for every job, you are going to run into problems. Every tool has limitations and so does OOP. Employee object is not a representation of the will of the employee. It is an interface with operations that are best naturally acting on an Employee object -- changing its state.
- giantDinosaur 6y agoI suppose a manager is also an employee, but Manager inherits from Employee with a .fire() method seems wrong, no? I'd expect a method which takes another object or ID, not to change the state of the object with the fire() method. Anyway, this is why I stay far, far away from OOP when I can - vast amounts of time spent on these questions which generate zero insight (at least the mathematical obsession with some parts of FP can be fun)
- inopinatus 6y agoAbstract concepts map very well to objects. The problem of mapping a business domain to computing structures isn't unique to OOP. In this case, I'm slightly gobsmacked that no-one pointed out that an employee is not their job. The contract of employment is a separate domain concept. So is the invocation of the clauses of that contract. Termination involves invoking a particular contract clause. The job is to model a) the contract, b) the invocation of a specific clause, c) the record of that invocation (including its authorisations and so forth), and d) the consequential processing in other systems. Whether you're working in FP, or Kay-style OOP, or Java-style OOP or, heck, SQL stored procedures, these are separate concerns, separate concepts, separate units of code, separate records, hopefully loosely coupled by whatever idiomatic form is at hand.
- nimblegorilla 6y ago> Abstract concepts map very well to objects. The problem of mapping a business domain to computing structures isn't unique to OOP. Yes, I agree in theory. What I meant to say is that many concepts don't map to physical objects. > In this case, I'm slightly gobsmacked that no-one pointed out that an employee is not their job. The contract of employment is a separate domain concept. This is what I mean by flamewars. Your solution sounds good, but there are other people on this same thread still arguing that it makes perfect sense for an employee to fire itself.
- inopinatus 6y agoThe litany of category and analytic blunders on display in that subthread is remarkable, but it’s hardly intrinsic to OOP, and mostly attributable to inexperience.
- virmundi 6y agoGetters were popular with automatic tooling. They were intended for only UI models. In Java this was called the Bean Standard. https://en.m.wikibooks.org/wiki/Java_Programming/JavaBeans https://en.m.wikibooks.org/wiki/Java_Programming/JavaBeans
- lmilcin 6y agoDon't get me started on all the helpful tools that make it easy to automate antipatterns. Heard fields should be kept private? Don't know why? Lombok to the rescue, let's generate all those suckers up when we could just as well made fields public.
- BlackFly 6y agoThe rationale is the same as that for an abstract data type. You don't need to know how a class structures its properties and directly coupling to a representation can burden future maintenance. This very rarely comes up, but when it does it is nice to change a getter instead of tracking down all the locations where it was directly coupled to the representation. It isn't at all obvious when you are writing a class whether future maintenance will need to change the representation or not. This isn't as much a big deal in python, for example, where you can @property your getter and setter. In that way you can easily migrate existing code from direct data structure coupling to indirect/computed access.
- huffer 6y ago.. except when manipulating proxy-ed objects, like Spring beans or ORM detached entities. The object you're calling the setter on is not the object (struct) holding the field.. I know, yet another idea thrown into the concepts cocktail.. (not saying these are correct justifications for the getter/setter pollution, just reasons why you find them everywhere in the wild)
- valenterry 6y agoI agree with nimblegorilla: an employee that fires himself does not make sense. HR fires them, or some other entity, whichever has the power and permission, does so. In the end, no matter what example you will pick it will always have the same kind of problem, that a higher entity is needed. And in the cases where that is not true, no encapsulation is needed. For example, "employee.age()". You can just do "olderEmployee = copy(employee, age = employee.age + 1)" (pseudocode) from the outside by having the age exposed (which is not classical OOP at all). But I'm curious if you can find a counter example. Usually it stops working when global constraints come in.
- moocowtruck 6y agoafter doing some smalltalk i think it would be Employee doesn't fire himself, you send him the fire message Employee fire: "immediately" so I kind of see where he's coming from here...
- valenterry 6y agoYeah but that suffers from the problems already mentioned - an employee doesn't fire themselves.
- moocowtruck 6y agoan employee isn't firing themselves, they are being sent the message they are being immediately fired
- valenterry 6y agoSure - then what happens? They notice that they have been fired, but they don't remove themselves from the payroll, or anything like that. So what does the message do?
- Udik 6y agoWhat do you do when you're fired? You collect all your belongings, wipe your machine, and leave. Sure, someone could do this for you, but how would they know that you've left a tracksuit in a locker in the hallway or some cookies in the fridge? Unless the company manages a lot of bureaucracy that keeps track of every single object or resource belonging to the employee.