Say I have a class Person
that has instance variables age
, weight
, and height
, and another class Fruit
that has instance variables sugarContent
and texture
. The Person
class has no methods save setters and getters, while the Fruit
class has both setters and getters and logic methods like calculateSweetness
. Is the Fruit
class the type of class that is better practice than the Person
class. What I mean by this is that the Person
class seems like it doesn't have much purpose; it exists solely to organize data, while the Fruit
class organizes data and actually contains methods for logic.
-
So, a Person has setters for height, weight and/or height, right? Setters would be pointless unless there is logic that manipulates these attributes somewhere. Is that logic in a correct class?– COME FROMCommented Dec 10, 2012 at 10:02
-
@COMEFROM: you are right, that is the question to be asked here. However, in information systems it is not uncommon that the whole purpose of some attributes is that they are stored, shown and reported in that system, without any real logic (business processes actually using that attributes may exist outside of the information system).– Doc BrownCommented Dec 10, 2012 at 12:36
-
@Doc Brown: I know and I agree. I don't see anything wrong with classes without logic but having setters in such class is somewhat suspicious. I would check where these setters are needed. Like you wrote: add functionalities to a class when needed. A setter is a functionality.– COME FROMCommented Dec 10, 2012 at 13:38
7 Answers
If your person is actually not doing anything, then there is no need to have any actions on it. It is possible to have classes which only collects data and then there will be classes which operates on this data. In your case, it may be possible that you do not have any action on single person, but there may be action on group of persons, like CalculateAverageHeight(). In this case it makes sense to have only Person without action and then have another class (may be friend) which works on this.
-
1I wouldn't say it was "common" to split your data and logic into different classes in a properly-designed OOP system. For your example, I would expect
CalculateAverageHeight()
to be a static method onPerson
which takes a collection ofPerson
objects. That way, even thoughCalculateAverageHeight()
isn't applicable to an individual instance ofPerson
, you are still keeping it close to the data it operates on.– TMNCommented Dec 10, 2012 at 14:02 -
1@TMN - Sorry for the common word. It is not common, but possible. I disagree that Calculation of average height is closely related to the person class. Consider another function HighDensityArea(), which finds out which is the area in which most of the population resides. This function only needs the address field of the person. There is no need for binding this closely with the Person class.– Manoj RCommented Dec 10, 2012 at 14:25
It is difficult to come with a rule saying all classes must have some logic. In general classes without any logic are considered to be AnemicDomainModel.
Even then, it is better to organize data if the related information is getting large. For example in this case you may still need a collection of Person than many unrelated collections.
-
3I don't think this (AnemicDomainModel) is always true just because you have no logic. In fact, I think that many basic Entity types are just this: a collection of information all related to one particular object, but without any particular logic connected with it. A Person just ... is, yet it would be hard to argue you shouldn't have a class to represent a Person. Commented Dec 10, 2012 at 6:39
-
@ Peter Rowell : The Entity (bean) from J2EE gets special mention in the article.– JayanCommented Dec 10, 2012 at 6:59
-
1
-
A good working definition of Anemic Domain Model is a domain where business rules must exist to enforce data integrity within an object, but those rules are not encapsulated within the same object. If an object doesn't need logic to maintain an internally consistent state, such as a Money pattern, then it shouldn't have said logic. However, if an Invoice has a Subtotal data property that should always be the sum of its line items' Extended Costs (each of which is in turn Unit Price * Quantity), then those properties should be calculated and not directly settable.– KeithSCommented Dec 10, 2012 at 18:49
-
If you have many classes that are like this you have a problem. However, sometimes you simply want to organize some data items but there are no methods that don't make more sense elsewhere. Commented Dec 10, 2012 at 22:46
The DataTransferObject is a good example of a class that has no logic, only data. That's its purpose, though; it's explicitly an exception to the general rule that all classes should implement the business logic that affects their internal state. Having a class whose internal state is changed by external logic is often a design smell. It's not always wrong, but it's almost always something that you should consider refactoring.
Reverse the question, look at the other end. If you have a collection of information that obviously belongs together, should you keep it apart just because there are no methods which you could add to that class? Should you be forced to invent arbitrary methods just to justify the class?
Models are no end to themselves - you should add functionalities to a class when you really need them in your program, not on guessing that you will need them probably in the future. So its natural that at one point in time you have classes with no "real" methods, and later, when you determine that it makes sense to add methods to the class, you do exactly that. The quality of a model is not measured by "do I have methods here and no methods there" - the quality is measured by "do I have all the methods my application actually needs in there".
For example, when your application in version 1.0 needs something like calculateSweetness
for a Fruit
, but does no operations on a Person
except getting and setting the attributes, then your model should exactly reflect that by not having any logic in the class Person
. In version 2.0, it may make sense to add some logic to a Person
too, so when you are at that point, add the methods in question.
I think this depend on the language and how you are using the language.
In the trivial case some languages insist on everything being in a class, so e.g. collections of constants have to go into a class which then may or may not have any logic, in other languages they might end up in a namespace instead.
In multi-paradigm languages it can also depend on what paradigm you want your design to adhere to. Borrowing the example of CalculateAverageHeight(), as is it probably should reside in a PersonCollection class, however that presupposes an OOP solution. in a more Functional design you might use a higher order function with a generic collection, e.g. in C#
List<Person> personList = GetListOfPeople();
personlist.Average(p => p.Height);
and then the logic is not in PersonCollection or even statically in Person. Indeed higher order functions and generic data types in general mean you are more likely to end up with objects that are just bags of data, as the logic is operating at a higher level of abstraction then your specific data model.
It sounds like what you are talking about is a POD (plain old data). Different languages can represent these in different ways - it could be a class with public members for instance, or a struct with only public members in C++.
Organising data is a perfectly valid reason for a class to exist - it can often make code cleaner and easier to read. std::pair
in C++'s STL is a good example of a structure that exists solely to organise data - simply a struct that holds two values of any type named first
and second
. Probably one the most useful classes in the entire STL (in my opinion anyways :) )