Avoiding spaghetti code while writing small functions - function

My understanding of "Spaghetti Code" is a code base that jumps from one block of code to another without an logical and legible purpose. The most common offender seems to be the GOTO statement.
I'm currently reading/referencing the function chapter of Clean Code: A Handbook of Agile Software Craftsmanship. The author, while self admittedly, is extremely strict on the size of functions. I understand the idea of keeping functions small, however, he suggests they should be around 5 lines. While Classes certainly become more legible, I'm afraid of creating spaghetti code by writing smaller functions. Smaller functions also seem to inadvertently create much higher abstractions as well.
At what point does code become spaghetti code? How abstract is too abstract? Any answers would be greatly helpful.
As an aside, I'm a long time follower of Stack Overflow although this is my first time posting a question, so any suggestions regarding my post are welcome as well.
Thanks a lot!

As already said in the comments, there is no absolute rule. At the end, you should aim for a good readability of your code. But that is not all about the length of your methods. Robert Martin suggests ordering the methods according to the degree of abstraction. Abststract methods should be at the top of your class, and the more a method is, the deeper it should be located.
Another importand aspect is the method name. It should be chosen well in order to make clear what the method does! If you choose your method names wisely, then comments should be hardly necessary. For example, consider an if-statement:
if(isValidAge(value)) {
...
}
is much more readable than
if(value > 10 && value < 99) {
...
}
because the intention of the statement becomes much clearer. Of cause you could add a comment in the second example. But comments often become outdated (there is an extra chapter in Robert Martin's book about that). I think, this style of programming leads to many short methods.
It is hard to choose the right level of abstraction. According to my expecience, it is easier to start with a low level of abstraction. So I can first concentrate on solving the problem well. When I need more abstraction later, I still can refactor the code. TDD helps a lot!
Hope, this helps ...

I agree with comments and answers here. From practical point of view the thinks which Robert Martin writes in his books are every time very good orientations and I try to get as much close as possible to this "rules" and indeed 5-lines-methodes are mostly not to bad.
In my eyes best way to avoid spaghetti code is to write (small) classes with a high Cohesion. The disadvantage is that you become a whole bunch of classes, which makes it sometimes a little bit more hard for new employees to come in the project.

I understand the idea of keeping functions small, however, he suggests they should be around 5 lines.
That sounds ideal :)
While Classes certainly become more legible, I'm afraid of creating spaghetti code by writing smaller functions.
Spaghetti code is caused by code jumping from place to place with (having different levels of abstraction in the same function - low-level IO code and high level application logic). If you extract small functions, your result is getting further away from spaghetti code, not closer).
At what point does code become spaghetti code?
When the code forces you (the programmer) to make mental jumps (switch contexts) from line to line, the code is spaghetti code. This is true whether you use GOTOs or not (but GOTOs can make the problem much worse).

Related

What terms do you use to describe the nature of a refactorization?

Currently I'm trying to write a good commit comment for a code refactoring I've made.
And I feel like I'm missing a word to sum up what I did instead of describing it.
Right now my description is:
"Code refactor to improve decoupling inside the generator class."
But IMO, it's not really decoupling as it's only inside a class itself. It doesn't have any strong link to the code responsibility. It's more to improve testability of the class by having more smaller methods instead of few big one.
So that led me to a quite simple question:
What are the most common terms you use in your commit messages to describe a code refactoring ?
http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672
Is the defacto standard for basic refactoring vocabulary everywhere I've worked.
Cleaned up implementation of function x within class y, by breaking it into functions a, b & c to make unit testing easier.

What is the golden rule for when to split code up into functions?

