Objective-C의 순환 복잡도 측정

9486 단어 SwiftObjective-C
제반 사정이 있어 Objective-C의 코드를 검토하고 있지만, if else의 중첩이 많이 순환적 복잡도를 계측하고 싶어졌기 때문에 계측해 보았다.

순환적 복잡도(CCN)란?



순환적 복잡도는 영어로 cyclomatic complexity number 이며 CCN로 약칭된다.

어쨌든 if와 switch가 많은 코드는 분기가 많아지기 때문에 그 분기를 숫자로 나타낸 것.
CCN이 10 이하인 것은 좋은 구조이며, 그 이상은 바람직하지 않다고 되어 있다.
(지표이므로, 절대적으로 그렇다고 하는 것은 아니다)

그러나 개인적으로 CCN이 5를 넘으면 코드를 쫓는 것이 힘들어진다. (코드에 따라 다름)
  • 참고
  • 순환 복잡성을 활용한 버그 잠재 위험 감소 - 현장을 위한 소프트웨어 개발 프로세스 - 타카리 일기
  • 순환 복잡성 - Wikipedia


  • 측정해보기



    OCLint 에서 개발하면서 계측하는 것이 좋을 것 같지만, 이번에는 우선 계측만 하고 싶었으므로 OCLint 는 사용하고 있지 않다.

    terryyin/lizard로 ObjC의 CCN 측정



    그 밖에도 여러가지 있는 것 같지만, GitHub 로 검색해 나온 terryyin/lizard 를 사용해 본다.

    Mac이라면 python 들어 있다고 생각하기 때문에 pip로 install 할 수 있습니다.
    $ pip install lizard
    

    실제로 측정



    Pods나 gem 등도 계측 대상이 되므로, 계측하고 싶은 코드가 있는 디렉토리로 이동해 lizard 커멘드를 실행한다.
    $ cd PROJECT_ROOT/PROJECT
    $ lizard -Tcyclomatic_complexity=10
    ================================================
      NLOC    CCN   token  PARAM  length  location
    ------------------------------------------------
           3      1     19      0       4 application: didFinishLaunchingWithOptions:@18-21@./AppDelegate.m
           2      1      9      0       4 applicationWillResignActive:@24-27@./AppDelegate.m
           2      1      9      0       4 applicationDidEnterBackground:@30-33@./AppDelegate.m
           2      1      9      0       3 applicationWillEnterForeground:@36-38@./AppDelegate.m
           2      1      9      0       3 applicationDidBecomeActive:@41-43@./AppDelegate.m
           2      1      9      0       3 applicationWillTerminate:@46-48@./AppDelegate.m
           5      1     35      2       5 main@12-16@./main.m
           3      1      8      0       4 viewDidLoad@17-20@./ViewController.m
           3      1      8      0       4 didReceiveMemoryWarning@23-26@./ViewController.m
    5 file analyzed.
    ==============================================================
    NLOC    Avg.NLOC  AvgCCN  Avg.token  function_cnt    file
    --------------------------------------------------------------
          3       0.0     0.0        0.0         0     ./AppDelegate.h
         17       2.2     1.0       10.7         6     ./AppDelegate.m
          5       5.0     1.0       35.0         1     ./main.m
          2       0.0     0.0        0.0         0     ./ViewController.h
         10       3.0     1.0        8.0         2     ./ViewController.m
    
    =============================================================================================
    No thresholds exceeded (cyclomatic_complexity > 10 or length > 1000 or parameter_count > 100)
    ==========================================================================================
    Total nloc   Avg.NLOC  AvgCCN  Avg.token   Fun Cnt  Warning cnt   Fun Rt   nloc Rt
    ------------------------------------------------------------------------------------------
            37       2.7     1.0       12.8        9            0      0.00    0.00
    

    작성해 아무것도 하고 있지 않는 Project 이므로 문제가 있는 코드는 없다고 나와 있다.

    if 문을 대량으로 두고 측정



    정신이 불안정해지는 코드 :
    - (void)viewDidLoad {
        [super viewDidLoad];
        if (true) {
            if (true) {
                if (true) {
                    if (true){
                        if (true){
                            if (true){ }
                        }
                    }
                }
            }
        } else {
            if (true) { }
        }
        if (true) { }
        if (true) { }
        if (true) { }
        if (true) { }
    }
    

    lizard 실행
    $ lizard -Tcyclomatic_complexity=10
    ... 略 ...
    
    =========================================================================================
    !!!! Warnings (cyclomatic_complexity > 10 or length > 1000 or parameter_count > 100) !!!!
    ================================================
      NLOC    CCN   token  PARAM  length  location
    ------------------------------------------------
          21     12     77      0      22 viewDidLoad@17-38@./ViewController.m
    

    CCN이 12가 되었으며 Warning에서 가르쳐주고 있습니다.

    코드의 품질을 측정 할 수 있습니다
    (단, CCN은 어디까지나 하나의 지표입니다)

    이렇게 하지 않기 위해



    조기 리턴을하거나 메소드를 분할하여 중첩을 얕게하십시오.



    정말 10 이하라면 문제 없다고 말할 수 있을까?



    이 코드에서 CNN은 7입니다.
    - (void)viewDidLoad {
        [super viewDidLoad];
        if (true) {
            if (true) {
                if (true) {
                    if (true){
                        if (true){
                            if (true){ }
                        }
                    }
                }
            }
        }
    }
    

    Swift도 측정 가능



    지금 직장에서 쓰는 코드.
    SwiftLint 로 설정하고 있기 때문에 그것과 같은 결과이지만, Swift 의 경우 enum 의 switch case 늘어나고 거기서 CCN 높아진다고 생각하지만 모두 하고 있을 것이다.
    ========================================================================================
    !!!! Warnings (cyclomatic_complexity > 5 or length > 1000 or parameter_count > 100) !!!!
    ================================================
      NLOC    CCN   token  PARAM  length  location
    ------------------------------------------------
          18     15    127      1      18 hoge@134-151@./Hoge/Error.swift
          30      8    142      1      31 hoge@28-58@./Hoge/Message.swift
          11      6    117      0      11 hoge@59-69@./Hoge/Controller.swift
    

    좋은 웹페이지 즐겨찾기