Java cyclomatic complexity is

Java – Cyclomatic Complexity in piece of code with multiple exit points

Let’s focus on the cyclomatic complexity number: what is its value?

Metrics 1.3.6 says it’s 7, but I cannot really find seven independent paths: I only find 5! And Wikipedia didn’t help out much—how am I suppose to use this formula π — s + 2 ?

I have 2 if ‘s, 1 for and 3 exit points but I’m stuck: do I have to count the entry point? Should I count twice the first if since it has two conditions?

Ok, now I found out that Cyclomatic Number is 7. This means that there are 7 independent paths and so I should be able to find 7 different test cases if I would to cover 100% of code, am I right?

Well, I still cannot found the last one!
I found these:

  1. Valid: asdf1234
  2. Too short: asdf123
  3. Too long: asdfsgihzasweruihioruldhgobaihgfuiosbhrbgtadfhsdrhuorhguozr
  4. Invalid character: asdf*123
  5. All-digit: 12345678
  6. No-digits: asdfghjk
  7. wtf.

Best Solution

I think the trick is that the logical operators are counted.

Based off of your Metrics link (http://metrics.sourceforge.net/) under the McCabe Cyclomatic Complexity section:

3 decision points (if,for,if)

3 conditional logic operators (||,||,||)

Conditional logging with minimal cyclomatic complexity

With current logging frameworks, the question is moot

Current logging frameworks like slf4j or log4j 2 don’t require guard statements in most cases. They use a parameterized log statement so that an event can be logged unconditionally, but message formatting only occurs if the event is enabled. Message construction is performed as needed by the logger, rather than pre-emptively by the application.

If you have to use an antique logging library, you can read on to get more background and a way to retrofit the old library with parameterized messages.

Are guard statements really adding complexity?

Consider excluding logging guards statements from the cyclomatic complexity calculation.

It could be argued that, due to their predictable form, conditional logging checks really don’t contribute to the complexity of the code.

Inflexible metrics can make an otherwise good programmer turn bad. Be careful!

Assuming that your tools for calculating complexity can’t be tailored to that degree, the following approach may offer a work-around.

The need for conditional logging

I assume that your guard statements were introduced because you had code like this:

private static final Logger log = Logger.getLogger(MyClass.class); Connection connect(Widget w, Dongle d, Dongle alt) throws ConnectionException < log.debug("Attempting connection of dongle " + d + " to widget " + w); Connection c; try < c = w.connect(d); >catch(ConnectionException ex) < log.warn("Connection failed; attempting alternate dongle " + d, ex); c = w.connect(alt); >log.debug("Connection succeeded: " + c); return c; > 

In Java, each of the log statements creates a new StringBuilder , and invokes the toString() method on each object concatenated to the string. These toString() methods, in turn, are likely to create StringBuilder instances of their own, and invoke the toString() methods of their members, and so on, across a potentially large object graph. (Before Java 5, it was even more expensive, since StringBuffer was used, and all of its operations are synchronized.)

This can be relatively costly, especially if the log statement is in some heavily-executed code path. And, written as above, that expensive message formatting occurs even if the logger is bound to discard the result because the log level is too high.

This leads to the introduction of guard statements of the form:

 if (log.isDebugEnabled()) log.debug("Attempting connection of dongle " + d + " to widget " + w); 

With this guard, the evaluation of arguments d and w and the string concatenation is performed only when necessary.

A solution for simple, efficient logging

However, if the logger (or a wrapper that you write around your chosen logging package) takes a formatter and arguments for the formatter, the message construction can be delayed until it is certain that it will be used, while eliminating the guard statements and their cyclomatic complexity.

public final class FormatLogger < private final Logger log; public FormatLogger(Logger log) < this.log = log; >public void debug(String formatter, Object. args) < log(Level.DEBUG, formatter, args); >… &c. for info, warn; also add overloads to log an exception … public void log(Level level, String formatter, Object. args) < if (log.isEnabled(level)) < /* * Only now is the message constructed, and each "arg" * evaluated by having its toString() method invoked. */ log.log(level, String.format(formatter, args)); >> > class MyClass < private static final FormatLogger log = new FormatLogger(Logger.getLogger(MyClass.class)); Connection connect(Widget w, Dongle d, Dongle alt) throws ConnectionException < log.debug("Attempting connection of dongle %s to widget %s.", d, w); Connection c; try < c = w.connect(d); >catch(ConnectionException ex) < log.warn("Connection failed; attempting alternate dongle %s.", d); c = w.connect(alt); >log.debug("Connection succeeded: %s", c); return c; > > 

Now, none of the cascading toString() calls with their buffer allocations will occur unless they are necessary! This effectively eliminates the performance hit that led to the guard statements. One small penalty, in Java, would be auto-boxing of any primitive type arguments you pass to the logger.

The code doing the logging is arguably even cleaner than ever, since untidy string concatenation is gone. It can be even cleaner if the format strings are externalized (using a ResourceBundle ), which could also assist in maintenance or localization of the software.

Further enhancements

Also note that, in Java, a MessageFormat object could be used in place of a «format» String , which gives you additional capabilities such as a choice format to handle cardinal numbers more neatly. Another alternative would be to implement your own formatting capability that invokes some interface that you define for «evaluation», rather than the basic toString() method.

Java – Multiple line code example in Javadoc comment

In addition to the already mentioned tags, you should also use the @code JavaDoc annotation, which will make life much easier when it comes to HTML entities issues (in particular with Generics), e.g.:

Will give correct HTML output:

While omitting the @code block (or using a tag) will result in HTML like this:

For reference, a full list of tag descriptions available in Java SE 8 can be found here.

Источник

Java: Cyclomatic Complexity

How to compute McCabe’s Cyclomatic Complexity in Java methods

Flow complexity in methods. McCabe proposed a way to measuring flow complexity of a method which basically counts one for each place where the flow changes from a linear flow. His measurement was designed before exceptions and threads were used in programming languages, so what I’ve added I believe reflects some of the original intent. His algorithm, translated, at least approximately, into Java terms is as follows.

Example

Compute the cyclomatic complexity of the following main method.

1* 2 3* 4 5 6 7 8 9** 10* 11 12 13 14 15 16* 17* 18 19 20 21 22 23* 24 25 26 27
public static void main(String[] args) < init(); do < String prompt = "" + toHTML() + "
Enter row and column to bomb:"; //. Ask user for row and column input. String input = JOptionPane.showInputDialog(null, prompt); if (input == null || input.length() == 0) < break; // Quit if there is no input. >try < //. Split input into row and column. Sub 1 to get internal row/col String[] inputs = input.split(" "); if (inputs.length != 2) < throw new NumberFormatException(); >int row = Integer.parseInt(inputs[0]) - 1; int col = Integer.parseInt(inputs[1]) - 1; dropBomb(row, col); //. Drop bomb at those coords. > catch (NumberFormatException unused) < JOptionPane.showMessageDialog(null, "Enter two integers."); >> while (shipsRemain()); >

Each «*» beside a line number gets one point. This method is quite complicated.

Keep complexity under 10

Lower is better. A McCabe complexity under 5 is good, from 5-10 is OK, and over 10 is too complex. A high flow complexity may be a symptom of a function which does too much or has low cohesion (does too many different things). But don’t take these numbers too seriously — you may have comprehensible control flow despite high numbers. For example, one large switch statement can be clear to understand, but will dramatically increase the count.

How to fix high complexity

Make simpler or break up complex methods. How do you simplify a method? Sometimes you can make a method simpler with a little more design thought, but often you will have to simplify it by breaking it into two or more methods. The complexity, the demands on the human to keep many things in their mind at the same time, can be reduced by breaking one method into two highly cohesive, well-named, methods. This may seem counter-intuitive that creating another method will make something simpler, but if each method has a clear purpose, the result will be simpler.

External sources

Источник

Java cyclomatic complexity is

  • Haskell vs. PureScript: The difference is complexity Haskell and PureScript each provide their own unique development advantages, so how should developers choose between these two .
  • A quick intro to the MACH architecture strategy While not particularly prescriptive, alignment with a MACH architecture strategy can help software teams ensure application .
  • How to maintain polyglot persistence for microservices Managing microservice data may be difficult without polyglot persistence in place. Examine how the strategy works, its challenges.
  • The basics of implementing an API testing framework With an increasing need for API testing, having an efficient test strategy is a big concern for testers. How can teams evaluate .
  • The potential of ChatGPT for software testing ChatGPT can help software testers write tests and plan coverage. How can teams anticipate both AI’s future testing capabilities .
  • Retail companies gain DORA metrics ROI from specialist tools DORA metrics and other measures of engineering efficiency are popping up in add-ons to existing DevOps tools. But third-party .
  • How to create and manage Amazon EBS snapshots via AWS CLI EBS snapshots are an essential part of any data backup and recovery strategy in EC2-based deployments. Become familiar with how .
  • Prices for cloud infrastructure soar 30% Tough macroeconomic conditions as well as high average selling prices for cloud computing and storage servers have forced .
  • Deploy a low-latency app with AWS Local Zones in 5 steps Once you decide AWS Local Zones are right for your application, it’s time for deployment. Follow along in this step-by-step video.
  • Using defense in depth to secure cloud-stored data To better secure cloud-resident data, organizations are deploying cloud-native tools from CSPs and third-party tools from MSPs to.
  • Multiple Adobe ColdFusion flaws exploited in the wild One of the Adobe ColdFusion flaws exploited in the wild, CVE-2023-38203, was a zero-day bug that security vendor Project .
  • Ransomware case study: Recovery can be painful In ransomware attacks, backups can save the day and the data. Even so, recovery can still be expensive and painful, depending on .
  • AWS Control Tower aims to simplify multi-account management Many organizations struggle to manage their vast collection of AWS accounts, but Control Tower can help. The service automates .
  • Break down the Amazon EKS pricing model There are several important variables within the Amazon EKS pricing model. Dig into the numbers to ensure you deploy the service .
  • Compare EKS vs. self-managed Kubernetes on AWS AWS users face a choice when deploying Kubernetes: run it themselves on EC2 or let Amazon do the heavy lifting with EKS. See .

Источник

Читайте также:  Openoffice calc and html
Оцените статью