Hallo allemaal, Leo hier. Today we will talk about cyclomatic complexity in Swift.

Do you ever feel like your code is getting out of hand? Are you struggling to understand or maintain a particular function or module in your app? If so, you might be running into issues with cyclomatic complexity and that is more common than you imagine.

Cyclomatic complexity is a fancy term for the number of decision points in a piece of code. Really that’s it. Essentially, the more decision points you have – like if statements, switch statements, loops, and so on – the more complex your code becomes. And the more complex your code becomes, the harder it is to understand, test, and maintain.

As a Swift developer, it’s important to be aware of cyclomatic complexity and how it affects the quality and maintainability of your code. High levels of cyclomatic complexity can make it difficult to debug and optimize your app and can lead to a higher risk of bugs and errors.

I like to talk about Swift’s capabilities, for example, how to use lazy variables in Swift, where we discuss all the implications of having lazy vars in your code. Lazy is a cool concept that can make your code way more efficient but you need to be careful to not throw lazy everywhere creating unnecessary overhead in your objects.

Another thing that I like to discuss is defensive programming, in that ballpark you can read how to improve your access to values inside arrays in Swift using a simple technique. Everybody knows that runtime problems are tricky, but accessing an array index that doesn’t exist is something that you can simply avoid.

But don’t worry, there are strategies you can use to reduce cyclomatic complexity and improve the quality of your Swift code. By breaking up complex functions into smaller, more modular pieces, and using control flow statements like guard and if let to simplify decision points, you can make your code more efficient and easier to maintain.

In this article, we’ll dive deeper into what cyclomatic complexity is, why it matters for Swift developers and strategies for reducing it in your code. By the end of this article, you’ll be equipped with the knowledge and tools you need to write cleaner, more maintainable Swift code that will make your life as a developer easier and more enjoyable.

Let’s code! But first…
 

Special Thanks

I want to give a special thanks to Marc that donated 5 coffees via buy me a coffee. I can’t stress enough how important is your help to keep this work going and I appreciated all your helps with this blog. 

 

The Painting of The Day

The Ninth Wave (Russian: Девятый вал, Dyevyatiy val) is an 1850 painting by the Russian Armenian marine painter Ivan Aivazovsky.

Ivan Aivazovsky, a Russian-Armenian marine painter, created a painting in 1850 called “The Ninth Wave” (Russian: Девятый вал, Dyevyatiy val). The title alludes to a maritime saying about a massive wave that follows a series of increasingly larger waves. An old sailing expression referring to a wave of the incredible size that comes after a succession of incrementally larger waves.

And like your code, if you don’t take care of your cyclomatic complexity the bigger 

 

What is Cyclomatic Complexity in Swift?

Cyclomatic complexity is a quantitative measure of the number of linearly independent paths through a program’s source code. It measures the number of decision points or branches in a program and the complexity of the logic used to navigate those branches.

The higher the cyclomatic complexity, the more complex the control flow of the app. When we develop software, we always aim for the least complexity possible so we can have great maintainability of the code.

 

Why Cyclomatic Complexity in Swift Matters?

High cyclomatic complexity can make code more difficult to read, understand, and maintain. It can lead to code that is harder to test, debug, and modify. High complexity can increase the likelihood of errors in the code, which can be costly to fix.

By reducing the cyclomatic complexity of a program, developers can make code easier to understand, maintain, and test, which can ultimately result in fewer bugs and more efficient development.

 

Measuring Cyclomatic Complexity in Swift

Cyclomatic complexity can be measured using a formula based on the number of decision points and the number of linearly independent paths through the code. In Swift, developers can use tools such as Xcode’s built-in static analyzer or third-party tools like SwiftLint to measure cyclomatic complexity.

Xcode’s static analyzer provides a visualization of the control flow of a program, highlighting decision points and loops. It also provides a cyclomatic complexity value for each method or function.

SwiftLint is a popular third-party tool that includes a rule for limiting cyclomatic complexity, which can be configured to match the developer’s standards.

 

Cyclomatic Complexity in Swift Code Example

Check the code below:

func calculateGrade(score: Int) -> String {
    switch score { // first branch
    case 90...100:
        return "A"
    case 80..<90:
        return "B"
    case 70..<80:
        return "C"
    case 60..<70:
        return "D"
    default:
        if score < 60 { // second nested branch
            return "F"
        } else {
            if score > 100 { // third nested branch
                return "Invalid score"
            } else {
                return "Unknown error"
            }
        }
    }
}

This function takes a numerical score as input and returns a letter grade based on a grading scale. However, it has a high cyclomatic complexity because of the multiple decision points in the code.

In particular, the function has two switch statements and nested if statements within the default case of the outer switch. These decision points increase the cyclomatic complexity of the function and make it more difficult to understand, test, and maintain.

To reduce the cyclomatic complexity of this function, you could consider refactoring it to use fewer decision points or to break it up into smaller, more modular functions.

Let’s solve that problem now!

 

Reducing Cyclomatic Complexity in Swift

To reduce cyclomatic complexity in Swift, developers can use several techniques. One common technique is to simplify control flow by using guard statements instead of nested if statements. This can make code more readable and reduce the number of branches in the code.

Another technique is to refactor complex methods or functions into smaller, more manageable pieces. This can break up complex code into smaller, more understandable pieces that are easier to test and maintain.

 

Solving Cyclomatic Complexity in Swift

To solve the above example we just need to extract the logic and put it in the guard statement.

Observe the solution below:

func calculateGrade(score: Int) -> String {
    guard score >= 0 && score <= 100 else { // one branch
        return "Invalid score"
    }
    
    switch score { // one branch
    case 90...100:
        return "A"
    case 80..<90:
        return "B"
    case 70..<80:
        return "C"
    case 60..<70:
        return "D"
    default: // the last if was just one more case
        return "F"
    }
}

This solution is exciting because now we don’t have any more nested branches/points and our code is really easy to reason and make your life easier. And that my friends, is the goal of removing the cyclomatic complexity of your code.

 

Conclusion

Cyclomatic complexity is an important aspect of code quality that can impact the readability, maintainability, and testability of a program. By understanding and measuring cyclomatic complexity in Swift code, developers can improve the quality and efficiency of their development efforts. By using techniques to reduce the complexity of code, developers can create code that is easier to understand, modify, and test, resulting in fewer bugs and more efficient development.

I hope from now on, you think twice when increasing the number of nested branches/ifs in your app, your future self will be thankful!

Fellow Apple Developers, that’s all.

I hope you liked reading this article as much as I enjoyed writing it. If you want to support this blog you can Buy Me a Coffee or say hello on Twitter. I’m available on LinkedIn or send me an e-mail through the contact page.

You can likewise sponsor this blog so I can get my blog free of ad networks.

Thanks for the reading and… That’s all folks.

Image credit: Featured Painting