Development By The Numbers - Drupal

Transcription

DevelopmentBy The Numbers

We Are Going ToMeasure Complexity

Why Should We CareAbout Complexity?

"The Central Enemy OfReliability is Complexity"- Geer et al.

Complexity AndQuality Are StronglyRelated

Basic Metrics

CyclomaticComplexity

Cyclomatic ComplexityNumber 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

SimpleRight?

Cyclomatic Complexity(Single Method)1 - 4: Low Complexity5 - 7: Moderate Complexity8 - 10: High Complexity11 : Very High Complexity

Cyclomatic Complexity(Average Per Method)1 - 2:2 - 4:4 - 6:6 :Low ComplexityModerate ComplexityHigh ComplexityVery High Complexity

Compare:Average CC per MethodWordpress:6.28Drupal 7:3.02Drupal 8:2.10Symfony 2:1.81Zend Framework 2: 2.62Laravel:1.79

Cyclomatic Complexity(Average Per Line Of Code).01 - .05:.05 - .10:.10 - .15:.15 :Low ComplexityModerate ComplexityHigh ComplexityVery High Complexity

Compare:Average CC per LOCWordpress:0.20Drupal 7:0.04Drupal 8:0.07Symfony 2:0.06Zend Framework 2: 0.10Laravel:0.07

N-PathComplexity

N-Path ComplexityNumber 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 AreThe Same?

NotGenerally!

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:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath:

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath: 8

function foo2( a, b, c) { d 0;if ( a) { d a;}if ( b) { d b;}if ( c) { d c;}return d;}CC:4NPath: 82 (CC-1)

N-Path Complexity 16:Low Complexity17-128: Moderate Complexity129-1024: High Complexity1025 : Very High Complexity

N-Path ComplexityMinimum Number OfTests Required ToCompletely TestA Routine

N-Path Complexityentity load()CC:N-Path:

N-Path Complexityentity load()CC: 2N-Path:

Cyclomatic Complexity1 - 4: Low Complexity5 - 7: Moderate Complexity8 - 10: High Complexity11 : Very High Complexity

N-Path Complexityentity load()CC: 2N-Path: 2

N-Path Complexitydrupal http request()CC:N-Path:

N-Path Complexitydrupal http request()CC: 41N-Path:

Cyclomatic Complexity1 - 4: Low Complexity5 - 7: Moderate Complexity8 - 10: High Complexity11 : Very High Complexity

N-Path Complexitydrupal http request()CC: 41N-Path: 25,303,344,960

To Completely Testdrupal http request()At 1 Line Of Code Per TestWould Require2 TerabytesWorth Of Tests

To Completely Testdrupal http request()At 1 Line Of Code Per TestWould Require412 DVD'sWorth Of Tests

To Completely Testdrupal http request()At 1 Line Of Code Per TestWould Require670k DrupalsWorth Of Tests

And That's NotThe Worst One!

N-Path Complexitydate repeat rrule process()CC:N-Path:

N-Path Complexitydate repeat rrule process()CC: 81N-Path:

N-Path Complexitydate repeat rrule process()CC: 81N-Path: 19,781,719,256

N-Path Complexitydate repeat rrule process()CC: 81N-Path: 19,781,719,256,250,000,000,000

N-Path Complexitydate repeat rrule process()CC: 81N-Path: 19,781,719,256,250,000,000,000,000,000,000

To Completely Testdate repeat rrule process()At 1 Line Of Code Per TestWould Require336T 2009'sWorth Of Tests

To Completely Testdate repeat rrule process()At 1 Line Of Code Per TestWould Require1 Greenland Ice Cap ofmicroSD cardsWorth Of Tests

CRAP

CRAP(Change Risk Analysis Predictions)

CC Cyclomatic Complexity (method)COV Test Coverage (percent)CRAP CC (CC 2 * (1 - COV) 3)

CRAPRelates ComplexityAnd Test Coverage

CRAPIncreasing Test Coverage Lowers CRAPDecreasing Complexity Lowers CRAP

CRAPA Low Complexity MethodWith No TestsIs Good

CRAPA Low Complexity MethodWith Good TestsIs Great

CRAPA Moderate Complexity MethodWith Good TestsIs OK

CRAPA Moderate Complexity MethodWith No TestsIs CRAP

CRAP 5:5 - 15:15-30:30 :GREAT CodeAcceptable CodeEih. CodeCRAPpy Code

How Do WeApply TheseMetrics?

Sebastian pqatools.orgwww.jenkins-php.org

PHPLOC

PHPLOCBy Sebastian Bergmann

PHPLOCBy Sebastian BergmannCommand Line Tool

PHPLOCBy Sebastian BergmannCommand Line ToolSummarizes An EntireCodebase

phploc path/to/Drupal7/Directories: 73Files:180Lines of Code (LOC):63347Cyclomatic Complexity / Lines of Code: 0.04Comment Lines of Code (CLOC):19321Non-Comment Lines of Code (NCLOC):44026

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

Methods:433Scope:Non-Static: 378 (87.30%)Static:55 (12.70%)Visibility:Public:255 (58.89%)Non-Public: 178 (41.11%)Average Method Length (NCLOC): 17Cyclomatic Complexity / Number of Methods: 3.02Anonymous Functions:0Functions:521Constants:22Global constants: 15Class constants:7

PDepend

PDependBy Manuel Pichler(Also German)

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

PDependBy Manuel Pichler(Also German)Like PHPLOC, But GranularLower Level Analysis

Fanout: Describes Outward Dependencies- Describes Dependence on Other ClassesANDC: Average Num of Derived Classes- Describes How Much Inheritance Is UsedAHH: Average Hiearchy Height- Describes How Deep Of Inheritance Is Used

PHPMD(Mess Detector)

PHPMDBy Manuel Pichler(German)

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

PHPMDBy Manuel Pichler(German)Finds "Messy" Parts Of CodeFinds Rule Violations

PHPMD RulesCodeSize- (CC, NPath, Number of Methods, Size of Methods, etc)Design- (Eval, Goto, Exit(), Inheritance Depth)Naming- (Short names, Inconsistent Names)Unused CodeControversial- (Superglobal Access, Naming Conventions)

Prevent Complex CodeFrom Even Getting In!

By ThemselvesUseful

Over Time

Over TimeInvaluable

Drupal 8.x BranchNon-Comment Lines Of Code

Drupal 8.x BranchNumber Of Classes

Drupal 8.x BranchCyclomatic Complexity Per Method

Drupal 8.x BranchCyclomatic Complexity Per Line

Drupal 8.x Branch

One More ThingTo Keep In Mind

Anthony utube.com/ircmaxell

Cyclomatic Complexity (Average Per Method) 1 - 2: Low Complexity 2 - 4: Moderate Complexity 4 - 6: High Complexity 6 : Very High Complexity