My OO projects were usually in Java with a DB. They all ran afoul of what Martin Fowler calls the Anemic Domain Model. Basically your objects are data-only, so there's no benefit. In addition Spring injection became ubiquitous, and further killed objects with behavior. The only project using a DB and had objects with behavior was an old one that happened to use TopLink as an OR mapping.
> Basically your objects are data-only, so there's no benefit.
This makes me wonder why most of us use Java at all. In your typical web app project, classes just feel like either:
1) Data structures. This I suspect is a result of ORM's not really being ORM's but actually "Structural Relational Mappers".
- or -
2) Namespaces to dump functions. These are your run-of-the-mill "utils" classes or "service" classes, etc.
The more I work in Java, the more I feel friction between the language, its identity(OO beginning to incorporate functional ideas), and how people write in it.
Java was the first popular language to push static analysis for correctness. It was the "if it compiles, it runs" language of its day, what meant that managers could hire a couple of bad developers by mistake and it wouldn't destroy the entire team's productivity.
I'm not sure that position lasted for even 5 years. But it had a very unique and relevant value proposition at the time.
OCaml would like to have a word with you. In 2005 it already had better static analysis and correctness on object oriented stuff than what Java struggles to approach today.
OCaml is also from 1996. And I say 2005 because that's when I started using it, not when it started being useful.
By that time it supported parametric generics, multiple inheritance, named parameters, optionals instead of nulls everywhere, compile to machine code and quite a few extra things that I couldn't understand at the time.
A lot of that is down to how people rely on frameworks that force them into "convenient" abstractions. Like Spring and Hibernate. But those are not the language. They represent a (vocal) subset of programmers.
You don't need an ORM or an overgrown dependency injection framework to create a webapp in Java.
Service classes are the thing I hate most. They’re just namespaces for functions. They’re a product of Java not being able to have top level functions.
Not everything can be associated to a single entity. Many operations work on two or more entities where none of them are the "master". Otherwise you end up with "coordinators".
Users.create(...) is the easy case. Try transfer_permissions(user1, user2, entity) while retaining transactionality and the ability of either user to cancel the transfer.
I'm not sure why having a global function by the same would make this any easier or harder to implement. But it would pollute the global namespace with highly specific operations.
It doesn't have to be a class. It can be an interface. And regardless of what it is, it has to go somewhere. Whether it's in assorted_functions.c or Permissions.java makes little difference.
I mean it makes sense to group "like" things together. Whether that's in a module, a class, an interface, or a namespace. Having a huge number of things globally is just confusing pollution.
Yes, but going as a static method into a class that goes into a module is overkill vs just putting it in the module.
> Having a huge number of things globally is just confusing pollution.
I don't know what language you use, but modern programming languages allow specifying what to import when importing a module. You don't have to import everything from every module.
OO conflates many different aspects that are often orthogonal but have been conflated together opportunistically rather than by sound rigor. Clearly most languages allow for functions outside classes. It's clearly the case today especially with FP gaining momentum, but it's also clear back then when Java and the JVM were created. I think smalltalk was the only other language that had this limitation.
I've read his book "Domain Modeling Made Functional" without much prior knowledge of F#. He provides some compelling examples and some of it ended up inspiring how I write OO code. F# seems cool but it felt like it was close to being extinct.
Honestly one of the best books I've read about programming. It's inspired me to try the language out just for fun things, think I'm going to use it for Advent of Code this year. I think it does benefit from being interoperable with C# so you can use it where it makes sense and still have C# to fall back on. Kind of like Scala/Kotlin with Java.
Java is a waste of time for the reasons you said. People use it for legacy reasons. Back then, the alternatives like JS just weren't there yet in several spaces like backend. Your alternatives were even more cumbersome like C++.
OO fatigue is a healthy symptom of readiness to move to clojure, where data and functions are free to live without encapsulation. No king of nouns, no king of execution!
I don't think anyone sets out to make an anemic domain model, it just happens. Lots of developers start with POJO's for JPA models and then never advance them into being full fledged objects when the requirements develop.
Surely that's a conscious design decision? Deciding to create data-carrying POJOs with JPA annotations is a valid strategy. Mixing in a bunch of logic and non-JPA state with them is a recipe for disaster. If you want your classes to Do Stuff, you have to design them to Do Stuff.
I dislike the term "anemic domain model", it casts a value judgment which I think is unwarranted. There's a spectrum from anemic to obese (for want of a better word). There are tradeoffs all along that spectrum. Finding a sweet spot will depend heavily on what you're doing, why you're doing it, what your team is comfortable with etc.
I genuinely believe its not a conscious design decision. Most people never properly learn how to turn things into objects. I've seen this happen in many projects across many companies. They simply just write procedural code without centralizing their logic anywhere.
Does it have to be? Java is a hybrid paradigm language. It's perfectly fine to write data-oriented code. And if you're using an anemic model, there's no point paying the overhead price of fully fledged classes.
I meant, if you want to evaluate OOP by itself, you can't use things that break the paradigm. Java broke that probably because they realized OOP isn't always a good idea, after sticking to it up through v7.