1

we've a python function that can be achieved in 2 ways 1st method

def complexity_1(x, y):
    if 2 == x and 3 == y:
        a=3
        b=4
        c = a + b
    elif 2 == x and not 3 == y:
        a = 3
        b = 5
        c = a + b
    else:
        c=5
    return c

2nd method

def complexity_2(x, y):
    if 2 == x:
        a=3
        if y==3:
            b=4
        else:
            b=5

        c = a + b
    else:
        c=5
    return c

Which is the better way to do it the first one east to understand and reduces cyclomatic complexity but you're having duplicated code c=a+b and a=3 twice, but in the 2nd method you don't have that duplication but hard to go through the logic which one is better and right way to do?

3

1 Answer 1

5

How about:

def complexity_3(x, y):
    if 2 != x:
       return 5

    return (7 if (3 == y) else 8)

Don't be afraid to exit a function from multiple locations. That advice was specific to assembly, and means always return to the caller that called you. This is (excluding some safe compiler optimisations) enforced by functions and return.

Also don't sweat cyclomatic complexity. Its a way of calculating branching, nothing more. Only the most uninteresting pieces of code that do not change their own behaviour, do not branch. Everything else necessarily must branch. Of course if the branching becomes too high (say spaghetti code) then yes some cleanup is required.

And finally code should be written to be maintainable. And by maintainable I mean very readable, because that is the single slowest thing this code will ever do. There are many ways to try and achieve this. The simplest way is to get the new guy on the team to read it. The next best way is to just get someone else to read it the longer they take/more questions they have, the harder the code is to read.

4
  • I like your answer but in the return (7 if (3 == y) else 8) for simplicity I replaced with constants but how would you deal with a variable? ex: ``` def complexity_2(x, y,z): if 2 == x: a=3 if y==3: b=z else: b=z+2 c = a + b else: c=5 return c ``` Jul 10, 2020 at 2:19
  • Push and Pull. Identify the common parts and either push or pull them into another scope. You have two concerns floating in this code, the calculation itself, and what parameters to pass to it. So the complicated calc a+b might be pushed down to def calc(a, b): return a + b. The setup for the cal is then if (cond): return calc(x,6) else return calc(y, z - x) style. Perhaps the decision about the content of c being z*2 - x or x * cos(z) could be pulled up and passed in as another argument.
    – Kain0_0
    Jul 10, 2020 at 3:21
  • This is a great answer. I think it's helpful to know that a lot of tools calculate cyclomatic complexity incorrectly but counting every return as another path. So while I think this has the same complexity as the other examples (3), a tool might incorrectly report this as having a complexity of 4. What's even more annoying is that because these tools do this, a fair amount of people believe that's the right way to calculate it.
    – JimmyJames
    Jul 10, 2020 at 18:55
  • 1
    What's the quickest way to distract a developer? Give them a metric to optimise. What's the quickest way to make awful code? Give the developer an awful metric. Cyclomatic Complexity (correctly implemented) is a way to get a qualitative feel, in no way should it represent a goal.
    – Kain0_0
    Jul 12, 2020 at 23:27

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.