SlideShare a Scribd company logo
Development
By The Numbers
Development by the numbers
Development by the numbers
Development by the numbers
Development by the numbers
We Are Going To
Measure Complexity
Why Should We Care
About Complexity?
- Geer et al.
"The Central Enemy Of
Reliability is Complexity"
Complexity And
Quality Are Strongly
Related
Development by the numbers
Basic Metrics
Cyclomatic
Complexity
Cyclomatic Complexity
Number Of
"Decision Points"
In A Routine
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
4
Simple
Right?
Development by the numbers
Cyclomatic Complexity
(Single Method)
1 - 4: Low Complexity
5 - 7: Moderate Complexity
8 - 10: High Complexity
11+: Very High Complexity
Cyclomatic Complexity
(Average Per Method)
1 - 2: Low Complexity
2 - 4: Moderate Complexity
4 - 6: High Complexity
6+: Very High Complexity
Compare:
Average CC per Method
Wordpress: 6.28
Drupal 7: 3.02
Drupal 8: 2.10
Symfony 2: 1.81
Zend Framework 2: 2.62
Laravel: 1.79
Cyclomatic Complexity
(Average Per Line Of Code)
.01 - .05: Low Complexity
.05 - .10: Moderate Complexity
.10 - .15: High Complexity
.15+: Very High Complexity
Compare:
Average CC per LOC
Wordpress: 0.20
Drupal 7: 0.04
Drupal 8: 0.07
Symfony 2: 0.06
Zend Framework 2: 0.10
Laravel: 0.07
Development by the numbers
N-Path
Complexity
N-Path Complexity
Number Of
"Unique Paths"
In A Routine
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
function foo($a, $b) {
$c = 0;
if ($a) {
$c = $a;
} elseif ($b) {
$c = $b;
}
if ($a && $b) {
$c = $a + $b;
}
return $c;
}
4
They Are
The Same?
Not
Generally!
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC:
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC:
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath:
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath: 8
function foo2($a, $b, $c) {
$d = 0;
if ($a) {
$d += $a;
}
if ($b) {
$d += $b;
}
if ($c) {
$d += $c;
}
return $d;
}
CC: 4
NPath: 8
2^(CC-1)
N-Path Complexity
<16: Low Complexity
17-128: Moderate Complexity
129-1024: High Complexity
1025+: Very High Complexity
Development by the numbers
N-Path Complexity
Minimum Number Of
Tests Required To
Completely Test
A Routine
Development by the numbers
Development by the numbers
N-Path Complexity
entity_load()
CC:
N-Path:
N-Path Complexity
entity_load()
CC: 2
N-Path:
Cyclomatic Complexity
1 - 4: Low Complexity
5 - 7: Moderate Complexity
8 - 10: High Complexity
11+: Very High Complexity
N-Path Complexity
entity_load()
CC: 2
N-Path: 2
Development by the numbers
N-Path Complexity
drupal_http_request()
CC:
N-Path:
Development by the numbers
Development by the numbers
Development by the numbers
Development by the numbers
N-Path Complexity
drupal_http_request()
CC: 41
N-Path:
Cyclomatic Complexity
1 - 4: Low Complexity
5 - 7: Moderate Complexity
8 - 10: High Complexity
11+: Very High Complexity
N-Path Complexity
drupal_http_request()
CC: 41
N-Path: 25,303,344,960
Development by the numbers
To Completely Test
drupal_http_request()
At 1 Line Of Code Per Test
Would Require
2 Terabytes
Worth Of Tests
To Completely Test
drupal_http_request()
At 1 Line Of Code Per Test
Would Require
412 DVD's
Worth Of Tests
To Completely Test
drupal_http_request()
At 1 Line Of Code Per Test
Would Require
670k Drupals
Worth Of Tests
And That's Not
The Worst One!
Development by the numbers
N-Path Complexity
_date_repeat_rrule_process()
CC:
N-Path:
N-Path Complexity
_date_repeat_rrule_process()
CC: 81
N-Path:
N-Path Complexity
_date_repeat_rrule_process()
CC: 81
N-Path: 19,781,719,256
N-Path Complexity
_date_repeat_rrule_process()
CC: 81
N-Path: 19,781,719,256
,250,000,000,000
N-Path Complexity
_date_repeat_rrule_process()
CC: 81
N-Path: 19,781,719,256
,250,000,000,000
,000,000,000
To Completely Test
_date_repeat_rrule_process()
At 1 Line Of Code Per Test
Would Require
336T 2009's
Worth Of Tests
To Completely Test
_date_repeat_rrule_process()
At 1 Line Of Code Per Test
Would Require
1 Greenland Ice Cap of
microSD cards
Worth Of Tests
Development by the numbers
CRAP
Development by the numbers
CRAP
(Change Risk Analysis Predictions)
CC = Cyclomatic Complexity (method)
COV = Test Coverage (percent)
CRAP = CC + (CC^2 * (1 - COV)^3)
Development by the numbers
CRAP
Relates Complexity
And Test Coverage
CRAP
Increasing Test Coverage Lowers CRAP
Decreasing Complexity Lowers CRAP
CRAP
A Low Complexity Method
With No Tests
Is Good
CRAP
A Low Complexity Method
With Good Tests
Is Great
CRAP
A Moderate Complexity Method
With Good Tests
Is OK
CRAP
A Moderate Complexity Method
With No Tests
Is CRAP
CRAP
< 5: GREAT Code
5 - 15: Acceptable Code
15-30: Eih... Code
30+: CRAPpy Code
Development by the numbers
How Do We
Apply These
Metrics?
Development by the numbers
Development by the numbers
Development by the numbers
Sebastian Bergmann
PHPUnit
DbUnit
PHPLOC
PHPCPD
PHPCOV
hphpa
www.phpqatools.org
www.jenkins-php.org
PHPLOC
PHPLOC
By Sebastian Bergmann
PHPLOC
By Sebastian Bergmann
Command Line Tool
PHPLOC
By Sebastian Bergmann
Command Line Tool
Summarizes An Entire
Codebase
$ phploc path/to/Drupal7/
Directories: 73
Files: 180
Lines of Code (LOC): 63347
Cyclomatic Complexity / Lines of Code: 0.04
Comment Lines of Code (CLOC): 19321
Non-Comment Lines of Code (NCLOC): 44026
Namespaces: 0
Interfaces: 1
Traits: 0
Classes: 38
Abstract: 2 (5.26%)
Concrete: 36 (94.74%)
Average Class Length (NCLOC): 197
Methods: 433
Scope:
Non-Static: 378 (87.30%)
Static: 55 (12.70%)
Visibility:
Public: 255 (58.89%)
Non-Public: 178 (41.11%)
Average Method Length (NCLOC): 17
Cyclomatic Complexity / Number of Methods: 3.02
Anonymous Functions: 0
Functions: 521
Constants: 22
Global constants: 15
Class constants: 7
PDepend
PDepend
By Manuel Pichler
(Also German)
PDepend
By Manuel Pichler
(Also German)
Like PHPLOC, But Granular
PDepend
By Manuel Pichler
(Also German)
Like PHPLOC, But Granular
Lower Level Analysis
Development by the numbers
Fanout: Describes Outward Dependencies
- Describes Dependence on Other Classes
ANDC: Average Num of Derived Classes
- Describes How Much Inheritance Is Used
AHH: Average Hiearchy Height
- Describes How Deep Of Inheritance Is Used
PHPMD
(Mess Detector)
PHPMD
By Manuel Pichler
(German)
PHPMD
By Manuel Pichler
(German)
Finds "Messy" Parts Of Code
PHPMD
By Manuel Pichler
(German)
Finds "Messy" Parts Of Code
Finds Rule Violations
PHPMD Rules
CodeSize
- (CC, NPath, Number of Methods, Size of Methods, etc)
Design
- (Eval, Goto, Exit(), Inheritance Depth)
Naming
- (Short names, Inconsistent Names)
Unused Code
Controversial
- (Superglobal Access, Naming Conventions)
Development by the numbers
Prevent Complex Code
From Even Getting In!
By Themselves
Useful
Over Time
Over Time
Invaluable
Drupal 8.x Branch
Non-Comment Lines Of Code
Drupal 8.x Branch
Number Of Classes
Drupal 8.x Branch
Cyclomatic Complexity Per Method
Drupal 8.x Branch
Cyclomatic Complexity Per Line
Drupal 8.x Branch
Development by the numbers
Development by the numbers
Development by the numbers
One More Thing
To Keep In Mind
Development by the numbers
Development by the numbers
Anthony Ferrara
@ircmaxell
ircmaxell@php.net
anthony.ferrara@nbcuni.com
blog.ircmaxell.com
github.com/ircmaxell
youtube.com/ircmaxell

More Related Content

Development by the numbers