Development By The Numbers We Are Going To Measure Complexity Why - - PowerPoint PPT Presentation

development by the numbers we are going to measure
SMART_READER_LITE
LIVE PREVIEW

Development By The Numbers We Are Going To Measure Complexity Why - - PowerPoint PPT Presentation

Development By The Numbers We Are Going To Measure Complexity Why Should We Care About Complexity? "The Central Enemy Of Reliability is Complexity" - Geer et al. Complexity And Quality Are Strongly Related Basic Metrics


slide-1
SLIDE 1

Development By The Numbers

slide-2
SLIDE 2
slide-3
SLIDE 3
slide-4
SLIDE 4
slide-5
SLIDE 5
slide-6
SLIDE 6

We Are Going To Measure Complexity

slide-7
SLIDE 7

Why Should We Care About Complexity?

slide-8
SLIDE 8
  • Geer et al.

"The Central Enemy Of Reliability is Complexity"

slide-9
SLIDE 9

Complexity And Quality Are Strongly Related

slide-10
SLIDE 10
slide-11
SLIDE 11

Basic Metrics

slide-12
SLIDE 12

Cyclomatic Complexity

slide-13
SLIDE 13

Cyclomatic Complexity

Number Of "Decision Points" In A Routine

slide-14
SLIDE 14

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

slide-15
SLIDE 15

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

slide-16
SLIDE 16

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

4

slide-17
SLIDE 17

Simple Right?

slide-18
SLIDE 18
slide-19
SLIDE 19

Cyclomatic Complexity (Single Method)

1 - 4: Low Complexity 5 - 7: Moderate Complexity 8 - 10: High Complexity 11+: Very High Complexity

slide-20
SLIDE 20

Cyclomatic Complexity (Average Per Method)

1 - 2: Low Complexity 2 - 4: Moderate Complexity 4 - 6: High Complexity 6+: Very High Complexity

slide-21
SLIDE 21

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

slide-22
SLIDE 22

Cyclomatic Complexity (Average Per Line Of Code)

.01 - .05: Low Complexity .05 - .10: Moderate Complexity .10 - .15: High Complexity .15+: Very High Complexity

slide-23
SLIDE 23

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

slide-24
SLIDE 24
slide-25
SLIDE 25

N-Path Complexity

slide-26
SLIDE 26

N-Path Complexity

Number Of "Unique Paths" In A Routine

slide-27
SLIDE 27

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

slide-28
SLIDE 28

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

slide-29
SLIDE 29

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

slide-30
SLIDE 30

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

slide-31
SLIDE 31

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

slide-32
SLIDE 32

function foo($a, $b) { $c = 0; if ($a) { $c = $a; } elseif ($b) { $c = $b; } if ($a && $b) { $c = $a + $b; } return $c; }

4

slide-33
SLIDE 33

They Are The Same?

slide-34
SLIDE 34

Not Generally!

slide-35
SLIDE 35

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: NPath:

slide-36
SLIDE 36

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: NPath:

slide-37
SLIDE 37

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-38
SLIDE 38

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-39
SLIDE 39

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-40
SLIDE 40

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-41
SLIDE 41

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-42
SLIDE 42

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-43
SLIDE 43

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-44
SLIDE 44

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-45
SLIDE 45

function foo2($a, $b, $c) { $d = 0; if ($a) { $d += $a; } if ($b) { $d += $b; } if ($c) { $d += $c; } return $d; }

CC: 4 NPath:

slide-46
SLIDE 46

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

slide-47
SLIDE 47

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)

slide-48
SLIDE 48

N-Path Complexity

<16: Low Complexity 17-128: Moderate Complexity 129-1024: High Complexity 1025+: Very High Complexity

slide-49
SLIDE 49
slide-50
SLIDE 50

N-Path Complexity

Minimum Number Of Tests Required To Completely Test A Routine

slide-51
SLIDE 51
slide-52
SLIDE 52
slide-53
SLIDE 53

N-Path Complexity

entity_load() CC: N-Path:

slide-54
SLIDE 54

N-Path Complexity

entity_load() CC: 2 N-Path:

slide-55
SLIDE 55

Cyclomatic Complexity

1 - 4: Low Complexity 5 - 7: Moderate Complexity 8 - 10: High Complexity 11+: Very High Complexity

slide-56
SLIDE 56

N-Path Complexity

entity_load() CC: 2 N-Path: 2

slide-57
SLIDE 57
slide-58
SLIDE 58

N-Path Complexity

drupal_http_request() CC: N-Path:

slide-59
SLIDE 59
slide-60
SLIDE 60
slide-61
SLIDE 61
slide-62
SLIDE 62
slide-63
SLIDE 63

N-Path Complexity

drupal_http_request() CC: 41 N-Path:

slide-64
SLIDE 64

Cyclomatic Complexity

1 - 4: Low Complexity 5 - 7: Moderate Complexity 8 - 10: High Complexity 11+: Very High Complexity

slide-65
SLIDE 65

N-Path Complexity

drupal_http_request() CC: 41 N-Path: 25,303,344,960

slide-66
SLIDE 66
slide-67
SLIDE 67

To Completely Test

drupal_http_request() At 1 Line Of Code Per Test

Would Require

2 Terabytes

Worth Of Tests

slide-68
SLIDE 68

To Completely Test

drupal_http_request() At 1 Line Of Code Per Test

Would Require

412 DVD's

Worth Of Tests

slide-69
SLIDE 69

To Completely Test

