This occurs when you have less than 10 methods per class and when no method is longer than 10 lines.
for another compatible approach and http://citeseer.ist.psu.edu/basili95validation.html
for validation that bigger classes are more error-prone.
- Easier to test.
- Easier to reuse.
- Easier to modify.
- Less bugs are discovered, statiscally, on short methods and on short classes.
- Development team codes faster, because there is less need for refactoring.
it is mentioned: Avoid gratituous requirements along the lines of "every method must have 10 lines of code or less; every class must have 20 methods or less." There only push code elsewhere, they do not improve the quality of your system.
Then it is mentioned that reuse is too hard to achieve. It is mentioned that this should be called PolyBloodyHardReuse
, because it is so hard. I think these two statements are not coincidence. Having big classes makes reuse hard, if not impossible. Most reusable classes have very few methods, each with very few parameters. And if that reusable class is to reuse other code, then it won't copy and paste it, but invoke it, where ever it is. This means that most methods are short. This is a simple rule of thumb that is a requisite for reuse. You also need to reuse that code several times to make sure that it is actually reusable.
You can also try FewShortClassesPerMethod
is the opposite of ManyShortMethodsPerClass
. It consists on having FewShortMethodsPerClass
. It is considered better than ManyShortMethodsPerClass
is an improvement over VeryLongMethods
, but at the same time it shows some FearOfAddingClasses
How much is few methods? I would say 10 methods per class is the maximum. If there are more than that, consider refactoring. However, you might consider not counting getter and setter methods if your laguage requires such methods.
To see why this is important, see MassiveFunctionHeaders
On C3 methods had 3.8 lines of code on average. This was taken from OnePieceOfPaper
Also the class size must be reduced in order to get higher quality code as indicated by the following: ''The size of the median for changed classes is thus 3.9 (175.0 / 47.0) times
greater than the size of the median for unchanged classes.'' This was taken from http://fc-md.umd.edu/mikli/LindvallSPE98p.PDF
Rationale: One liners are ok. It is easy to test one liners and otherwise verify that they are correct.
Big methods are hard to test. Also they tend to get modified often. If one could write a system so that all methods were one liners that would be great, but what would you do with loops and recursions? It doesn't seem reasonable.
A method with more than 10 lines is way too big. I do not advocate that the compiler should reject it, only flag that method as a method that needs to be refactored. There may be other priorities. All projects, I suppose, arrive to a point when developers think the project is out of control. Putting more time and effort into it only makes it worse. Usually a different attitude is needed: Look back into the time when the project was on the right trail. Remove all features that may have broken the system, reapply them carefully and test everything on every step.
YMMV, others simply apply extensive logging, but the result is the same: the project is halted because we are trying to see what went wrong. At this point UnitTest
s are invaluable. But they may be not enough. Testing everything in isolation makes you feel confident. Have you really tested everything? CodeCoverage
tools may help. Having small methods of course helps, specially if they are tested throughly.
This is a nice statement of a desired result, but without a method to achieve the result, it is of no value. Just refactor code as appropriate and don't worry about method length or the number of methods per class. These issues will just take care of themselves.
Or do CodeReviews, PairProgramming, CodingConventions and SoftwareMetrics that tell you that this and that method are too long. You should refactor them in smaller methods. Then classes will have too ManyShortMethodsPerClass, divide them in several classes.
Saying that a method is too long or a class has too many methods provides no insight in reducing size or quantity respectively. If one knows the approaches needed to keep methods short and classes small, then one will apply those techniques. On the other hand, if one just randomly chops up methods or classes in order to make some metric pass, one will do more harm than good. Although a logically decomposed method or class is ideal, it is better to have larger methods or classes than randomly decomposed methods and classes.
That's why long methods and classes are called code smells, not code heresy.
Somebody who's looking for techniques for decomposing code could start browsing through CategoryRefactoring
The key idea is not short methods nor few methods per class. The key idea is ConceptualSingularity
. The class has one and only one purpose. All methods support a single, singular purpose and nothing else. All code in those methods support the single purpose and nothing else.
When a class is singular, it tends to be "small" simply because every line you add potentially disrupts the ConceptualSingularity
of the class. A "small" class tends to have fewer methods, again, simply because every method you add increases the probability of contaminating the singular purpose. Methods tend to be short for the same reason.
If you aim for a class with ConceptualSingularity
, it will tend to have (though not necessarily have) FewShortMethodsPerClass
. As counterpoint, it's possible to have, for example, a class with many long methods while retaining ConceptualSingularity
. It's rare, but possible.
tends to be very stable. If you have all of the functionality for a given purpose (within the bounds of your domain) in a SingularClass
, there is little need to change it (unless your domain changes). You've captured everything there is to know about a currency exchange rate, for example, in a CurrencyExchangeRate?
class. Unless the definition of a currency exchange rate changes (i.e. the domain changes), the CurrencyExchangeRate?
class will remain very stable. On the other hand, if the CurrencyExchangeRate?
also handles file I/O, Gui presentation, etc. it will change more often because you now have multiple agents affecting force on the class to change. The currency exchange rate functionality remains stable, but the file I/O changes, or the GUI demands change, etc.
Duplication exists because there is a blob of functionality that is being spread like jam across a wide area of code. Extract that blob of functionality into a SingularClass
and the duplication goes away. Why? If the Frimfram class does all of frimfram and only frimfram, then whenever you need frimfram functionality, where do you go? to the Frimfram class! A SingularClass
becomes a lightning rod for all the code that needs to use the class's functionality. Look at the DesignPatterns
code. Classes so sparse they are almost vapor. Singular, and therefore applicable and reusable across a vast number of applications.
Here's an experiment: take a relatively small class and go merciless on it. Refactor it as much as you possibly can. When you're done, look at any class that has multiple member variables in it. Can any one of the member variables exist separately from the others? Split off that member variable into it's own class (even it seems absurd to you...). Can the methods be partitioned into methods that work on variableA and methods that work on variableB? Split the sets of methods into two classes. Can any part of the class be made more abstract? Extract out the abstract part into a new class. Continue doing this until you can't refactor any more. Bring in a buddy. Ask him/her to go through the remaining classes looking for classes with one or more different "kinds" of functionality in them, e.g. a money class with currency information held within it. Split the class up based on the functionality. When you're done, you will have singular purposes classes. Repeat this experiment over and over again. After two years go back and take another look at your first attempt. Split the classes up even further on what you now see...
-- John Arrizza