K
kanze
Phlip said:ma740988 wrote:
OO design is about behavior. Classes should tell others what to do. If
a class takes data out of another, manipulates it, and puts it back
in, then the behavior is in the wrong class.
If you indeed share data, then this "data transfer object" should be a
separate thing, without any behavior, and the classes should pass it
around.
Which begs the question: what should you do about these shared objects?
My experience suggests that there are two radically different types of
"data classes". The first are your classical value classes, which
typically, you copy (although if the value has a lot of state, e.g. a
matrix of some sort, you might prefer to avoid copying for performance
reasons). This includes all of the basic types -- a double has a state,
and there is an allowed set of operations on it, but any identity that
it has is fully represented by its value. The second are entity data
sets (or whatever you want to call them -- I've yet to find a good
name). Typically, they are collections of data which have an identity;
if they are copiable or assignable, it is to support transactions and
roll-back, and that is all. Often, I find it useful to support two
interfaces to such classes, one read-only, and a second which allows
mutation. Generally, such classes are maintained by some sort of
dedicated collection or manager. Such classes are, however, usually
pure data; true behavior and business logic are situated elsewhere (and
generally depend on more than one object of this sort).
IMHO, depending on the applications, setters and getters may be
perfectly appropriate for this second category. In other applications,
just using a struct may be even more appropriate.
In the end, I think the warning is appropriate. If you find that most
of your classes, regardless of their role in the system, are full of
getters and setters, you are probably doing something wrong. On the
other hand, if the role of the class is a data holder, then you have
encountered the obvious exception which confirms the rule. Of the many,
many different roles a class can have, there is only one (or very few)
where the exception is really justified. The fact that there are
classes in this role in a lot of applications, and that in some
particular applications, they may even represent the majority of
classes, is irrelevant. It's still just one role.