重构此方法可将其认知复杂度从21降低到允许的15.如何重构并降低复杂性 [英] Refactor this method to reduce its Cognitive Complexity from 21 to the 15 allowed. How to refactor and reduce the complexity

查看:2997
本文介绍了重构此方法可将其认知复杂度从21降低到允许的15.如何重构并降低复杂性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何降低给定代码段的复杂性?我在Sonarqube中收到此错误->重构该方法,将其认知复杂度从21降低到允许的15.

how to reduce the complexity of the given piece of code? I am getting this error in Sonarqube---> Refactor this method to reduce its Cognitive Complexity from 21 to the 15 allowed.

this.deviceDetails = this.data && {...this.data.deviceInfo} || {};
    if (this.data && this.data.deviceInfo) {
      this.getSessionInfo();
      // tslint:disable-next-line: no-shadowed-variable
      const { device, driver, ipAddress, port, active, connectionType } = this.data.deviceInfo;
      this.deviceDetails = {
        name: device.name || '',
        manufacturer: device.manufacturer || '',
        deviceType: device.deviceType || '',
        model: device.model || '',
        description: device.description || '',
        managerId: device.deviceManager && device.deviceManager.managerId || null,
        locationId: device.location && device.location.locationId || null,
        active: device.active,
        connectionType: connectionType || null,
        driver_id: driver && driver.driverId || null,
        ipAddress: ipAddress || '',
        port: String(port) || '',
        connectionStatus: active,
      };
      this.oldDeviceDetails = {...this.deviceDetails};
      this.deviceLocation = device.location && device.location.locationId || null;
    } else {

推荐答案

关于圈复杂度的工作原理以及为什么应将其保持在较低水平的一些信息

首先,重要的是要了解"认知复杂性"是如何实现的.与"环复杂性"相比,它的工作原理更为有效.认知复杂性考虑了人脑感知的复杂性.这就是为什么它不能简单地指出条件路径的数量(简化了条件数量,而return语句则加1).

First of all it is important to understand how "Cognitive Complexity" works as compared to "Cyclomatic Complexity". Cognitive complexity takes into account the complexity perceived by the human brain. This is why it does not simply indicate the number of conditional paths (simplified the number of conditionals plus 1 for the return statement).

另一方面,圈复杂度考虑了嵌套条件(例如,if语句内部的if),这使得阅读和理解代码更加困难从人类的角度来看.

The cyclomatic complexity on the other hand also considers nested conditions (e.g. an if inside an inside an if statement) which makes it even harder to read and understand the code from a human's perspective.

SonarQube文档中的以下示例( https://www.sonarsource.com/docs /CognitiveComplexity.pdf )概述了我要解释的内容:

The following sample from the SonarQube documentation (https://www.sonarsource.com/docs/CognitiveComplexity.pdf) outlines what I'm trying to explain:

if (someVariableX > 3) { // +1
    if (someVariableY < 3) { // +2, nesting = 1
        if (someVariableZ === 8) { // +3, nesting = 2
            someResult = someVariableX + someVariableY - someVariableZ;
        }
    }
}

因此请注意,二进制运算会增加复杂性,但嵌套条件会为每个嵌套条件加1分.这里的认知复杂度为6,而循环复杂度仅为4(每个条件一个,返回路径一个);

So be aware that binary operations add to the complexity but nested conditions add a score of plus 1 for each nested condition. Here the cognitive complexity would be 6, while the cyclomatic complexity would only be 4 (one for each conditional and one for the return path);

例如,如果您使代码对人类更易读,通过从包含条件的行中提取方法,您可以同时实现更好的可读性和更少的循环复杂性.

If you make your code more readable for a human, e.g. by extracting methods from lines that contain conditionals you achieve both, better readability and less cyclomatic complexity.

尽管您提供的代码没有嵌套条件,但我认为重要的是首先了解圈复杂度计算的工作原理,以及为什么将其保持在较低水平是个好主意.

Although the code you provided does not have nested conditionals I think it is important to first understand how cyclomatic complexity calculation works and why it is a good idea to keep it low.

[TL; DR]一种将代码重构为不太复杂且可读性更好的版本的可能方法

让我们首先看一下注释所概述的代码的复杂度计算是如何完成的:

Let's first look how the complexity calcuation is done for your code as outlined by the comments:

if (this.data && this.data.deviceInfo) { // +1 for the if conditaionl, +1 for the binary operator
    this.getSessionInfo();

    const { device, driver, ipAddress, port, active, connectionType } =             
    this.data.deviceInfo;
    this.deviceDetails = {
        name: device.name || '', // +1 for the binary operator
        manufacturer: device.manufacturer || '', // +1 for the binary operator
        deviceType: device.deviceType || '', // +1 for the binary operator
        model: device.model || '', // +1 for the binary operator
        description: device.description || '', // +1 for the binary operator
        managerId: device.deviceManager && device.deviceManager.managerId || null, // +2 for the varying binary operators
        locationId: device.location && device.location.locationId || null, // +2 for the varying binary operator
        active: device.active,
        connectionType: connectionType || null, // +1 for the binary operator
        driver_id: driver && driver.driverId || null, // +2 for the varying binary operator
        ipAddress: ipAddress || '', // +1 for the binary operator
        port: String(port) || '', // +1 for the binary operator
        connectionStatus: active,
    };
    this.oldDeviceDetails = { ...this.deviceDetails };
    this.deviceLocation = device.location && device.location.locationId || null; // +2 for the varying binary operator
} else { // +1 for the else path 
    // some statement
}

这可能是代码的重构版本(通过快速手动计数而不进行真正的SonarQube分析)可以将认知复杂度降低到12.(请注意,这只是手动计算.)

This could be a refactored version of your code which (from a quick manual count without real SonarQube analysis) should lower the cognitive complexity down to 12. (Please be aware that this is just a manual calculation.)

可以通过应用简单的重构(例如提取方法和/或移动方法)来完成(另请参阅Martin Fowler,

It can be done by applying simple refactorings such as extract method and/or move method (see also Martin Fowler, https://refactoring.com/catalog/extractFunction.html).

this.deviceDetails = this.data && { ...this.data.deviceInfo } || {}; // +2
if (deviceInfoAvailable()) { // +1 for the if statement
    this.getSessionInfo();
    // tslint:disable-next-line: no-shadowed-variable
    const { device, driver, ipAddress, port, active, connectionType } = this.data.deviceInfo;
    this.deviceDetails = {
        name: getInfoItem(device.name), 
        manufacturer: getInfoItem(device.manufacturer),
        deviceType: getInfoItem(device.deviceType),
        model: getInfoItem(device.model),
        description: getInfoItem(device.description), 
        managerId: getManagerId(device),
        locationId: getDeviceLocation(device),
        active: device.active,
        connectionType: getInfoItem(connectionType), 
        driver_id: getDriverId(driver), 
        ipAddress: getInfoItem(ipAddress), 
        port: getInfoItem(port), 
        connectionStatus: active,
    };
    this.oldDeviceDetails = { ...this.deviceDetails };
    this.deviceLocation = getDeviceLocation(device);
} else { // +1 for the else
    // some statement
}

function getDriverId(driver) {
    return driver && driver.driverId || null; // +2 for the binary operators
}

function getDeviceLocation(device) {
    return device.location && device.location.locationId || null; // +2 for the binary operators
}

function getManagerId(device) {
    return device.deviceManager && device.deviceManager.managerId || null; // +2 for the binary operators
}

function deviceInfoAvailable() {
    return this.data && this.data.deviceInfo; // +1 for the binary operator
}

function getInfoItem(infoItem) {
    return infoItem || ''; // +1 for the binary operator
}

使用简单的提取方法重构很多重复(请参见getInfoItem()函数)消除了,这使降低复杂性和增加复杂性变得容易可读性.

With the simple extract method refactorings lots of duplications (see getInfoItem() function) got eliminated as well which makes it easy to reduce the complexity and increase the readability.

说实话,我什至会更进一步,甚至重新构造代码,以便在提供设备详细信息时检查空项目和设置默认值(此处为空字符串)的逻辑由设备完成类或设备详细信息类本身,以具有更好的数据凝聚力以及对数据进行操作的逻辑.但由于我不知道其余的代码,因此这种初始重构应该使您更进一步,以提高可读性和降低复杂性.

To be honest, I would even go some steps further and restructure your code even more so that the logic for checking for empty items and setting a default value (here an empty string) when providing the device details is done by the device class or a device details class itself to have better cohesion of the data and the logic that operates on that data. But as I don't know the rest of the code this inital refactoring should get you one step further to better readability and less complexity.

这篇关于重构此方法可将其认知复杂度从21降低到允许的15.如何重构并降低复杂性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