It's good to split code up into functions and classes for modularity / decoupling, but if you do it too much, you get really fragmented code which is also not good.
What is the golden rule for when to split code up into functions?
It really does depend on the size and scope of your project.
I tend to split things into functions every time there is something repeated, and that repetition generalized/abstracted, following the golden rule of DRY (Do not repeat yourself).
As far as splitting up classes, I tend to follow the Object Oriented Programming mantra of isolating what is the same from what is different, and split up classes if one class is implementing more an one large theoretical "idea" or entity.
But honestly if your code is too fragmented and opaque, you should try considering refactoring into a different approach/paradigm.
If I can give it a good name (better than the code it replaces), it becomes a function
I think you generally have to think of a chunk of codes have a chance of being reuse. It comes with experience to figure that out and plan ahead.
I agree with the answers that concentrate on reusability and eliminating repetition, but I also believe that readability is at least as important. So in addition to repetition, I would look for pieces of code (classes, functions, blocks, etc.) that do more than one thing.
If the name associated with the code does not describe what it does, then that is a good time to refactor that code into units which each have a single responsibility and a descriptive name. This separation of concerns will help both reusability, and readability.
Useful code can stick around for a long time, so it is important that you (or ideally someone else) can go back and easily understand code that was written months or years before.
Probably my own personal rule is if it is more than 2 lines long, and is referenced more than once on the same page (ASP.net), or a few times spread over a couple of pages, than I will write a function to do it.
I was taught that anything you do more than once should be a function. Anything similar should have a parent class, and above all else consult your source code "standards" within your organization. The latter mostly deals with formatting.
First, write the feature you're adding. (Notice the word "First", we tend to write a function/class before writing the feature, which might lead to having too many fragmentation).
Then, review the code you just wrote/changed, find what blocks of the code that is:
3-lines or more, and..
repeated, and..
Can be grouped under a named function. Because code is written by us, people (not programs), to be read/changed later by us, people (not programs).

how big should function length be (lines of code in a function)? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How many lines of code should a function/procedure/method have?
I would like to know how many lines of code should be function have? How many lines is too much.
I read this a while back, it around 10 or 20 lines but it was because the screen would only accommodate so many lines. Now as the screen size become larger, that would not hold true.
Let's assume that the no part of the function is used anywhere else i.e. disregard DRY principle.
I'd like to hear what others have to say about this.
thanks.
Note: Duplicate of When is a function too long?, could not find it when I posted.
Lines are irrelevant, but complexity is.
A function should do one task, and it should be readily apparent. It shouldn't take you more than a few moments to understand exactly how and what the function does.
This kind of question is well answered in Code Complete. Steve McConnel wrote an entire page to answer this question. His conclusion:
Decades of evidence say that routines
of such length (>100 lines) are no
more error prone than shorter
routines. Let issues such as the
routine's cohesion, number of decision
points, number of comments needed to
explain the routine, and other
complexity-related considerations
dictate the length of the routine
rather than imposing a length
restriction per se. That said, if you
want to write routines longer than
about 200 lines, be careful.
It should have as many as it needs.
I don't see any point in restricting a function line-count to screen size (ok to be fair, I didn't start programming until after screens could accomadate more than 10-20 lines - maybe this did make sense in some environments). Just write the function as it makes sense to. When it gets so large that pieces of code start repeating, refactor those pieces to other functions/classes/components.
It's a pretty arbitrary rule of thumb. Some like 20 lines, others like the no-scroll rule. In the end, just make sure it's readable and easily understood at a glance. Read over your SOLID principles and make sure the method has only 1 responsibility, etc.
As long as necessary, as short as possible.
I take 5-10 Lines as a rule of thumb but if there is some logic that can't be (re)factored easily into multiple functions i write longer where necessary. On the other hand i often have functions that are just a line or two long.
If you do not immedatly understand what a part of code does, write a new function for it.
I don't think it matters how many lines it has...as long as it's efficient.
Any code that can be reused anywhere in your codebase should be moved to another function/method in the same class or a shared class and called.
I've heard the screen size metric before too but obviously not intended to be a hard limit or to scale with monitor size. It's just intended to convey the principle of DRY and that keeping functions as small as possible is one of the best ways to write code that can scale (in project size).
The Linux Kernel Coding Style document says:
Functions should be short and sweet,
and do just one thing. They should
fit on one or two screenfuls of text
(the ISO/ANSI screen size is 80x24, as
we all know), and do one thing and do
that well.
Now, I realize this is in the context of kernel code, but I think some of the points it makes re: function length are generally valid. Find a copy here. The section on functions is Chapter 4.
All in all, function length shouldn't be constrained by some artificial rule; factor stuff out if it makes sense, and because it makes stuff easier to read, but the rule about 1-2 screens is not written in stone.
this is just an opinion from an oo-perspective:
i prefer to keep my methods in logical units of work and dont really care about metrics like LoC. this makes it also quite easy to properly name your methods, and keeps them from getting bloated.
a very trivial functional example would be instead of having a function that calculates the fibonacci sequence inline in a loop i would add a successor(int a,int b) function, that gets called by the fibonacci() function.
a more complex example in oo fashion would be a http client that performs a GET request. i'd break that up into something like this:
Connection getConnection(String host, int port)
Request createRequest(String[] params)
void sendRequest(Request r)
String getResponse(Connection c,Request r)
Functions should be exactly small enough to do their job, but no smaller.

