Measure cyclical complexity of Objective-C
Bài đăng này đã không được cập nhật trong 7 năm
There are vaious articles about reviewing Objective-C code, but because of there are so many "if-else
nest" inside the code so i wanted to measure the cyclical complexity of those nests
What is Cyclical Complexity Number (CCN)?
For short, because if
and switch
blocks in our code create many logic branches, so CCN is a number implies to that logic branches.
If CCN is less than 10 then the code structure is good. The structure is not good if CCN is more than 10.
But for my personal point of view, it is harder and harder to follow the code that has a more-than-5 in terms of CCN (code becomes dark)
Related Articles
Let's try to Measure
It is ok if we measure by OCLint (http://oclint.org/
) while developing, but this time I just wanted to measure so i did not use OCLint
Measure the CCN of Objective-C by terryyin/lizard (https://github.com/terryyin/lizard
)
There are so many tools for us to try, but i did search on Github and decided to use terryyin/lizard this time
I think python is already installed on your Mac so we can install it by pip
$ pip install lizard
Actual Measurement
Pods and gem can also be measured, so that we have to navigate to the directory that we want to measure and run the lizard
command
$ 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
This is the result for a brand new project with no code inside (no problem found)
Put a large amount of if
blocks and measure
I put a really bad code like this:
- (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) { }
}
Run 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 is calculated equals to 12, and a warning added too
We are able to measure the code quality now (if CNN is counted one of the criterias)
How to avoid this?
We can return sooner, and break method into smaller blocks to get rid of building a nest in our code
Bonus
Does it really "not matter" if the code has CNN less than 10?
Following is the CNN-equals-7-code looks like:
- (void)viewDidLoad {
[super viewDidLoad];
if (true) {
if (true) {
if (true) {
if (true){
if (true){
if (true){ }
}
}
}
}
}
}
6 blocks of if
makes the code looks like a mess...
We can also measure Swift code
We can get the same result if we set by SwiftLint
The CNN will be getting higher in Swift if we add more and more switch case
of enum
========================================================================================
!!!! 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
All rights reserved