CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Eric Wise

Business & .NET

What does 10 lines give you anyway?

While I agree with 95% of Jeffrey's post I have to throw down the gauntlet on the magic number of 10 lines in his suggestion.  Just as "magic numbers" are rather undesirable in code, the concept that a method should be constrained by a number of lines is undesirable as well.

<rant>For me, this brings back memories of writing assignments in school where the teacher would insist that you write 1500 words.  What if you could elegantly cover the topic in 1000?  What made 1500 so damn special anyways?</rant>

Anyways, I digress.  What I think should be said in place of the 10 lines concept is that wherever possible, a method call should be a complete thought / task.  Most tasks can be divided into subtasks which are thoughts on their own.

The thing you really have to watch out for though (and the thing that prompted this post) is "code hop".  Code hop is when someone takes the 10 lines concept and goes way too far with it.  If I have to jump into more than 4 files just to follow a method call through the code, it's almost as bad as having a method of 60 lines.  At least with the 60 line method I can easily see the flow and steps that are being taken without having to jump around.  The downfall of the 60 line method is that the steps are not broken out to be reusable.

So that's really the distinction I want people to make.  Go for simplicity and readability first.  Splitting out everything all over the place isn't simple or readable, nor is dumping everything into a super method.  Organization of code is somewhat of an art, and is another one of those things that coders can really benefit from exploring the code of others. 

Bottom line if you're walking through my code, if something isn't meant to be reused, I tend to have a longer method to keep complete thoughts together.  I can always pull out chunks of code refactoring to make it reusable if the need arises.  I also don't mix major tasks, data retrieval is not mixed with business logic, etc.  But those are "thoughts" as described above.

Fun semantic argument either way.  ;)



Comments

Jeffrey Palermo said:

Thanks for "throwing down the 'gauntlet'" on something I clearly labeled as "my pain point".

You missed my point completely by choosing to focus on one tiny thing you found to disagree with.  Congratulations.
# April 11, 2006 8:43 AM

rsakalley said:

I agree with you in a way, classic example is a the IntializeComponent() method. Many a time, you have to re-initialize controls on a form based on some kind of data/user input, the code for which might run into a 100 lines at times, and breaking such a function into smaller units would be an overkill. A function/method should be a logical unit, and while most logical units can be written within 10-20-30 lines, some might not. Having said that, there are no excuses to ignore basic function/method design guidelines and leave these over for refactoring later.
# April 11, 2006 8:45 AM

Ridge said:

That's the funniest 'first post' comment, ever.  Congratulations.
# April 11, 2006 9:03 AM

Bjørn Reppen said:

Eric, please go check the cyclomatic complexity of the code you have written, if it's high as I suspect, shame on you. :-P

# April 11, 2006 10:25 AM

Marc said:

@Ridge: I just thought the same thing... how am I supposed to take somebody seriously who writes

> You missed my point completely by choosing to focus on one tiny thing
> you found to disagree with.  Congratulations.

Sheesh...
# April 11, 2006 10:55 AM

Eric Wise said:

Speaking of missing the point completely.  The problem I am addressing is the one that rsakalley alludes to.  When you break up your code for the sake of breaking it up rather than to logically separate concepts for re-use.  I would advocate that putting some magic line number constraint is a "pain point" not because of anything to do with the skills of the developer, but because the arbitrary goal is flawed.

Imagine reading a book where you had a few lines on page one, and then in parens you get (see page 50), then a few more lines and then more parens (see page 101).  This sort of disjointed view of the sourcecode can severly inhibit readability and I cringe at the thought of coding newbies busting up cohesive code just to meet some magic number from a peer.

Real World Example.  Let's say you have a method LoadUserById(id).  It initializes a return object (user), grabs some data into a data reader, parses the return row columns to be put into the props, and returns the user object.

Each of these could be put into their own separate method calls, a few of them (like executing a stored procedure for a datareader) should be.  But would we gain anything by breaking the population of properties into it's own method?  If we're reusing it then yes, something like PopulateUser(datareader dr, User user) might make sense.  If we're not reusing it then we just introduced a hop for no apparent reason.

