Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 5, 2023 02:42 pm GMT

Measuring your code complexity

Wrote some code and want to know if it's good? If it's testable, maintainable, and "clean"?

How to measure code complexity?

Evaluating code quality can be subjective, as it often depends on individual contexts, patterns, and rules.

Time complexity and space complexity are two possible ways, but writing a compiler to measure this is a challenging task. Also these are metrics more focused in performance than code complexity itself. So what about cyclomatic complexity?

What is Cyclomatic Complexity?

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 computed using the control-flow graph of the program: the nodes of the graph correspond to indivisible groups of commands of a program, and a directed edge connects two nodes if the second command might be executed immediately after the first command. Cyclomatic complexity may also be applied to individual functions, modules, methods or classes within a program.

Simplifying the definition

Cyclomatic complexity is a way to measure how complex a program is by counting its independent paths.

Independent paths include loops, conditional structures, and other "branches" in your code. If a code segment can lead to a different route or deviation, it's an independent path. Examples include if, else, else if, for, and while.

Fewer independent paths make your code more readable, maintainable, and testable, while also simplifying testing and understanding.

Writing a TypeScript cyclomatic complexity analyzer

Let's use the TypeScript API to write a code to analyze the cyclomatic complexity of a TypeScript function.

import ts from 'typescript';import fs from 'fs';const args = process.argv.slice(2);const fileToRead = args[0];const fileContent = fs.readFileSync(fileToRead, 'utf8');const tmpSourceFile = ts.createSourceFile(  'tmp.ts',  fileContent,  ts.ScriptTarget.Latest,  true,);let complexity = 1;/** * Function to visit each node in the AST recursively * @param {ts.Node} node - The node to visit */const visitNode = (node: ts.Node) => {  switch (node.kind) {    case ts.SyntaxKind.IfStatement:    case ts.SyntaxKind.ForInStatement:    case ts.SyntaxKind.ForOfStatement:    case ts.SyntaxKind.ForStatement:    case ts.SyntaxKind.WhileStatement:    case ts.SyntaxKind.TryStatement:    case ts.SyntaxKind.CatchClause:    case ts.SyntaxKind.ConditionalExpression:      complexity += 1;      break;    case ts.SyntaxKind.SwitchStatement:      const switchStmt = node as ts.SwitchStatement;      switchStmt.caseBlock.clauses.forEach((clause) => {        if (ts.isCaseClause(clause)) {          // handle only case clausa, because it is not allowed to have a switch inside another          complexity += 1;        }      });      break;    case ts.SyntaxKind.BinaryExpression:      const binaryExpr = node as ts.BinaryExpression;      if (        binaryExpr.operatorToken.kind ==          ts.SyntaxKind.AmpersandAmpersandToken ||        binaryExpr.operatorToken.kind == ts.SyntaxKind.BarBarToken      ) {        // if the binary expression token is AND or OR, it is an assertion branch        // so it increases the complexity in +1        complexity += 1;      }      break;  }  ts.forEachChild(node, visitNode);};visitNode(tmpSourceFile);console.log(complexity);

This code basically reads a TypeScript file, and measure the cyclomatic complexity by visiting the AST nodes and adding +1 for each independent path it finds.

Usage

To run this code you just need to build the TypeScript file and run it using node. For example:

tsc && node dist/main.js

Or just

yarn start

if you are following my configuration

Current limitations

The cyclomatic complexity analyzer presented above has some limitations:

  1. Single function support: The code measures cyclomatic complexity accurately only when the provided file contains a single function. It won't work correctly for classes or files with multiple functions.

  2. TypeScript-specific: The analyzer is designed for TypeScript. If you use another programming language, you will need to reimplement the analyzer using the appropriate language-specific tools and techniques.

Github repository

TS Cyclomatic Complexity


Original Link: https://dev.to/josethz00/measuring-your-code-complexity-21jp

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To