Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to reduce the cyclical complexity of the code

2025-01-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article focuses on "how to reduce the cyclical complexity of the code", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to reduce the cyclical complexity of the code.

0. What is cyclomatic complexity?

Maybe you haven't heard the word before, and you'll wonder what it's for and what it's for. There's an explanation on Wikipedia.

Cyclomatic complexity is a software metric used to indicate the complexity of a program. It is a quantitative measure of the number of linearly independent paths through a program's source code. It was developed by Thomas J. McCabe, Sr. In 1976.

Cyclomatic complexity is used to measure the complexity of code, and the concept of cyclomatic complexity was put forward by this guy Thomas J. McCabe Sr in 1976.

1. Why do you need cyclomatic complexity

If your current project, the readability of the code is very poor, difficult to maintain, a single function code is particularly long, a variety of if else case nesting, looking at large chunks of bad code can not start, or even can not understand the point, then you can consider using cyclomatic complexity to measure the complexity of the code in your project.

If we do not deliberately control it, when our project reaches a certain scale, some more complex business logic will cause some developers to write very complex code.

To take an example of a real complex business, if you develop using TDD (Test-Driven Development), when you haven't really started writing the implementation of an interface, your single test may have reached dozens of case, and the real business logic hasn't even started writing yet.

For example, a function has hundreds or even thousands of lines of code, in addition to all kinds of if else while nesting, even if the writer of the code may forget the context and look at the code in a few weeks, they may not understand it, because the readability of the code is so poor that it is very difficult for you to read, so what about maintainability and extensibility?

So how can we avoid this situation early in coding, CR (Code Review)? Use the cyclomatic complexity detection tool to detect the cyclomatic complexity in the submitted code, and then reconstruct according to the cyclomatic complexity detection. Break excessively long and complex code into smaller, single and clear functions, or use design patterns to solve a large number of if else nesting logic in the code.

Some people may think that reducing cyclomatic complexity is not very beneficial to me, maybe in the short term, and even you may trigger cyclomatic complexity detection by moving other people's code, so you also need to ReFactor other people's code.

But in the long run, code with low cyclomatic complexity has better readability, expansibility and maintainability. At the same time, your coding ability will be improved with the practical application of design patterns.

two。 Circle complexity measurement standard

How does cyclomatic complexity measure the complexity of the code? Not by feeling, but by your own set of rules of calculation. There are two methods of calculation, as follows:

Node decision method

Point-edge calculation method

I sorted out the criteria into a table for reference only.

Cyclomatic complexity description

1-10 codes are OK, and the quality is OK.

The 11-15 code is already more complex, but it's okay. You can try to ReFactor some points.

The 16-∞ code is already very complex, low maintainability and high maintenance cost, so it must be refactored at this time.

Of course, I personally think that we can not arbitrarily apply this cyclomatic complexity criterion to all situations of all companies, and we should analyze it according to our own actual situation.

This is entirely determined by your own business volume and actual situation. Assuming that your business is simple, and it is a single application, and the function is very simple CRUD, then your cyclomatic complexity is not that easy even if you want to. At this point, you can choose to set the cyclomatic complexity reconstruction threshold to 10.

Assuming that your business is very complex and involves multiple other micro-service system calls, coupled with the judgment of corner case in various businesses, the cyclomatic complexity may be 100.

If such code is not refactored, it will become more and more difficult to maintain as the demand increases.

2.1 Node decision method

Only the simplest one, node determination method, is introduced here, because some tools are actually calculated according to this algorithm, and the calculation formula is as follows.

Cyclomatic complexity = number of nodes + 1

What does the number of nodes represent? These are the following control nodes.

If, for, while, case, catch, and, not, Boolean operation, ternary operator

In vernacular, when you see the symbol above, you increase the cyclomatic complexity by 1, so let's look at an example.

Picture

According to the above method, we can get that the number of nodes is 13, then the final cyclomatic complexity is 13 + 1 = 14, and the cyclomatic complexity is 14. It is worth noting that the & & will also be counted as one of the nodes.

2.2 use tools

For golang we can use gocognit to determine cyclomatic complexity, and you can use go get github.com/uudashr/gocognit/cmd/gocognit for quick installation. Then use gocognit $file to determine. We can create a new file test.go.

Package main

Import (

"flag"

"log"

"os"

"sort"

)

Func main () {

Log.SetFlags (0)

Log.SetPrefix ("cognitive:")

Flag.Usage = usage

Flag.Parse ()

Args: = flag.Args ()

If len (args) = = 0 {

Usage ()

}

Stats: = analyze (args)

Sort.Sort (byComplexity (stats))

Written: = writeStats (os.Stdout, stats)

If * avg {

ShowAverage (stats)

}

If * over > 0 & & written > 0 {

Os.Exit (1)

}

}

Then use the command gocognit test.go to calculate the cyclomatic complexity of the code.

$gocognit test.go

6 main main test.go:11:1

The main method, which represents the main package, starts at line 11 and calculates a cyclomatic complexity of 6.

3. How to reduce cycle complexity

There are actually a lot of methods here, and then various methods also have a lot of professional names, but they may not be so easy to understand for those who are new to cyclomatic complexity. So I summed up the method of how to reduce the cyclomatic complexity into a sentence, that is, "minimize the number of nodes in the node decision method".

To put it in vernacular, try to write fewer process control statements such as if, else, while and case.

