Reputation: 2223
At what point should we consider code to be too cluttered? I'm near completion for making a search widget that reads into a database of files within a server and then displays it, but my code has over 30 functions that could potentially be refactored to be shorter and more compact. As an entry-level programmer still in university, is there a certain standard in the industry, or a methodology that people follow with regards to my question?
Upvotes: 0
Views: 3679
Reputation: 530
I'm going to add a different perspective (but I don't know if it aligns with the leading "takes" on this issue) by proposing 2 rules:
Rule 1: If your function is only used once, it probably shouldn't be a function - ^ especially for "pipeline-style" code (where it's easier to read the code as a natural sequence)
Explanation: The primary elegance of functions in reusing code you've already written. If you aren't using the function multiple times, what was the point? Debugging becomes a nightmare; I'm now stuck trudging back and forth between different sections of code
Rule 2: Functions should not replicate trivial, existing features of the language
Explanation: There is nothing more infuriating that debugging someone's code that's jumbled with functions replicating normal language features. Consider the following code that checks if a javascript object is empty:
code A
function isEmptyObject(theObject) { // <-- function to check if object is empty
return Object.keys(theObject).length === 0;
}
const obj = {};
if (isEmptyObject(obj)) {
console.log('The object is empty.');
} else {
console.log('The object is not empty.');
}
code B
const obj = {};
if (Object.keys(obj).length === 0) { // <-- check if object is empty
console.log('The object is empty.');
} else {
console.log('The object is not empty.');
}
What is the point of taking an already straightforward action that the language provides and wrapping it in a function? Even if I'm going to be doing this process 100 times, wrapping a 1-line action in a function only ruins readability. I'd agree that this is a strawman argument if it weren't for the fact that I've seen this dozens of times (particularly in code written by non-CS academics).
Disclaimer: I'm happy being wrong here; I'm interested in what the counter arguments are. I know there could be an argument for modularity; i.e., if you're script has 5 main processes, why not wrap those in 5 large functions so you can easily see the flow of the pipeline at the end (function(1) -> function(2) -> ...). However, overmodularity destroys readability and makes debugging a massive headache. Why wrap a codeblock in a function when a comment would suffice?
Also, maybe modern IDEs solve these issues by making code navigation easier (e.g., jump to function source code), but I'm not yet convinced.
That's why my philosophy is: don't wrap your code in functions until it makes sense to. Plus, 90% of the time, the language already provides the function you need.
Upvotes: 0
Reputation: 10225
I believe a good industry practice is to have functions defined such that they provide a single obvious role. In other words, a function should do one thing and do it well.
It's common to have functions be as much as ~25 lines of code but if it is more than that...perhaps it can be broken down. This is just a guideline.
I would argue it's better to have many functions then too few which would commonly result in a monolithic mess.
Also, having separate functions alone, the next step is organizing them into classes or modules depending on the language you are using.
You may also want to read about cyclomatic complexity of functions. There are tools that can help analyze cyclomatic complexity but largely what this means is how complex the function is in terms of execution paths. More execution paths means more that needs to be tested, maintained and remembered when you are reading that function. A low cyclomatic complexity score is a good thing.
Upvotes: 3