File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes How to make a class smaller Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "How to make a class smaller" Watch "How to make a class smaller" New topic
Author

How to make a class smaller

Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

I've got a fairly large number of "business objects" in my current application, these are domain object, like User, Address, Account, etc.

I generally find that short functions are easier to understand. This seems to be generally accepted, at least from looking at source code for lots of libraries (from Java classes themselves, to Google Collections, many of the Apache commons classes). In addition to short functions (under a page per function, it seems that long classes are bad as well. Thus a Class can be considered smelly when its longer than a certain size, say 500 lines. By the time a class is 1000 lines long, its smelling like three day old dead fish.

My question to the collective brains here on JavaRanch:

How do I make a class that has good coherence, but is rich in functionality, be short? And no wise guy answers like leaving out all the javadoc comments,
or removing whitespace.

What practical suggestions are out there?

Thanks
Pat
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4174
    
  21

1) Locate common code in methods and make it a method of its own.

2) Locate common code in multiple classes and refactor it out to shared classes.

3) Take advantage of inheritance when it seems suitable. Do your domain objects User, Address, and Account share certain features or functionality? Perhaps it makes sense to implement an Abstact parent class which performs those actions.

4) Reduce the functionality of a class and spread it out to multiple classes. A 'super-functional' class can be a bad idea. Perhaps rather than making the class super-functional, make several classes that perform a particular function or several very related functions, then have the super-functional class delegate to those specific task oriented classes (think command pattern-ish where the super-functional class becomes more of a controller which decides which command/function to run but really doesn't do anything itself).

5) Refactor related data and functionality into its own object. Instead of having two variables that must be changed together and a few methods used to manipulate those variables - put both variables and methods into another object.


Steve
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

Steve Luke wrote:1) Locate common code in methods and make it a method of its own.

2) Locate common code in multiple classes and refactor it out to shared classes..


Already done. There is just a lot of code in the class.

Steve Luke wrote:3) Take advantage of inheritance when it seems suitable. Do your domain objects User, Address, and Account share certain features or functionality? Perhaps it makes sense to implement an Abstact parent class which performs those actions.


Already done all the persistance, caching, etc. is already in base classes.

Its just that a Person is a complex thing, and the Person is the center of all known information

Steve Luke wrote:4) Reduce the functionality of a class and spread it out to multiple classes. A 'super-functional' class can be a bad idea. Perhaps rather than making the class super-functional, make several classes that perform a particular function or several very related functions, then have the super-functional class delegate to those specific task oriented classes (think command pattern-ish where the super-functional class becomes more of a controller which decides which command/function to run but really doesn't do anything itself).


Again, this is not a UI class, no display, no DBMS. So it already has the "control" and similar functions in other clases.

Steve Luke wrote:5) Refactor related data and functionality into its own object. Instead of having two variables that must be changed together and a few methods used to manipulate those variables - put both variables and methods into another object.


Not sure I follow you here. Already a Person has an Address class, which contains streetline1, city, state, zip, geociding, etc. all treated as a Address object
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4174
    
  21

"Its just that a Person is a complex thing, and the Person is the center of all known information "

