Software Development

Rule of 30 – When is a method, class or subsystem too big?

A question that constantly comes up from people that care about writing good code, is: what’s the right size for a method or function, or a class, or a package or any other chunk of code?
 
At some point any piece of code can be too big to understand properly – but how big is too big? It starts at the method or function level.
 
 
 
 
 
 
In Code Complete, Steve McConnell says that the theoretical best maximum limit for a method or function is the number of lines that can fit on one screen (i.e., that a developer can see at one time). He then goes on to reference studies from the 1980s and 1990s which found that the sweet spot for functions is somewhere between 65 lines and 200 lines: routines this size are cheaper to develop and have fewer errors per line of code.

However, at some point beyond 200 lines you cross into a danger zone where code quality and understandability will fall apart: code that can’t be tested and can’t be changed safely. Eventually you end up with what Michael Feathers calls “runaway methods”: routines that are several hundreds or thousands of lines long and that are constantly being changed and that continuously get bigger and scarier.

Patrick Duboy looks deeper into this analysis on method length, and points to a more modern study from 2002 that shows that code with shorter routines has fewer defects overall, which matches with most people’s intuition and experience.

Smaller must be better

Bob Martin takes the idea that “if small is good, then smaller must be better” to an extreme in Clean Code:

“The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that. Functions should not be 100 lines long. Functions should hardly ever be 20 lines long.”

Martin admits that “This is not an assertion that I can justify. I can’t produce any references to research that shows that very small functions are better.” So like many other rules or best practices in the software development community, this is a qualitative judgement made by someone based on their personal experience writing code – more of an aesthetic argument – or even an ethical one – than an empirical one. Style over substance.

The same “small is better” guidance applies to classes, packages and subsystems – all of the building blocks of a system. In Code Complete, a study from 1996 found that classes with more routines had more defects. Like functions, according to Clean Code, classes should also be “smaller than small”. Some people recommend that 200 lines is a good limit for a class – not a method, or as few as 50-60 lines (in Ben Nadel’s Object Calisthenics exercise)and that a class should consist of “less than 10” or “not more than 20” methods. The famous C3 project – where Extreme Programming was born – had 12 methods per class on average. And there should be no more than 10 classes per package.

PMD, a static analysis tool that helps to highlight problems in code structure and style, defines some default values for code size limits: 100 lines per method, 1000 lines per class, and 10 methods in a class. Checkstyle, a similar tool, suggests different limits: 50 lines in a method, 1500 lines in a class.

Rule of 30

Looking for guidelines like this led me to the “Rule of 30” in Refactoring in Large Software Projects by Martin Lippert and Stephen Roock:
 
“If an element consists of more than 30 subelements, it is highly probable that there is a serious problem”:

  • Methods should not have more than an average of 30 code lines (not counting line spaces and comments).
  • A class should contain an average of less than 30 methods, resulting in up to 900 lines of code.
  • A package shouldn’t contain more than 30 classes, thus comprising up to 27,000 code lines.
  • Subsystems with more than 30 packages should be avoided. Such a subsystem would count up to 900 classes with up to 810,000 lines of code.
  • A system with 30 subsystems would thus possess 27,000 classes and 24.3 million code lines.

What does this look like? Take a biggish system of 1 million NCLOC. This should break down into:

  • 30,000+ methods
  • 1,000+ classes
  • 30+ packages
  • Hopefully more than 1 subsystem

How many systems in the real world look like this, or close to this – especially big systems that have been around for a few years?

Are these rules useful? How should you use them?

Using code size as the basis for rules like this is simple: easy to see and understand. Too simple, many people would argue: a better indicator of when code is too big is cyclomatic complexity or some other measure of code quality. But some recent studies show that code size actually is a strong predictor of complexity and quality – that

“complexity metrics are highly correlated with lines of code, and therefore the more complex metrics provide no further information that could not be measured simplify with lines of code”.

In ‘Beyond Lines of Code: Do we Need more Complexity Metrics’ in Making Software, the authors go so far as to say that lines of code should be considered always as the ‘first and only metric’ for defect prediction, development and maintenance models.

