tags:

views:

1308

answers:

6

Hi, I have to give a general note to some huge java project for which I have but little visibility and I was wondering if there were any guidelines for determining:

  • what number of classes per package can be considered right, to low, or to high (this project has 3.89 classes per package, which seems a bit too small for me),
  • number of methods per class? (this project has 6.54 methods per class...
  • number of lines per method? (this project has about 7 lines per method (seems pretty good to me, maybe a bit low))

I should note that this question is only dealing with volumetry. I have a bunch of reports from quality tools (checkstyle, jdepend, cpd, pmd, ncss) that give me more vision about code redondancy, classes usage, bugs, etc.

+7  A: 

I think stats like that are pretty useless, how does knowing the lines per method show whether its any use to the project or not; i think you should be looking more along the lines of:

  1. Do your packages encompass like classes?
  2. Do your classes work as an entity on their own?
  3. Do the methods within the classes function correctly and efficiently?

Surely other than memory usage, it doesn't matter whether the method is large or not? the other thing to look for in very protracted methods is whether the stack trace is going to be bigger than adding that functionality to a parent method. I'd be wary of measuring a projects success based on the lines of code.

Mauro
i have other stats given through checkstyle, pmd, jdepend, cpd that give me more information about what you are saying. This question relates to volumetry only.
m_oLogin
It absolutely DOES matter how large a method is, since a) a method is read more times than it is written and b) small methods are easier to understand.
Microserf
To a point, yes, but if the number of lines/method were in the 100s or 1000s I would be concerned that there might be problems with the design of the code, making it brittle (and likely not sufficiently tested).
tvanfosson
+6  A: 

Steve McConnell in his book Code Complete recommends about 7 methods per class and no more lines in a method then can be viewed in a single screen without scrolling.

I'm not sure about classes per package.

I would highly recommend reading Code Complete for more information on such topics.

Y Low
I think this recommendation is overly simplistic.We don't split a class into two because they have more than seven methods. We need to think mainly about cohesion.
Victor Rodrigues
+2  A: 

Unfortunately, there's no absolute (objective) notion of quality in software. Thus, there's no "right" value for these. However, here are a two (personal) obsevations:

3.89 classes/package is very low. It means you'll be battling through a complicated tree of packages.

7 Lines per method: Indeed sounds good. However, if these number was arrived at as a result of an intentional effort to reduce the line count of methods then you might have ended up with a single logical task being spread around several private methods which will make it more difficult to understand the class (in certain cases). Actually in CodeComplete-2, the author cites a research which discovered that method length is much less importance than its cyclomatic complexity and its nesting level.

Itay
+3  A: 

Robert C. Martin, who recently released the book "Clean Code", states that the number of lines per method should be the absolutely smallest possible. Between 1-7 lines is a good rule of thumb.

There's also a good point being made in the book The ThoughtWorks Anthology, in the essay “Object Calisthenics” by Jeff Bay. He suggests 9 pretty hardcore constraints that will make you a better OO developer in the long run. Read more about them here.

To answer your specific questions, these are the constraints specifically to you: - No more than 10 classes per package - A maximum of 50 lines per class

These constraints might not be ideal for all of your real projects, but using them in a small (hobby?) project will force you into a better practice.

Microserf
50 lines per class seems pretty small to me, do you count the whole file or only statements? because if it's the whole file then 50 lines is pretty small or doesn't contain comments.
Julien Grenier
The article itself states that "These constraints are intended to be excessively restrictive, so as to force developers out of the procedural groove." The comments there include plenty of good arguments against writing real-world code in that manner.
Dave Sherohman
A: 

A useful design guideline says that each class should only do one thing and do it well. This will not give you a fixed number of methods per class, but it will limit the number and make the class easier to comprehend and maintain.

For methods you can adopt a similar view and aim for methods that are as small as possible, but no smaller. Think of it this way: if you can split the method into two or more distinct parts it is obviously not as small as it could be. Small methods are easy to understand and by splitting the code like this you will get a better overview in high level methods and push details to low level methods.

Brian Rasmussen
A: 

(note: tl;dr available at the very bottom for my real opinion)

I'm not going to quote any big name and say that's the right answer because it's always very case dependant how you do all this stuff. For example the number of methods: If you're making a control software for modern HD LCD TV's remote controller which has about 40-50 buttons, how can you break that down into classes coherently so that you only have like, say, 7 methods per class?

Personally I like to keep all the methods of one accessor level in one class which means some utility classes may end up having hundreds of methods but in my opinions it's easier to do something like StringUtil.escapeXMLspecialCharacters(someString) than StringUtil.XML.escapeSpecialCharacters(someString) or XMLUtil.escapeSpecialCharacters(someString). While these all are seemingly OK solutions, the first one thrives (at least in my mind, that is!) because it's simple and very easy way to access that method: You don't have to think if the string you're handling contains XML or XHTML or JSON or whatever, you'll just pick one method from the general group of methods and that's it.

Keeping on the previous TV remote analogy, lets assume you do split them to various classes anyway. If we allow ourselves to have 7 of such methods per class on average and manage to group the buttons on the remote to sensical groups like MenuButtons, AdjustmentButtons and 'NumberSelectorButtons', we end up with 8 or so classes. That's not a bad thing actually, but it gets slightly confusing easily especially if they're not divided to sensical groups with great care. Just imagine the rants around your TVRemotes'R'Us Inc. office: "Who says the power on/off button is a control button?" "Who's the joker who put volume +/- to menu buttons? PRE/CH (the button which switches between current and previous channel and/or image source) button isn't a number button!" "The guide button opens both tv guide AND navigational menu depending on context, what are we going to do with it!?"

So as you can hopefully see from this example, using some arbitrary number to limit yourself could introduce some unneeded complexity and break the logical flow of the application.

Before I throw in my last two cents, one thing about the number of lines per method: Think code as blocks. Each loop is a block, each conditional is a block and so on and so forth. What is the minimum amount of these blocks needed for a unit of code which has a single responsibility? That should be your limiter, not the desire to have "Seven everywhere." from number of classes in package, methods in classes and lines of code in methods.

And here's the TL;DR:

So, my real opinion is actually this: The number of classes in package should be fairly low. I've been lately starting to do the following but I'm not sure if I'll keep up to it:

  • Package foo contains interfaces and other common classes for implementations.
  • Package foo.bar contains implementation of said interfaces for function bar
  • Package foo.baz contains implementation of said interfaces for function baz

This usually means my whole structure has a coherent (and most likely low) number of classes and by reading the top level class interfaces (and their comments) I should be able to understand the other packages too.

Methods per class: All which are needed as I explained above. If your class can't live without 170 methods, then let it have them. Refactoring is a virtue, not something that can be applied all the time.

Lines per method: As low as possible, I usually end up with 10 to 25 lines per method and 25 is a bit high for me so I'd say 10 is a good balance point for that.

P Arrayah