How much complexity to put in POJOs?

S

Scott Balmos

Hi all,

I seem to have this problem no matter what OO-based language I'm using,
so this is probably not Java-specific. How much accessor/modifier
complexity do you put in your data objects? Do your data objects have
only the standard get/set combos for all data structures, or what
others do you add?

I wish I could provide a good example, but it's Monday, and the
flywheel in the brain is still spinning up to speed.

The best example I can think of is say you have a military personnel
app, with objects representing a soldier and their rank (ie class
Soldier has get/setRank). Would you put, say, function promote() in the
Soldier or Rank object class itself, or in the personnel-management
class(es), and have only get/set methods in Soldier and Rank?

It's this type of drawing the line at how much self-management a data
representation object should have that always trips me up.

Opinions appreciated. Thanks!

--Scott
 
J

Joan

Scott Balmos said:
Hi all,

I seem to have this problem no matter what OO-based language I'm using,
so this is probably not Java-specific. How much accessor/modifier
complexity do you put in your data objects? Do your data objects have
only the standard get/set combos for all data structures, or what
others do you add?

I wish I could provide a good example, but it's Monday, and the
flywheel in the brain is still spinning up to speed.

The best example I can think of is say you have a military personnel
app, with objects representing a soldier and their rank (ie class
Soldier has get/setRank). Would you put, say, function promote() in the
Soldier or Rank object class itself, or in the personnel-management
class(es), and have only get/set methods in Soldier and Rank?

It's this type of drawing the line at how much self-management a data
representation object should have that always trips me up.

Opinions appreciated. Thanks!

My personal style is to not use getters/setters. I rely on my ability
to not step on my foot. However, that said, I am rather fond of "private."
 
F

Filip Larsen

Scott Balmos wrote
The best example I can think of is say you have a military personnel
app, with objects representing a soldier and their rank (ie class
Soldier has get/setRank). Would you put, say, function promote() in the
Soldier or Rank object class itself, or in the personnel-management
class(es), and have only get/set methods in Soldier and Rank?

I almost always end up having the policy code separated from the entity
classes so that each class has a clearcut responsibility. With your
example that would correspond to the three classes: Soldier (entity for
one soldier), SoldierRegister (container operations) and SoldierManager
("pure" policy). SoldierManager would most likely be associated with a
single SoldierRegistry which it manages. If there are a lot of different
management policies that needs to be combined in many ways, the
SoldierManager may end up delegating the different management policies
to, say, SoldierPromotingPolicy, SoldierSaleryPolicy and
SoldierEducationPolicy.

By the way, try get your hands on some good OO modelling and design
books, preferably some that don't let the programming language dictate
design too much. To pick one out of the crowd of such good books, I can
recommend Craig Larmans "Applying UML and Patterns: An Introduction to
Object-Oriented Analysis and Design and Iterative Development".


Regards,
 
S

Scott Balmos

Scott Balmos wrote


I almost always end up having the policy code separated from the
entity classes so that each class has a clearcut responsibility. With
your example that would correspond to the three classes: Soldier
(entity for one soldier), SoldierRegister (container operations) and
SoldierManager ("pure" policy). SoldierManager would most likely be
associated with a single SoldierRegistry which it manages. If there
are a lot of different management policies that needs to be combined
in many ways, the SoldierManager may end up delegating the different
management policies to, say, SoldierPromotingPolicy,
SoldierSaleryPolicy and SoldierEducationPolicy.

Okay, this pretty much matches what I imagine anyway. The question is
between Soldier & SoldierManager. Let's say you want to promote everyone
in your battalion. Some pseudocode for SoldierManager.promote(),
neglecting function parameters, is below.

With a "logicless" Soldier:

SoldierManager.promote()
Soldier[] battalion = SoldierRegistry.getSoldiers()
foreach Soldier in battalion
Soldier.setRank(Soldier.getRank().getNextRank()) // getRank returns
object Rank
Soldier.getServiceRecord().addEntry("Promoted!")
// send out notification emails to HQ, etc

.... as opposed to this foreach in a "smart" Soldier:
foreach Soldier in battalion
Soldier.promote()

Makes sense... Soldier, and other concrete data objects have just
get/set methods, which handle only enforcement of data integrity for the
object type, say before writing to the database (though some may say
this is redundant, considering the database is supposed to enforce data
integrity itself, also).
By the way, try get your hands on some good OO modelling and design
books, preferably some that don't let the programming language dictate
design too much. To pick one out of the crowd of such good books, I
can recommend Craig Larmans "Applying UML and Patterns: An
Introduction to Object-Oriented Analysis and Design and Iterative
Development".


Regards,

Thanks for the recommendation. I'll put it on the list (ever-growing, as
it is...). It's mainly because I still don't have enough experience,
having worked on only two or three "major" projects. I've waffled both
ways in my design methods. That's why I posted this in the first place,
to try and pin myself down to the One True Way [tm], if there was such a
thing.

