The cyclomatic complexity of code is the measurement of how complex the code is; the numbers of linearly independent paths in it. It is one of the metrics for software quality.

Cyclomatic Complexity is calculated in numbers. The higher the complexity number, the lower the quality of the code.

For example, let’s look at this flowchart:

The flowchar has seven shapes(nodes), seven lines(edges), hence cyclomatic complexity is 7-7+2 = 2. The complexity score below 4 is considered good, a score in 4-7 is considered medium while score of 8 and above is considered too high.

Let’s take a PHP Code Example (taken from one of my WordPress plugins – WP Frontend Delete Account):

	/**
	 * Perform Delete Action.
	 *
	 * @since  1.0.0
	 *
	 * @return Void.
	 */
	public function confirm_delete() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
		if ( isset( $_POST['security'] ) ) {
			if ( ! wp_verify_nonce( wp_unslash( $_POST['security'] ), 'wpfda_nonce' ) ) { //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
				return;
			}

			$security       = get_option( 'wpfda_security', 'password' );
			$captcha_answer = get_option( 'wpfda_security_custom_captcha_answer', 'PERMANENTLY DELETE' );

			if ( 'password' === $security || 'recaptcha_v2' === $security ) {
				// Backwards compatibility. Removing reCAPTCHA support since 1.1.0.
				$user_id = get_current_user_id();
				$user    = get_user_by( 'id', $user_id );
				$pass    = isset( $_POST['value'] ) ? wp_unslash( $_POST['value'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

				if ( $user && wp_check_password( $pass, $user->data->user_pass, $user->ID ) ) {
					$this->delete_user();
				} else {
					wp_send_json_error(
						array(
							'message' => __( 'Invalid Password!', 'wp-frontend-delete-account' ),
						)
					);
				}
			} elseif ( 'custom_captcha' === $security ) {
				$value = sanitize_text_field( wp_unslash( $_POST['value'] ) );

				if ( $value === $captcha_answer ) {
					$this->delete_user();
				} else {
					wp_send_json_error(
						array(
							'message' => esc_html__( 'Incorrect Answer. Please try again.', 'wp-frontend-delete-account' ),
						)
					);
				}
			} elseif ( 'none' === $security ) {
				$this->delete_user();
			}//end if
		}//end if
	}

In the example code above, there are too many if..else, which means too many nested statements. You can visualize how complex the flowchart would be and the cyclomatic complexity. Such code should be refactored and we should avoid nested if else wherever possible.

Nested if conditions can sometimes be equivalent to AND operator. For example:

if (condition1) {
    if (condition2) {
       // do something
    }
}

is equivalent to:

if (condition1 && condition2) {
    // do something
}

This isn’t the only way to refactor the code, breaking into smaller functions is another option.

Ruleset of cyclomatic complexity.

It’s obvious that you won’t visualize the flowchart of every function you create and imagine its cyclomatic complexity. Cyclomatic Complexity is just another PHP Coding Standards you can add in your phpcs.xml file.

Example Ruleset:

	<rule ref="Generic.Metrics.CyclomaticComplexity">
		<properties>
			<property name="complexity" value="5"/>
			<property name="absoluteComplexity" value="7"/>
		</properties>
	</rule>

The ruleset above means it will show a warning when the complexity is 5 and above and shows an error when the complexity is 7. Anything above 7 means you should refactor your code immediately.

Ignoring the Ruleset:

Just like any other PHP Coding Standard rules, you can easily ignore this ruleset by adding a comment:

// phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded

when the complexity exceeded the max allowed, which is absoluteComplexity and 7 in the example above.

//phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh

when the complexity is tooHigh.

Here’s the full example of the phpcs.xml ruleset with the cyclomatic complexity rule.

Another rule set I usually configure in my WordPress plugins is short array syntax. WordPress Coding Standard forbids using the short array syntax. So, I use the ruleset to customize the Coding Standard by WordPress and thus allowing short array syntax.

	<!-- Allow short array syntax -->
	<rule ref="Generic.Arrays.DisallowShortArraySyntax.Found">
		<severity>0</severity>
	</rule>
	<rule ref="Generic.Arrays.DisallowLongArraySyntax.Found"/>

I hope it’s informative.

His code’s cyclomatic complexity is too high! πŸ‘‰
Tagged on:     

Sanjeev Aryal

Don't bury your thoughts, put your vision into reality ~ Bob Marley.

Leave a Reply

Your email address will not be published. Required fields are marked *

× WhatsApp