Complexity greater than authorized in AngularJS Co

2019-02-26 06:02发布

问题:

I use SonarLint with Eclipse, and I'm codding an application using AngularJS. I had a problem with a controller so I was trying to clean it a bit to see clearer, and then SonarLint popped me up an issue :

Function has a complexity of 11 which is greater than 10 authorized.

And here's the code of my controller :

app.controller('LauncherCtrl', function ($scope, $http) {

    $scope.genStatus = "stopped";

    $scope.startgenerator = function() {
        $http.get('/start').success(function () {
            $scope.updateStatus();
        });
    };

    $scope.resumegenerator = function() {
        $http.get('/resume').success(function () {
            $scope.updateStatus();
        });
    };

    $scope.suspendgenerator = function() {
        $http.get('/suspend').success(function () {
            $scope.updateStatus();
        });
    };

    $scope.stopgenerator = function() {
        $http.get('/stop').success(function () {
            $scope.updateStatus();
        });
    };

    $scope.updateStatus = function() {              
        $http.get('/status').success(function (response) {
              $scope.genStatus = response.data;
        });
    };

    $scope.updateStatus();
});

Is there something wrong with it ? I assume this issue would be about too much nested loops/functions, but as far as I can see it's not (apart from the functions start/stop/resume/pause which are calling update, but it isn't complexity 11, is it ?). + I double checked the brackets/parenthesis, I don't think the problem comes from there.

回答1:

If you want to remove complexity you can make one function :

    $scope.startgenerator = function() {
        $http.get('/start').success(function () {
            $scope.updateStatus();
        });
    };

    $scope.resumegenerator = function() {
        $http.get('/resume').success(function () {
            $scope.updateStatus();
        });
    };

    $scope.suspendgenerator = function() {
        $http.get('/suspend').success(function () {
            $scope.updateStatus();
        });
    };

    $scope.stopgenerator = function() {
        $http.get('/stop').success(function () {
            $scope.updateStatus();
        });
    };

to

$scope.generatorAction = function(action) {
    $http.get('/' + action).success(function () {
        $scope.updateStatus();
    });
};

and then use it like this:

$scope.generatorAction('stop');

Or use a service that handle your http request, It's a better practice.

Edit:

I'm using this styleguide for my angular applications : https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md

Creating a simple service for your http request :

(function() {
  'use strict';

  angular
    .module('yourModuleName')
    .factory('generator', generatorFactory);

  function generatorFactory($http) {

     var service = {
        start: start,
        resume: resume,
        suspend: suspend,
        stop: stop
     }

     return service;

     function start() {
        return $http.get('/start');
     }

     function resume() {
        return $http.get('/start');
     }

     function suspend() {
        return $http.get('/suspend');
     }

     function stop() {
        return $http.get('/stop');
     }
  }

})();

And then in your controller:

app.controller('LauncherCtrl', function ($scope, generator, $http) {

    $scope.genStatus = "stopped";

    $scope.startgenerator = function() {
        generator.start().then(function () {
            $scope.updateStatus();
        });
    };

    $scope.resumegenerator = function() {
        generator.resume().then(function () {
            $scope.updateStatus();
        });
    };

    $scope.suspendgenerator = function() {
        generator.suspend().then(function () {
            $scope.updateStatus();
        });
    };

    $scope.stopgenerator = function() {
        generator.stop().then(function () {
            $scope.updateStatus();
        });
    };

    $scope.updateStatus = function() {              
        $http.get('/status').success(function (response) {
              $scope.genStatus = response.data;
        });
    };

    $scope.updateStatus();
});

First it seems to take more code and more complexity to your app, but if you need to stop your generator in an other page or in a component/directive, you just have to inject your 'generator' service and do generator.stop(); and by doing this, if one day your endpoint url changed, you only have to change them in your service.



回答2:

Is there something wrong with it?

You're looking for an objective answer to a subjective question. Let's say that the more complex a function gets, the more you (or someone else) will struggle to maintain it. This issue is telling you that you've reached an arbitrary point where the code may be getting hard to understand.

it isn't complexity 11, is it?

The way SonarQube counts complexity doesn't quite match any of the currently enunciated standards, but here's how it got the number 11:

app.controller('LauncherCtrl', function ($scope, $http) {  // +1

    $scope.genStatus = "stopped";

    $scope.startgenerator = function() {                   // +1
        $http.get('/start').success(function () {          // +1
            $scope.updateStatus();
        });
    };

    $scope.resumegenerator = function() {                 // +1
        $http.get('/resume').success(function () {        // +1
            $scope.updateStatus();
        });
    };

    $scope.suspendgenerator = function() {                // +1
        $http.get('/suspend').success(function () {       // +1
            $scope.updateStatus();
        });
    };

    $scope.stopgenerator = function() {                   // +1
        $http.get('/stop').success(function () {          // +1
            $scope.updateStatus();
        });
    };

    $scope.updateStatus = function() {                    // +1
        $http.get('/status').success(function (response) {// +1
              $scope.genStatus = response.data;
        });
    };

    $scope.updateStatus();
});