Are you sure that needs to be the case? A Person is a fairly simple thing to define, other than holding the definition of the person, what else does it need (you don't have to answer that question to me, ask that of your code and see if it helps you move things out of the Person and into other things).

Steve Luke wrote:
"4) Reduce the functionality of a class and spread it out to multiple classes... delegate to those specific task oriented classes..."
Pat Farrell wrote:
"Again, this is not a UI class, no display, no DBMS. So it already has the "control" and similar functions in other clases. "

I am not talking specifically about UI classes, or DBMS, I am just talking about delegating responsibility. Does your person walk? Instead of having a walk() method, have a Walker class that can be called like Walker.walk(Person, Location). Look at what your Person DOES, and see if you can move any/all of those ACTIONS into separate task-based classes.

Steve Luke wrote:
"5) Refactor related data and functionality into its own object..."
Pat Farrell wrote:
"Not sure I follow you here. Already a Person has an Address class, which contains streetline1, city, state, zip, geociding, etc. all treated as a Address object "

And hopefully no code in Person actually operates on the Address (changes an value in it, makes it displayable, etc...) all those operations should be in the Address object. Similarly, your Person has a name right? You aren't storing firstName, lastName, middleInitial, fullName are you? Instead you have a Name object which stores those values and makes displayable views right? Similarly for Birthdate/Age operations, Employee Information, etc... A Person should really just be a conglomerate of this information with very little of its 'own' data and functionality. I don't know much about your application but when I have a situations like this my Person usually does very little other than return other Objects which represent the more specific information, and that more specific class has all related view / formatting / manipulating / reading / writing code.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

Steve Luke wrote:"Its just that a Person is a complex thing, and the Person is the center of all known information " Are you sure that needs to be the case? A Person is a fairly simple thing to define, other than holding the definition of the person, what else does it need (you don't have to answer that question to me, ask that of your code and see if it helps you move things out of the Person and into other things).


Yes, I'm sure that a person has to have an address, phone number, cell number, birthdate, gender, name, nickname, etc.

Steve Luke wrote:Does your person walk? Instead of having a walk() method, have a Walker class that can be called like Walker.walk(Person, Location). Look at what your Person DOES, and see if you can move any/all of those ACTIONS into separate task-based classes.



Oh no! That is terrible. The point of OO is that you get code reuse, so if all Human object can 'walk" you just call aPerson.walk() and the person walks in his own way. Perhaps it would be better to have "move" and then they can walk, run, or ride a Segway.



Steve Luke wrote:And hopefully no code in Person actually operates on the Address (changes an value in it, makes it displayable, etc...) all those operations should be in the Address object.


Right, all that is in the contained objects.

At least 80 percent of the code is just setters and getters. But there are a lot of fields, and so there are a lot of setters and getters, and a few useful operations


Perhaps having 1200 lines of code with 50% javadoc comments is really not all that large.
Ulrika Tingle
Ranch Hand

Joined: Nov 24, 2009
Posts: 92
Pat Farrell wrote:How do I make a class that has good coherence, but is rich in functionality, be short?


What do you mean by good coherence? That the class has exactly the right amount of methods? Well in that case it also has exactly the right length. Namley the length required to implement it.

You could make it appear shorter though by applying the usual modularization techniques. One is not to duplicate code but try to write general private methods. Another is to put code elsewhere, for example in implementation classes you use by composition or even by inheritance.

In an application, classes will be distributed along a log-linear scale. This means you will have many short classes, a few long classes and the rest in-between. This is only natural and nothing to worry about. It's only when you've got a substantial number of long classes you know you're probably doing something wrong.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

Ulrika Tingle wrote:What do you mean by good coherence?


Coupling and Coherence are two competing metrics for how related the class is to itself and other classes.

A class with lots of coupling to other classes depends on the other classes, so a change to one will cause changes to the next.

Coherence is a measure of how well the class deals with itself. A person class should have Name, birthdate, and gender, but it would be bad coherence if it has information about bank balances or recent purchases at Amazon.com
Ulrika Tingle
Ranch Hand

Joined: Nov 24, 2009
Posts: 92
Pat Farrell wrote:
Coupling and Coherence are two competing metrics for how related the class is to itself and other classes.


It was more a rhetorical question. The correct terms are coupling and cohesion and I didn't want to nitpick about it, just making sure we meant the same thing.

And If we're talking about a type with good cohesion the answer isn't to break it up. What's left to make the implementation appear shorter is standard modularization. You introduce general private methods if possible and you introduce implementation types. I'm quite fond of inner types but then the actual class file tends to become larger and if you don't want that you can make them package private instead. Anyway this splits up the implementation and makes it appear shorter.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

Ulrika Tingle wrote:It was more a rhetorical question. The correct terms are coupling and cohesion and I didn't want to nitpick about it, just making sure we meant the same thing.


In the rules it says "be nice"

It was not a rhetorical question, and it would have been most useful and easier to understand if you just asked:

"I've head of coupling and cohesion, is that what you mean"

It would have jogged my brain into seeing that I was using the incorrect term.
Ulrika Tingle
Ranch Hand

Joined: Nov 24, 2009
Posts: 92
Pat Farrell wrote:
Ulrika Tingle wrote:It was more a rhetorical question. The correct terms are coupling and cohesion and I didn't want to nitpick about it, just making sure we meant the same thing.


In the rules it says "be nice"

It was not a rhetorical question, and it would have been most useful and easier to understand if you just asked:

"I've head of coupling and cohesion, is that what you mean"

It would have jogged my brain into seeing that I was using the incorrect term.


It's not my style to nitpick about terminology. In any case I've reformulated my advice in my previous reply. There are two things you can use to make an implementation appear shorter: general private methods and implementation types.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: How to make a class smaller