0

Prompted by Sonar, I am looking to reduce the complexity of a function (one that some might call arrow code). I am loosely familiar with some of the principles of reducing arrow code complexity (flattening, eager returns, guard statements instead of affirmative condition checks), but I doubt that this particular code is satisfied by any of those.

The function takes three parameters and returns a string. If the first parameter does not meet the criteria for if/else-if outer block, the function returns a default string (the initial string assignment). For the sake of brevity, I think we can safely assume the function takes only 2 parameters.

Pseudocode

String getMyString(String parameter1, String parameter2) {
    String myString = "STRING_A.Y"
    if (parameter1 == optionA) {
        if (parameter2 == optionX) {
            myString = "STRING_A.X"
        } else {
            myString = "STRING_A.Y"
        }
    } else if (parameter1 == optionB) {
        if (parameter2 == optionX) {
            myString = "STRING_B.X"
        } else {
            myString = "STRING_B.Y"
        }
    }
    return myString
}  

In the case of three parameters, we are looking at 8 possible outputs. The only way I see to "reduce" complexity would be to turn this into a switch statement, but I personally find that the code would be less readable (particularly when more parameters are introduced). I don't see a meaningful way to separate this code into smaller functions. I don't see a way to add guard statements that might reduce the degree of nesting here. Is a switch statement the best alternative?

8
  • 3
    The problem with pseudocode is, that it leads to pseudo-solutions. If this was the real thing, I'd tell you to determine the two parts of the string separately and catenate them afterwards.
    – mtj
    Nov 11, 2021 at 13:44
  • Unfortunately, the string is not composed in a way that would allow that. I'm also returning constants in the actual method
    – j.k
    Nov 11, 2021 at 13:55
  • 4
    The answer will depend on the language you are using as each language will have different ways of solving this.
    – David Arno
    Nov 11, 2021 at 13:59
  • Does this answer your question? How to tackle a 'branched' arrow head anti-pattern?
    – gnat
    Nov 11, 2021 at 15:42
  • I'm not sure now in hindsight if anything I said makes sense. I should probably refrain from using this site while completely drunk. :-D I just realized there are still five cases in your example. A.X,A.Y, B.X,B.Y, O. Ah well, analyzing cyclomatic complexity is hardly my forte. I tend to not be that zoomed in to care about these things quite as much (more concerned with integration than units at my zoomed-out level). But there is an obvious duplication of logic in the inner branches which sticks out to me and implies more things to test and could go wrong at a glance level...
    – user379844
    Nov 11, 2021 at 18:16

3 Answers 3

6

According to your own comment, you do not build the result based on parameters but you rather mapped specific parameter combinations to some constant. So why not use some ParameterTuple=>Constant map?

Add some default in case there is no match. Actual implementation is language specific, but more parameter would only result in additional map entries, without further complexity.

4

If you are attempting to optimize for readability and not optimizing for cleverness or performance or brevity, this is the way I would write it.

String getMyString(String parameter1, String parameter2) {
    if (parameter1 == optionA && parameter2 == optionX) return "STRING_A.X";
    if (parameter1 == optionA && parameter2 != optionX) return "STRING_A.Y";
    if (parameter1 == optionB && parameter2 == optionX) return "STRING_B.X";
    if (parameter1 == optionB && parameter2 != optionX) return "STRING_B.Y";
    return "STRING_A.Y";
}

This eliminates any confusion and many of the common logic bugs. The conditions are all mutually exclusive and free of sequential dependency; they can be put in any order, and new ones can be added in between, or conditions removed, with little risk of impacting the other conditions. Also, the default value is clearly expressed as a catch-all at the end.

-2

This solves the problem in three lines, and looks more readable to me as well.

String part1 = (parameter1 == optionA ? "String_A" : "String_B";
String part2 = (parameter2 == optionX ? ".X" : ".Y";
return part1 + part2;
2
  • 1
    As the OP points out in a comment, "Unfortunately, the string is not composed in a way that would allow that. I'm also returning constants in the actual method"
    – David Arno
    Nov 11, 2021 at 17:01
  • Well, the code he posted allows it.
    – gnasher729
    Nov 11, 2021 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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