Recognizing that simple sizing rules are arbitrary, should you use them, and if so how?

I like the idea of rough and easy-to-understand rules of thumb that you can keep in the back of your mind when writing code or looking at code and deciding whether it should be refactored. The real value of a guideline like the Rule of 30 is when you’re reviewing code and identifying risks and costs.

But enforcing these rules in a heavy handed way on every piece of code as it is being written is foolish. You don’t want to stop when you’re about to write the 31st line in a method – it would slow down work to a crawl. And forcing everyone to break code up to fit arbitrary size limits will make the code worse, not better – the structure will be dominated by short-term decisions.

As Jeff Langer points out in his chapter discussing Ken Beck’s four rules of Simple Design in Clean Code:

“Our goal is to keep our overall system small while we are also keeping our functions and classes small. Remember however that this rule is the lowest priority of the four rules of Simple Design. So, although it’s important to keep class and function count low, it’s more important to have tests, eliminate duplication, and express yourself.”

 
Sometimes it will take more than 30 lines (or 20 or 5 or whatever the cut-off is) to get a coherent piece of work done. It’s more important to be careful in coming up with the right abstractions and algorithms and to write clean clear code – if a cut-off guideline on size helps to do that, use it. If it doesn’t, then don’t bother.
 

Reference: Rule of 30 – When is a method, class or subsystem too big? from our JCG partner Jim Bird at the Building Real Software blog.

Jim Bird

Jim is an experienced CTO, software development manager and project manager, who has worked on high-performance, high-reliability mission-critical systems for many years, as well as building software development tools. His current interests include scaling Lean and Agile software development methodologies, software security and software assurance.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
pschwarz
pschwarz
11 years ago

After saying “Functions should hardly ever be 20 lines long”, Bob Martin goes on to say, of a program written by Kent Beck, “every function was just 2, or 3, or 4 lines long, each was transparently obvious, each told a story, and each led you to the next in a compelling order”. That’s how short your functions should be.

✯ Verified อ_อ
11 years ago
Reply to  pschwarz

Does that scale to 1 million lines of code?

Anonymous Coward
Anonymous Coward
10 years ago
Reply to  pschwarz

I’m just reading Bob Martin’s book. I think he doesn’t consider an aspect which is IMO crucial to how the human brain works. We don’t work with code of a given size, we work with ensembles of symbols. The more symbols in a given context, the harder we comprehend that context. Contexts are hierarchical, and roughly identical to programming artefacts – projects, packages, classes and methods. So if you want to keep your system comprehensible at all levels/ keep all contexts that make up your system, there are two things you should do: * make sure you can reason in… Read more »

dapeng liu
dapeng liu
11 years ago

“a class avg 30 methds, avg 900 lines” is absurd, any class grows more than 300 lines is absurd imo

James S
James S
10 years ago

I have to say, this is absolute futile speculation. How can you quantify how large a function should be when a lot of it is 1 – domain specific, 2 – language specific ( and moreso api), 3 – purpose specific ? If you are coding some realtime system in C, or system coding in C++ , especially where there are complicated algorithms in which separation would be arbitrary, putting a metric is like that makes no sense at all. Let’s look at ownership, something a Java coder rarely does ( usually just hoping gc figures it out and removes… Read more »

Haihao Y
Haihao Y
9 years ago
Reply to  James S

Honestly speaking, I think the overall principle is not to keep your code in 3 line exactly. Simplify the logic of an algorithm is not easy so that’s why remarkable programmer would work their ass off to achieve it. Yes, there is certain scenario that the logic is extraordinary hard to break, e.g. implementation of any datastructure. However, if you decide to implement such algorithm ask yourself if there is a clear way to achieve it? In your example the implementation radix sort isn’t ridiculous. I think 30 – 50 lines are acceptable. However, if you saying the algorithm can… Read more »

Ankit shrivastava
Ankit shrivastava
9 years ago

how to find avg complexity , avg depth, classes, class size, method per class, statement per method, statement, files of eclipse checkstyle plugin.

leonps
leonps
8 years ago

Large methods are great for job security, if your company is has weak management or technically challenged.

Back to top button