Taken to extremes that I've encountered in cleaning up bad consulting.  The whole app was using in-line sql and all they wanted was to go in and change the sort order of a report return.  The code was so split apart with poorly named methods that you had to run the debugger to find what you were looking for.  Following the debugger from the page request to where the sql actually got executed literally walked through 3 dlls and 15 files.  Many of the methods were just wrapper calls to other methods, taking up space for little apparent reason.  If you had to make multiple changes along that executing path it would add complexity, cost, and time.
# April 11, 2006 11:30 AM

Jeremy D. Miller said:

I think everybody has a good story about bad consultants.

You don't split methods up just for possible re-use, you do it to make the code easier to understand and test.  Your LoadUserById/PopulateUser() is a good example.  Splitting stuff like PopulateUser() into separate methods IS valuable because you can see the overall flow of the parent LoadUserById() method without getting bogged down by the details of which IDataReader column goes into what User setter.  

Look at the Compose Method refactoring from Joshua Keriesvky's book --> http://www.industriallogic.com/xp/refactoring/composeMethod.html.  That's what small methods, with good names, can give you.

Invest just a little bit of time in the code navigation shortcuts in VS/ReSharper and you can easily bounce around the code.

Just to be a smartass because I know you're skeptical of all things agile, if you were doing TDD with granular unit tests you probably wouldn't have to spend nearly as much time in the debugger.

# April 11, 2006 2:54 PM

johnwood said:

I think you codebetterans need to get a little more sleep and stop snapping at each other :)
# April 11, 2006 4:27 PM

Josh said:

Eric - you really are missing the point. You missed it the first time with the post, and then after Jeffrey calls out the flaw in your argument, you go and reiterate how you missed it.
"I would advocate that putting some magic line number constraint is a "pain point""
Nobody advocated a magic number constraint. Jeffrey never said "*YOU* should not create a method over 10 lines." Jeffrey never said "*I* never create a method over 10 lines." If he had made either of those statements, your disagreement would be understandable.

He basically said "I don't LIKE it when MY methods go over 10 lines".

How can you argue with that?
# April 11, 2006 8:59 PM

Geoff Appleby said:

It's funny, because it certainly read to me like he was saying that no method should be more than 10 lines.
# April 12, 2006 2:47 AM

Josh said:

I guess if you go looking for an argument, you'll find one.

What line made you think "no method should be more than 10 lines"?
These are the lines I read (*starred* emphasis mine) and understood as a personal guideline - not a hard and fast law that everyone must live by.


"Here are *general rules* I try to live by"

"The method *should* be viewable without scrolling.  Fewer than 10 lines of code is *desirable* (*my* pain point)."
# April 12, 2006 9:40 AM

Geoff Appleby said:

And i certainly guess I found one - thanks for stepping up josh. You are definately looking too, this I can tell.

So you want to analyse the nuances of language do you? For starters, you can stop quoting specific phrases and shouting out that there's nothing misleading. you take a specific phrase out of context, and of course you can find the meaning you're looking for.

But let's take your quotes.

>"Here are *general rules* I try to live by"

You're right. They're general rules, and they're his. And?
Well for starters, he's still called them rules. He didn't call them 'my general rules', he just called them general rules. The inference of this is that these are rules that should apply to everyone.

He's said he tries to follow them. The impression given is that he tries to follow them, and that I should too. That's the first impression I get. What other impression should I take? Well, he can only have listed these rules for one of two reasons. 1) because he thinks that everyone should follow them, or 2) because he's open to discussion on them, perhaps willing to change or remove some.

So which option is it? I stick with (1), because it's clear it's not (2). If it was two, he wouldn't have made a fool of himself in the first comment left on this post. If it was (2), he would have opened a discussion instead of acting all hurt and offended.

Next quote.

>"The method *should* be viewable without scrolling.  Fewer than
>10 lines of code is *desirable* (*my* pain point)."

Should. Why are you highlighting that? You want to get picky about specific word choices? OK then, let's see what 'should' means.

Should: Used to express obligation or duty.