drupal_http_request() At 1 Line Of Code Per Test

Would Require

670k Drupals

Worth Of Tests

slide-70
SLIDE 70

And That's Not The Worst One!

slide-71
SLIDE 71
slide-72
SLIDE 72

N-Path Complexity _date_repeat_rrule_process()

CC: N-Path:

slide-73
SLIDE 73

N-Path Complexity _date_repeat_rrule_process()

CC: 81 N-Path:

slide-74
SLIDE 74

N-Path Complexity _date_repeat_rrule_process()

CC: 81 N-Path: 19,781,719,256

slide-75
SLIDE 75

N-Path Complexity _date_repeat_rrule_process()

CC: 81 N-Path: 19,781,719,256 ,250,000,000,000

slide-76
SLIDE 76

N-Path Complexity _date_repeat_rrule_process()

CC: 81 N-Path: 19,781,719,256 ,250,000,000,000 ,000,000,000

slide-77
SLIDE 77

To Completely Test

_date_repeat_rrule_process() At 1 Line Of Code Per Test

Would Require

336T 2009's

Worth Of Tests

slide-78
SLIDE 78

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

slide-79
SLIDE 79
slide-80
SLIDE 80

CRAP

slide-81
SLIDE 81
slide-82
SLIDE 82

CRAP

(Change Risk Analysis Predictions)

slide-83
SLIDE 83

CC = Cyclomatic Complexity (method)

COV = Test Coverage (percent) CRAP = CC + (CC^2 * (1 - COV)^3)

slide-84
SLIDE 84
slide-85
SLIDE 85

CRAP

Relates Complexity And Test Coverage

slide-86
SLIDE 86

CRAP

Increasing Test Coverage Lowers CRAP Decreasing Complexity Lowers CRAP

slide-87
SLIDE 87

CRAP

A Low Complexity Method With No Tests

Is Good

slide-88
SLIDE 88

CRAP

A Low Complexity Method With Good Tests

Is Great

slide-89
SLIDE 89

CRAP

A Moderate Complexity Method With Good Tests

Is OK

slide-90
SLIDE 90

CRAP

A Moderate Complexity Method With No Tests

Is CRAP

slide-91
SLIDE 91

CRAP < 5: GREAT Code 5 - 15: Acceptable Code 15-30: Eih... Code 30+: CRAPpy Code

slide-92
SLIDE 92
slide-93
SLIDE 93

How Do We Apply These Metrics?

slide-94
SLIDE 94
slide-95
SLIDE 95
slide-96
SLIDE 96
slide-97
SLIDE 97

Sebastian Bergmann

PHPUnit DbUnit PHPLOC PHPCPD PHPCOV hphpa

www.phpqatools.org www.jenkins-php.org

slide-98
SLIDE 98

PHPLOC

slide-99
SLIDE 99

PHPLOC

By Sebastian Bergmann

slide-100
SLIDE 100

PHPLOC

By Sebastian Bergmann Command Line Tool

slide-101
SLIDE 101

PHPLOC

By Sebastian Bergmann Command Line Tool Summarizes An Entire Codebase

slide-102
SLIDE 102

$ 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

slide-103
SLIDE 103

Namespaces: 0 Interfaces: 1 Traits: 0 Classes: 38 Abstract: 2 (5.26%) Concrete: 36 (94.74%) Average Class Length (NCLOC): 197

slide-104
SLIDE 104

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

slide-105
SLIDE 105

PDepend

slide-106
SLIDE 106

PDepend

By Manuel Pichler (Also German)

slide-107
SLIDE 107

PDepend

By Manuel Pichler (Also German) Like PHPLOC, But Granular

slide-108
SLIDE 108

PDepend

By Manuel Pichler (Also German) Like PHPLOC, But Granular Lower Level Analysis

slide-109
SLIDE 109
slide-110
SLIDE 110

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
slide-111
SLIDE 111

PHPMD (Mess Detector)

slide-112
SLIDE 112

PHPMD

By Manuel Pichler (German)

slide-113
SLIDE 113

PHPMD

By Manuel Pichler (German) Finds "Messy" Parts Of Code

slide-114
SLIDE 114

PHPMD

By Manuel Pichler (German) Finds "Messy" Parts Of Code Finds Rule Violations

slide-115
SLIDE 115

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)
slide-116
SLIDE 116
slide-117
SLIDE 117

Prevent Complex Code From Even Getting In!

slide-118
SLIDE 118

By Themselves Useful

slide-119
SLIDE 119

Over Time

slide-120
SLIDE 120

Over Time Invaluable

slide-121
SLIDE 121

Drupal 8.x Branch Non-Comment Lines Of Code

slide-122
SLIDE 122

Drupal 8.x Branch Number Of Classes

slide-123
SLIDE 123

Drupal 8.x Branch

Cyclomatic Complexity Per Method

slide-124
SLIDE 124

Drupal 8.x Branch Cyclomatic Complexity Per Line

slide-125
SLIDE 125

Drupal 8.x Branch

slide-126
SLIDE 126
slide-127
SLIDE 127
slide-128
SLIDE 128
slide-129
SLIDE 129

One More Thing To Keep In Mind

slide-130
SLIDE 130
slide-131
SLIDE 131
slide-132
SLIDE 132

Anthony Ferrara @ircmaxell

ircmaxell@php.net

anthony.ferrara@nbcuni.com

blog.ircmaxell.com github.com/ircmaxell youtube.com/ircmaxell