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 solve complex code

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

Share

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

This article mainly introduces "how to solve complex code". In daily operation, I believe that many people have doubts about how to solve complex code problems. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "how to solve complex code"! Next, please follow the editor to study!

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 shows that the 1-10 code is OK, and the quality is good. 11-15 code is already more complex, but it is good. You can try to ReFactor the 16-∞ code for some points. It is very complex, the maintainability is very low, and the maintenance cost is high. At this time, you have to refactoring.

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.

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 gocyclo to determine cyclomatic complexity, and you can use go install github.com/fzipp/gocyclo/cmd/gocyclo for quick installation. Then use gocyclo $file to determine. We can create a new file test.go.

Package mainimport ("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 gocyclo test.go to calculate the cyclomatic complexity of the code.

$gocyclo test.go5 main main test.go:10:1

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

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.

3.2 write fewer process control statements

Here is a very simple example.

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

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.

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.

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.

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.

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.

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.

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.

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 scenario

4.4.2 complex scenes

4.5 Intersect

Find the intersection of two sets.

4.5.1 simple scenario

4.5.2 complex scenarios

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

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 scenes

4.7 Group

Group groups unions according to the specified elements, and the source code for Group is as follows.

Key is the list of elements of the corresponding key that we get when we group with key,Group. 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, the study of "how to solve complex code" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

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