Yes, it's not as strong as 'must' or 'will'. But it certainly leads me to the idea that he's saying it's a rule that had better be followed if at all possible. But the sentence it was used in was to do with 'viewable without scrolling'. Eric never said that was an issue, i've not commented on whether i agree with it or not, so i'll leave it alone.

Desirable. No idea why you're highlighting that word. Yes, it implies that the rule can be broken, but there's no mention of what circumstances cause an allowable exception.

My pain point. Yes, it's *his*. However, like I said above, if it's not open for discussion, then he's laying down the law. Which is it? If it's open for discussion, then hey, aren't some people trying to discuss it? If it's open for discussion, then shut the fuck up josh, and let us discuss it - stop trying to get your childish banter taking over the thread. If it's laying down the law, then shut the fuck up josh, you're obviously wrong by saying that he's not.

Yes, it's Jeffrey's pain point. That's fine. So he's allowed state his pain piont is a certain number, but Eric can't state that his pain point is the existance of any number? So now one person can talk about their own stuff (and if it's not laying down the law, it must be open for discussion right? If it's not, then it shouldn't have been published) but when someone els talks about _their_ own stuff, you have a problem with that because you think they're laying down the law?

Fuck dude.

Me, I'd like to think that all things are open for discussion. And if so, why the hell can't we discuss them? Why do you have to get all high and muighty and defensive? Why does jeffrey have to act like a tool with his comment above?
# April 13, 2006 6:35 AM

Eric Wise said:

jmiller - I can get the effect of seeing the flow of a method in a condensed format without getting bogged down by the details with the nifty invention known as the #region tag.  Thus I don't have to bounce all over the source code and you still get logical grouping and clean looking code.

Of course this whole discussion is a matter of semantics and should be seen as a good dialogue.  At what point are things chopped up too much?  Certainly if I suggested wrapping each sql parameter assignment in its own method so I could test each of them individually you would think I was insane.  Yet I would also take flak for not doing any separation or unit testing at all.  The discussion in my mind was meant to say "how can we dictate where to draw the line without resorting to magic numbers and arbitrary statements like fitting on a screen (your resolution != my resolution)".  The answer to this question, would be far more valuable to the readership.

But that's just my two cents.
# April 13, 2006 8:48 AM

Aaron Erickson said:

If your methods are only 10 lines or less, the methods probably are not doing anything really interesting.

For example, if you try to do this: http://en.wikipedia.org/wiki/Dykstra's_algorithm
and break it up into less than 10 line parts, I am not sure you have made the code any *more* readable, and in fact, have probably done the opposite.

Nobody would advocate for 200 line methods that scan 3 printed pages.  But 10 is clearly too few, and frankly, would contribute to additional code complexity by adding more methods that needed.

That said, if the highlight of your day is taking internal variables, constructing objects from them, and sending them to a database, then perhaps 10 lines gives you enough expressiveness to get the job done in most instances.  Most things that actually add value to a business, however, go a great deal more than that!
# April 13, 2006 11:45 AM

josh said:

Interesting take Aaron. Jeffrey (if youre still listening), can you run some sort of static analysis on one of your real world apps and report how many methods exceed the 10 line threshold? Then report back on whether the application adds value to a business.
If the number of longer methods is more than 10%, then we can assume Aaron is right. If its less than 10% (and assuming your app actually adds value), Aaron is probably wrong. Or we argue about what the acceptable level of rule-breaker methods is - maybe 10% is too many?
# April 13, 2006 2:37 PM

Jeffrey Palermo said:

Yes, I'm still watching this thread.  If I could take back my first comment, I would.  I was a bit short.

I've posted about some code analysis I did here:
http://codebetter.com/blogs/jeffrey.palermo/archive/2006/04/13/142797.aspx

I don't think about the number of lines when I'm coding a method.  I code to satisfy the test that I've already made.  The test is testing one thing, so my method just does one thing.  I have run into situations where I need to perform instructions in a loop.  I end up refactoring the body of the loop into another method for readability.  The size of a good method isn't a rule I made up, but it's an observation.  The end result (small methods) is very favorable.

The methods that _are_ 20 lines of code have good reasons for being so, but they seem to be the exception rather than the trend.
# April 13, 2006 11:02 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!