Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Do iterative methods such as are commonly found in modern languages such as C#, JavaScript, and (hopefully) in Java 8 reduce cyclomatic complexity's impact on understandability and supportability of code?

For example in C# we might have the following code:

List<String> filteredList = new List<String>();

foreach (String s in originalList){
   if (matches(s)){
      filteredList.add(s);
   }
}

This has a simple cyclomatic complexity of 2.

We could easily re-write this as:

List<String> filteredList = originalList.where(s => matches(s));

Which has a simple cyclomatic complexity of 0.

Does this actually result in more supportable code? Is there any actual research on this topic?

share|improve this question
2  
Your title asks about cyclomatic complexity reduction, but your text assumes CC reduction and asks about maintainability. This has the potential to be a valuable question, can you edit the title to be more accurate? –  Kilian Foth Feb 25 '13 at 15:29
    
@KilianFoth Is that better? –  C. Ross Feb 25 '13 at 15:36
    
I'd asociate iterative methods with a iterative developmemt metodologies. I think a better term would be higher-order functions. (And as an aside, methods have no return type/void whereas functions return something). –  Johannes Rudolph Mar 1 '13 at 12:38
add comment

6 Answers

All you are doing is highlighting a flaw in cyclomatic complexity as a metric, the complexity of the code really hasn't changed. You have an explicit branch in the first example and need to understand there is an implied branch in the second. The second is clearer and easier to understand provided you understand the syntax, and since it uses less basic syntax that may be an issue.

share|improve this answer
add comment

My guess is that you just divided/moved the complexity. It decreased because you doesn't count the implementation of .where() in your CC.

The overall CC hasn't really moved, your own code's CC decreased, only because it's now moved to the framework's code.

I'd say it's more maintainable. When it's a feature of the language, use it. It's no a "ohh, I see, it's a clever trick" that you're using, only a simple inline reduce-like function.

share|improve this answer
add comment

In order to answer the question objectively, we'd need some sort of metric for maintainability. Cyclomatic complexity itself isn't a measure of maintainability, but it is a component of some metrics that purport to measure maintainability. For example, the formula for the Maintainability Index is:

MI = 171 - 5.2 * ln(V) - 0.23 * (G) - 16.2 * ln(LOC)

where G is the cyclomatic complexity of the code in question. Therefore, reducing the cyclomatic complexity of a piece of code does by definition improve the code's Maintainability Index and other metrics which similarly use cyclomatic complexity.

It's hard to say whether the kind of change you propose makes the program seem more maintainable to programmers; that probably depends on how familiar they are with (in your case) the where method.

share|improve this answer
    
Warning: Magic Numbers! (>_<) –  Izkata Feb 25 '13 at 19:12
    
There's just this one little problem with the Maintainability Index. The three components of it are Halstead Volume, Cyclomatic Complexity, and Lines of Code. Both Halstead Volume and Cyclomatic Complexity have been shown to be very strongly correlated to Lines of Code. This means that an alternative approximate equation for the Maintainability Index that depended ONLY on Lines of Code could be derived that would be almost as accurate as the original, with considerably less computational difficulty. –  John R. Strohm Feb 25 '13 at 19:17
    
@JohnR.Strohm I think you'd get a similar result even if you just use LOC as the maintainability metric. The OP's change reduces LOC to 1 from 4, and other changes that reduce cyclomatic complexity are similarly likely to reduce LOC as well. Either way, it really comes down to how you define and measure maintainability. –  Caleb Feb 25 '13 at 19:27
    
@Caleb: Agreed. The point I try to make is that people far too often go for these really complicated metrics and combinations of metrics, not realizing that just about all of them have been shown to be strongly correlated on real code with plain old Lines Of Code (LOC), and hence have no more predictive or descriptive value than LOC. –  John R. Strohm Feb 25 '13 at 20:23
add comment

Subjectively, it depends on the developer audience, if they understand lambda expressions, then;

List<String> filteredList = originalList.where(s => matches(s));

is quicker to understand, and perhaps slightly easier. I would be more concerned about using s, and matches(). Neither is self-descriptive, something like;

List<String> filteredList = 
    originalList.where(stringToBeTested => matchesNameTest(stringToBeTested));

Or

List<String> filteredList = 
        originalList.where(originalListString => matchesNameTest(originalListString));

gives the developer more meaningful information and is easier to analyze, without having to dive into the matches() function to determine what match is being performed.

Maintainability is not only about the ability to comprehend the code, but mainly about the speed and accuracy with which one can comprehend the code.

share|improve this answer
2  
Hi Ace. It's an example, intentionally devoid of semantic content to highlight the structure. –  C. Ross Feb 25 '13 at 18:17
add comment

Because it has been shown that cyclomatic complexity (CC) is very strongly correlated with code size, "so much so that CC can be said to have absolutely no explanatory power of its own." what you are really asking is whether "iterative methods such as are commonly found in modern languages such as C#, JavaScript, and (hopefully) in Java 8 reduce code size's impact on understandability and supportability of code."

At that point, one would hope that the answer would be obvious. It has been known for decades that shorter code is generally easier to understand, maintain, and support.

share|improve this answer
add comment

If you're talking about the raw stat of Cyclomatic Complexity, sure. You just nuked it from 2 to 0. If you're going by numbers, pure gain, all the way.

From a practical (read: human) perspective though, I would argue you've actually increased the complexity by 2. One point of that comes from the fact that now some other programmer must bring or get knowledge of fluent-syntax LINQ to understand this code.

Another point of increased difficulty comes from understanding Lambda Expressions; though a Lambda is fairly straightforward in this instance, there are some paradigm shifts that have to be made to fully appreciate them.

This case, using a.where(x => matches(x, arg)) isn't terrible, and in all honesty is a great way to get some coworker to see and work with LINQ and Lambda expressions for the first time (I actually presented a tutorial on LINQ/Lambdas to some former coworkers using this and other sets of code, to great effect.) However, the usage of these does require some knowledge.

I recommend caution, because I've seen cases where the LINQ refactor is actually significantly worse to read than what that foreach loop becomes.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.