Here I will try to write up some of the ideas we discussed (thanks to Mike Hill, Nat Pryce, Pippa Newbold, Rob Dupuis and Tung Mac).
Education by frameworks
A lot of the early examples in the Spring documentation are NOJOs. For example, on the page that introduces The IoC container there are several (here's one):
package examples;
public class ExampleBean {
// No. of years to the calculate the Ultimate Answer
private int years;
// The Answer to Life, the Universe, and Everything
private String ultimateAnswer;
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
Similarly, have a look at the JavaBeans on wikipedia - PersonBean.java is a NOJO. I think that there are a lot of developers who think that JavaBeans are NOJOs - as indicated by one of the comments on my NOJO article.
Fear of using the framework incorrectly (the framework won't like it)
It is possible that developers think that the early examples are the "correct" way to use such frameworks - and are worried that if they add methods to their NOJO then the framework will do something peculiar. This isn't entirely unreasonable as sometimes such frameworks do unexpected things due to the amount of behind-the-scenes-magic going on.
Fear of using the framework incorrectly (my colleagues won't like it)
Another possible fear is that that the early examples are the "correct" way to use such frameworks - and doing anything else is not how the framework is intended to be used (even though the framework seems to still work).
Separation of concerns
Another fear is that of putting the behaviour in the wrong place - in particular in enterprise Java projects, I think there is a perception that there is no worse "crime" than putting behaviour in the wrong "layer" (or the wrong sort of class). Therefore, rather than risk putting the behaviour on the wrong object in the right layer, enterprise Java developers will choose to put the behaviour on the wrong class in the right layer. Related to this is a desire to stick to some prescribed pattern - e.g. DTOs. I have been in a situation when pair programming with someone where I was told, "you can't add a method to that" followed by some lame reasoning justified by some pattern that they wanted to stick to religiously.
Afraid of "new"
Yet another fear is that you might have to create a new object (shock, horror!). To avoid that, maybe some developers prefer to write static methods on some Utils class so they don't need to create any objects?
Object-oriented programming education and thinking
Perhaps the popularity of NOJOs is just the manifestation of how developers (don't) learn object-oriented programming? Perhaps object-oriented programming simply doesn't suit how all developers think? Certainly, I've come across very good developers who prefer functional programming and don't really "get" object-oriented programming, so it's not meant to be a criticism (or at least, not in all cases). Many developers have learnt their programming from non object-oriented programming languages, like C. Perhaps it's not suprising that to a C programmer an object looks like a struct?
Intra-team APIs
Another source of NOJO programming is that the APIs that people design for communicating between team's subsystems often involve setting up, sending and receiving NOJOs.
Automated Testing
Another possibility is that developers who are not used to TDD find writing tests that use NOJOs easier than, for example, using Mock Objects.
UML
Using UML to "design" a system up front encourages thinking about the fields of objects rather than their behaviour - because that's what is easiest in notions like UML.
IDEs
Java IDEs can do lots of good things. One of the arguably less good things they do is generate getters and setters if you want. It is possible that the easy generation of getters and setters encourages their use, leading to NOJOs rather than objects that do things with their own fields. Using setter injection (probably the most common way people use Spring) also tempts developers into generating the getters too - after all, it's probably an extra click to not generate getters and what harm can some getters do? (Rhetorical).
Should I care that NOJOs are popular? Should I do anything about it?
Left as an exercise for the reader.
Copyright © 2008 Ivan Moore
2 comments:
The following extracts from Use Case Driven Object Modeling with UML - Theory and Practice elaborate a bit on the 'Education by frameworks' and 'Separation of concerns' sections of your post:
In the Java and C# universes, one (particularly prevalent) school of design encourages you to separate the "real" functionality (the operations) out of the domain classes and put them in separate support classes (validators, DAOs, Controllers, etc.). There has however been much discussion on the Spring message forum about this particular approach.
The problem is that it's possible to "overnormalize" the design and end up with hundreds of tiny classes flying around.
...
Remember the rules of OO design and encapsulation: a class consists of both data (the attributes/properties) and behaviour (the operations/methods). It's a noticeable modern design trend to separate these out so that you get separate classes to handle different aspects of a domain class's behaviour.
While it does make the design more flexible, it isn't necessarily a good thing because (for example) a book is no longer a cohesive, self-contained Book class; it's splintered out into a BookDetailsValidator, a BookDao, a JdbcBookDao, a BookDetailsController, and so on, with each class often containing just one short method.
This type of design is typified by an anemic domain model - that is, a design where the domain classes are all data and no behaviour (NOJOs).
...
we've tried to reach a compromise: using aggregation to link all the itty-bitty classes that Spring wants to see to the Book domain class, and having Book delegate behaviour into these helper classes. We can thus still easily understand our design (all the "bookish" behaviour is in the Book class), while following the "Spring rules" of using validators, DAOs, and so forth.
...
While some separation can be useful in order to satisfy certain design patterns, a balance needs to be achieved between monolithic, thousand-line classes at one extreme, and swarms of tiny classes at the other end.
...
The root cause of the "swarms of tiny classes" problem can be traced all the way back to the technical architecture. For example, see the "layers" diagram...in that diagram, the input validators are shown on the Controllers layer, whereas the domain classes are shown separately, in the Model layer. Really, these should be jammed tightly together, as the validation logic should live in the same class as the data it's validating.
You made no mention of the current popularity of SOA or the resources the big vendors are pushing into their ESB products.
Was this to keep blood pressure in the 3 digit range?
I still have yet to have a sincere answer from anyone as to the difference between a service and a function other than some indistinct mumbling a few words of which sound a bit like "interface".
With the men in blue suits pushing a functional programming model so hard, is it really surprising object orientation is suffering.
Post a Comment