In fact, when you reduce the cyclomatic complexity of your original code, it is actually a kind of refactoring. For most business code, the less the code, the easier it will be for subsequent maintainers to read the code.

To sum up, there are two directions, one is to split small functions, and the other is to find ways to reduce the number of flow control statements.

3.1 split small function

Split small functions, the calculation range of cyclomatic complexity is within a function, split your complex business code into small functions with a single responsibility, so that people who read the code later can understand what you are probably doing at a glance, and then specific to each small function, because it has a single responsibility and a small amount of code, you can easily understand it. In addition to reducing cyclomatic complexity, splitting small functions can also improve the readability and maintainability of the code.

For example, there are a lot of condition judgments in the code.

In fact, it can be optimized that we separate a judgment function and only do condition judgment.

Picture

3.2 write fewer process control statements

Here is a very simple example.

Picture

In fact, it can be directly optimized to look like this.

Picture

This is the end of the example, in fact, you also found that, as I said above, the purpose is to reduce the number of process control statements such as if. In fact, to think another way of thinking, complex logical judgment will certainly increase the cost of understanding our reading code, and it is not convenient for later maintenance. Therefore, when refactoring, you can find ways to simplify your code as much as possible.

Is there any more direct way besides these? For example, try to avoid this problem from the beginning of writing code.

4. Use go-linq

Instead of rushing to understand what go-linq is, let's look at a classic business scenario.

Get an ID list from a list of objects

If we were in go, we could do this.

Picture

It is a little tedious, and students who are familiar with Java may say why such a simple function is so complex, so they wrote down the following code.

Picture

Stream, the new feature of Java8, is used in the figure above, and the Go language is not yet able to achieve this effect. So it's go-linq 's turn to come out, and the code after using go-linq looks like this.

Picture

How, do you see the shadow of Java 8 Stream? we will not compare the number of lines of code after refactoring. From a semantic point of view, it is also clear and intuitive. This is go-linq. We use an example to introduce its definition, and then briefly introduce several common uses, which are all examples given on the official website.

4.1 ForEach

Similar to foreach in Java 8, it is a traversal of the collection.

Picture

The first is a From, which represents the input, where the dream begins, and can be equated with the stream in Java 8.

Then you can see ForEach and ForEachT,ForEachIndexed and ForEachIndexedT. The former only traverses the element, while the latter prints out its subscript as well. It is the same as Range in Go, and similar to ForEach in Java 8, but the ForEach of Java 8 has no subscript. Go-ling has it because it records an index,ForEachIndexed source code as follows.

Picture

What is the difference between the two? I know that whether you are sensitive to the type of element you want to traverse should be sensitive in most cases. If you use the one with T, go-ling will convert interface to the type you defined in the function, such as fruit string, when traversing.

Otherwise, we need to manually convert interface to the corresponding type, so I will directly use functions of this type in all subsequent examples.

4.2 Where

It can be understood as the where condition in SQL or the filter in Java 8, which filters the collection according to certain conditions.

Picture

The above Where filters out elements with a string length greater than 6, and you can see that there is a ToSlice, which outputs the filtered results to the specified slice.

4.3 Distinct

It has the same function as Distinct in MySQL or Distinct in Java 8.

4.3.1 simple scenarios

4.3.2 complex scenes

Of course, in actual development, it is rare that there is only one integer array, and most of the objects that need to be judged are a struct array. So let's look at a slightly more complicated example.

Picture

The above code deduplicates the slice of a products according to the Code field of the product.

4.4 Except

Make a difference between two sets.

4.4.1 simple scene picture

4.4.2 Pictures of complex scenes

4.5 Intersect

Find the intersection of two sets.

4.5.1 simple scene picture

4.5.2 complex scene picture

4.6 Select

Functionally, Select is similar to ForEach, with the following differences.

Select returned a Query object

ForEach does not return a value

Here you don't have to care about what the Query object is, just like the map, filter and other control functions in Java8 will return Stream. You can achieve the purpose of streaming programming in the code by returning Query.

4.6.1 simple scenario

Picture

Select simple scenario

SelectT traverses a set, and then does some operations to output the results to the new slice.

SelectMany returns a Query for each element in the collection, similar to flatMap in Java 8, while flatMap creates a Stream for each element. To put it simply, a two-dimensional array is flattened into an one-dimensional array.

4.6.2 complex scene pictures

4.7 Group pictures

Group groups combinations according to the specified elements. The source code of Group` is as follows.

Picture

Key is the list of elements of the corresponding key that we get when we group with key,Group.

Well, because of the space, this is the end of the introduction about the use of go-linq. If you are interested, you can go to the go-linq official website to see all the usages.

5. About the use of go-linq

First of all, I think that using go-linq is not just to "escape" the check of cyclomatic complexity, but to really make your code more readable by refactoring it.

For example, in some complex scenarios, using go-linq will make your code more difficult to understand. Code is for you and follow-up maintenance students to see, do not blindly pursue low cycle complexity code, and crazy use of go-linq.

Personally, I only prefer to use go-linq for some operations on the collection, other complexities, good code, plus appropriate comments, is the behavior of not digging holes for others (including yourself). And not all if else is bad code, if the necessary if else can greatly increase the readability of the code, why not? (of course, we're not talking about the kind of code with all kinds of if else front sets.)

At this point, I believe you have a deeper understanding of "how to reduce the cyclical complexity of the code". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report