What question(s) does an object's behavior answer?

Reading a book I have found the following statement:
(Object) Behaviors answer either of two questions: What does this object do (for me)? or What can I do to this object? In the case of an orange, it doesn’t do a whole lot, but we can do things to it. One behavior is that it can be eaten.
In my understanding of object behaviour the statement above is correct regarding the first question and is incorrect in case of the second. However, I often see classes with methods like Orange::eat(), and this makes me uncertain about my design skills. So I would like to ask is it a design mistake to give oranges a behaviour eat? (oranges and eat are used just for example)
I think there's nothing wrong with your way of thinking about objects and their responsibilities. Orange::eat() would make sense if oranges had mouths. Otherwise, it's an Animal who is doing the eating.
The thing of the matter is, SVO (Subject-Verb-Object) sentences aren't always the best way to describe something, but OOP seems to be heavily biased towards that kind of statement so we frequently run into strange, unnatural and abstract sentence constructions in code.
Lets take classic Employee sample. "What can I do for this object" means:
void SetSalary(int value);
Eating an orange is not orange method, it is Person method:
void Eat(Orange& orange);
An orange can do things, for example, give rize to new orange trees. You are right, oranges can't eat anything, so it would make sense to have whatever is eating the orange have the eat method.
With this obvious example the answer is easy but it gets more complex in real life scenarios, you could take a look at Agile Principles, Patterns, and Practices in C# by Robert Martin. To go though a few scenarios and understand who gets to do what etc.

Where to draw the line between efficiency and practicality

I understand very well the need for websites' front ends to be coded and compressed as much as possible, however, I feel like I have more lax standards than others when it comes to practical applications.
For instance, while I understand why some would, I don't see anything wrong with putting selectors in the <html> or <body> tags on a website with an expected small visitation rate. I would only do this for a cheap website for a small client, because I can't really justify the cost of time otherwise.
So, that said, do you think it's okay to draw a line? Where do you draw yours?
Some best practices can be safely ignored if you know what your are doing and why you are doing it.
Don't cut corners because you are lazy, but don't over engineer a 2 page website. Use your judgment.
But, if you delude yourself into thinking you are better than you are, either yourself, or a future maintainer will be cursing your existence.
For instance, while I understand why some would, I don't see anything wrong with putting selectors in the or tags on a website with an expected small visitation rate
I assume you mean putting inline CSS into those tags. Well, there's nothing wrong with that per se. As far as I'm concerned, everybody is allowed to do that to their heart's content (as long as I don't have to maintain it.) But a practice that puts all the CSS into a separate style sheet, so that the HTML file consists really only of a skeleton and the actual content, is just cleaner, easier to maintain and a joy to the eyes.
I would only do this for a cheap website for a small client, because I can't really justify the cost of time otherwise.
I don't think this reasoning is correct. A cleanly separated structure is equally expensive to build when you've got the hang of it, and cheaper to maintain in the long run.
A small client who doesn't have a lot of money to spend is going to be extremely angry when he asks you to change some color and it turns out that will take you two hours because it's specified in a bunch of in-line styles rather than in a css file.
I would also argue that if you get in the habit of using an external stylesheet and just applying styles in your HTML, you will find that it's actually faster than in-line css.
Where I draw the line is going to depend on the project. You're always going to have to choose a balance between readability and efficiency.
For example, it's possible to make HTML and JavaScript very efficient by making it unreadable--stripping whitespace, shortening element, variable, and function names, etc. To evaluate whether or not to do so, I would calculate delta in hardware costs plus opportunity cost of the heavier file and compare it to the cost of writing a generator that will take clean, easy-to-read code and turn it into terse, easy-to-load code. Whichever solution costs less is then the one to use.
Best practices so called for a reason. Your work will always reflect you, and although these things may seem small and insignificant, they will aid maintainability, readability etc when you come back to modify something. The profitability argument is one oft cited by freelancers - if you don't always do it, you may never do it. In time you'll realise it's actually quicker to "do it right" than bodge it, and you'll be proud of your work.
Always adhere to standards and best practices!