--Scott
 
I

iamfractal

Scott said:

Hi, Scott,

Excellent question. I think you're hitting this problem, however,
because you're not asking the right question (even though the one you
have asked is ... excellent).

Before diving in, I should say that I like Filip's suggestion
(essentially splitting the Soldier into more single-responsibility
parts) though I wouldn't have used his class names. I'd have
preferred, "SoldierManager," to be just, "Solider;" but that's another
story.

Also, before getting wet, I wasn't sure which of your suggestions you
think is best. You gave the, "Logicless Soldier," example, and the,
"Smart Soldier," example, and said, "Makes sense ..." Which
alternative did you think best?

Anyway, IMHO, to decide which is best, you have to ask a question that
you haven't touched on at all, and realise that this is *not* just a
question of the logical decomposition of a Solder-entity: this is a
question of encapsulation. You have to ask, "How can I maximise this
behaviour's encapsulation?"

Let's presume that you have all these soldier-related classes in a
package called, "fight," which contains the public interface,
"Solier." Your question boils down to asking: should Solider have a
promote() method, or a getRank() method?

This entirely depends on whether the Rank class is used by many
clients outside the fight package: in other words, it depends entirely
on how well encapsulated you want the Rank class (or more specifically,
the ranking behaviour) to be.

If you have many clients outside the fight package that need the
specifics of rankings and ranking behaviours (such as the ranking
succession you alluded to in your example), then it makes sense to
have a public Rank class (or better yet, a public Rank interface) in
the fight package (actually, there are better places for it than the
fight package but that's, again, another story); and so it makes sense
for the Soldier interface to have getRank() method.

If, however, no one cares about the ranking behaviour of your Soldier
outside your fight package, then this behaviour should be as
encapsulated as possible: your Soldier interface should just have a
promote() method.

This doesn't mean either that there must or must not be a Rank
interface, it's just that, if you want a Rank interface, it will be
package-private to the fight package and Soldier will delegate to it
(a second principle, in fact, will come into play here: the principle
of variance encapsulation; if you think that promotion behaviour is
likely to change, then there *should* be a separate, package-private
Rank interface, but that's another blah blah blah).

Also, cilents must make significant use of the Rank interface to
warrant making it a public interface: if the view package (for
example) wants to print a soldier's status, it will certainly want to
know his rank, but it would be more flexible if the view package gave
a some sort of TextStream to the Soldier to let it print out whatever
details it likes (or alternatively, and slighty more ugly, have Soldier
expose method: String getRank()) - this is not sufficient cause to
explose a public
interface.

..ed
 
S

Scott Balmos

Hi Ed,

Yeah, now we're coming to the meat of the problem. I knew it was a
problem with conceptually planning the amount of encapsulation. Like I
said, it's probably a lack of experience. :)

For clarification, I was saying that the logicless Soldier, which Filip
was describing, made sense. The basic jist that I've developed, along
with Filip's response, is that structural data objects should be
concerned solely with representing and maintaining the integrity of the
data they represent. E.g. a Soldier just represents a Soldier, the Rank
just represents the rank (and also knows its relation to other Ranks,
via getLowerRanks(), getHigherRanks(), etc in general).

Actual complex operations on those data objects, aside from simple
property manipulation, should be handled in separate management
classes, collectively the business logic tier. Back to our example,
changing a Soldier's rank to a new rank, in the process of promoting
them, is a simple property manipulation. Thus Soldier.setRank(Rank foo)
makes sense. But the complex operation of promoting (or demoting) a
Soldier, which may involve setting a Rank property, moving the Soldier
from one PayGradeList (extends List) to another, etc etc etc should be
handled in a separate business logic tier object, e.g.
SoldierManager.promote(Soldier luckyGuy).

Your points on object visibility are well-taken. And at the expense of
stretching my off-the-cuff military personnel app example to the
limits, I can say "I get it" for the most part. :D

Thanks.

--S
 
T

Thomas G. Marshall

Scott Balmos coughed up:
Hi all,

I seem to have this problem no matter what OO-based language I'm
using, so this is probably not Java-specific. How much
accessor/modifier complexity do you put in your data objects? Do your
data objects have only the standard get/set combos for all data
structures, or what others do you add?

Hah! Join the club. This is a classic OO question. In fact, I might
regard it as /the/ question, and as you have already figured out, it all
"depends".

....[rip]...
It's this type of drawing the line at how much self-management a data
representation object should have that always trips me up.

Opinions appreciated. Thanks!


Scott--- *please* post this question to comp.object. You'll get a very
valuable conversation in there!

I'll look for it.

Thomas



--
Puzzle: You are given a deck of cards all face down
except for 10 cards mixed in which are face up.
If you are in a pitch black room, how do you divide
the deck into two piles (may be uneven) that each
contain the same number of face-up cards?
Answer (rot13): Sebz naljurer va gur qrpx, qrny bhg
gra pneqf naq syvc gurz bire.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top