php benelux 2012: magic behind the numbers. software metrics in practice

Post on 14-Dec-2014

1.892 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

We use static code analysis tools more often these days that create great reports and funky graphs. But do we understand what it all means? Software metrics tends to be magic numbers for a lot of people, but they don’t really have to be. Seb will introduce you to a few basic, the most popular software metrics and tools. He will explain to you what they mean and how you can use them to produce better software.

TRANSCRIPT

Sebastian Marek, Software Architect

Magic behind the numbers

Software metrics in

practice

@proofek

•  a Pole living in Sheffield •  over 10 years PHP

experience •  co-author of 2 PHP books •  big fan of process

automation •  TDD and CI •  occasionally contributes

to open source projects •  wants to be a knight

Agenda

What I will be talking about •  Code metrics •  Design metrics

What I will not be talking about •  Project metrics

https://joind.in/4758

Most effective code quality measure

“It is the mapping of a particular characteristic of a measured entity to

a numerical value”

Source: Object-Oriented Metrics in Practice

What is a metric?

“Good design quality metrics are not necessarily indicative of good designs. Likewise, bad design quality metrics are not necessarily indicative of bad

designs”

Source: Jdepend Docs

Software design

System maintenance

•  Obsolete documentation •  Convoluted design •  Intensive patch mechanism (hacking) •  Large size •  Severe duplication •  Obsolete parts (dead code) •  Long build times •  Loss of original developers

Simple metrics

•  CLOC – comment lines of code •  ELOC – executable lines of code •  LOC – lines of code •  NCLOC – non comment lines of code •  NOP – number of packages •  NOC – number of classes •  NOM – number of methods

Cyclomatic Complexity (CYCLO)

Cyclomatic complexity measures the amount of decision logic in a single software

module.

Cyclomatic Complexity Number (CCN)

Conditional statements: •  ? •  case •  elseif •  for •  foreach •  if •  while

CCN2

Conditional statements: •  ? •  case •  elseif •  for •  foreach •  if •  while

•  && •  || •  or •  and •  xor

Cyclomatic complexity

Conditional statements: •  ? •  case •  elseif •  for •  foreach •  if •  while

•  && •  || •  or •  and •  xor •  catch

Cyclomatic complexity - example

class Foo { public function example() { if ($a == $b) { if ($a1 == $b1) { fiddle(); } elseif ($a2 == $b2) { fiddle(); } else { fiddle(); } } elseif ($e == $f) { for ($n = 0; $n < $h; $n++) { fiddle(); } } else { fiddle(); } } }

Cyclomatic complexity - example

class Foo { public function example() { 1 if ($a == $b) { if ($a1 == $b1) { fiddle(); } elseif ($a2 == $b2) { fiddle(); } else { fiddle(); } } elseif ($e == $f) { for ($n = 0; $n < $h; $n++) { fiddle(); } } else { fiddle(); } } }

Cyclomatic complexity - example

class Foo { public function example() { 1 if ($a == $b) { 2 if ($a1 == $b1) { fiddle(); } elseif ($a2 == $b2) { fiddle(); } else { fiddle(); } } elseif ($e == $f) { for ($n = 0; $n < $h; $n++) { fiddle(); } } else { fiddle(); } } }

Cyclomatic complexity - example

class Foo { public function example() { 1 if ($a == $b) { 2 if ($a1 == $b1) { 3 fiddle(); } elseif ($a2 == $b2) { fiddle(); } else { fiddle(); } } elseif ($e == $f) { for ($n = 0; $n < $h; $n++) { fiddle(); } } else { fiddle(); } } }

Cyclomatic complexity - example

class Foo { public function example() { 1 if ($a == $b) { 2 if ($a1 == $b1) { 3 fiddle(); } elseif ($a2 == $b2) { 4 fiddle(); } else { fiddle(); } } elseif ($e == $f) { for ($n = 0; $n < $h; $n++) { fiddle(); } } else { fiddle(); } } }

Cyclomatic complexity - example

class Foo { public function example() { 1 if ($a == $b) { 2 if ($a1 == $b1) { 3 fiddle(); } elseif ($a2 == $b2) { 4 fiddle(); } else { fiddle(); } } elseif ($e == $f) { 5 for ($n = 0; $n < $h; $n++) { fiddle(); } } else { fiddle(); } } }

Cyclomatic complexity - example

class Foo { public function example() { 1 if ($a == $b) { 2 if ($a1 == $b1) { 3 fiddle(); } elseif ($a2 == $b2) { 4 fiddle(); } else { fiddle(); } } elseif ($e == $f) { 5 for ($n = 0; $n < $h; $n++) { 6 fiddle(); } } else { fiddle(); } } }

Cyclomatic complexity - example

class Foo { public function example() {

6

if ($a == $b) { if ($a1 == $b1) { fiddle(); } elseif ($a2 == $b2) { fiddle(); } else { fiddle(); } } elseif ($e == $f) { for ($n = 0; $n < $h; $n++) { fiddle(); } } else { fiddle(); } } }

phploc phploc 1.6.1 by Sebastian Bergmann.Directories: 6Files: 20Lines of Code (LOC): 5478 Cyclomatic Complexity / Lines of Code: 0.13Comment Lines of Code (CLOC): 2143Non-Comment Lines of Code (NCLOC): 3335Namespaces: 0Interfaces: 1Classes: 18 Abstract: 2 (11.11%) Concrete: 16 (88.89%) Average Class Length (NCLOC): 191Methods: 151 Scope: Non-Static: 143 (94.70%) Static: 8 (5.30%) Visibility: Public: 116 (76.82%) Non-Public: 35 (23.18%) Average Method Length (NCLOC): 22 Cyclomatic Complexity / Number of Methods: 3.72Anonymous Functions: 0Functions: 2Constants: 4 Global constants: 3 Class constants: 1

Cyclomatic complexity - thresholds

Low Avg High V.High Complexity 1-4 5-7 8-10 > 11

JAVA

Metric Low Avg High V.High CYCLO/Line of code 0.16 0.20 0.24 0.36 LOC/Method 7 10 13 19.5 NOM/Class 4 7 10 15

Source: Object-Oriented Metrics in Practice (based on 45 Java projects)

C++

Metric Low Avg High V.High CYCLO/Line of code 0.20 0.25 0.30 0.45 LOC/Method 5 10 16 24 NOM/Class 4 9 15 22.5

Source: Object-Oriented Metrics in Practice (based on 37 C++ projects)

WMC and AMW

Weighted Method Count – total complexity of a class

Average Method Weight – average complexity of a method

JAVA

Metric Low Avg High V.High WMC 5 14 31 47 AMW 1.1 2.0 3.1 4.7 LOC/Class 28 70 130 195

Source: Object-Oriented Metrics in Practice (based on 45 Java projects)

C++

Metric Low Avg High V.High WMC 4 23 72 108 AMW 1.0 2.5 4.8 7.0 LOC/Class 20 90 240 360

Source: Object-Oriented Metrics in Practice (based on 37 C++ projects)

Coverage report

C.R.A.P

C.R.A.P

Change Risk Analysis and Predictions

Change Risk Analysis and Predictions

C.R.A.P formula

Code coverage = 100%

Code coverage = 0%

NPATH – acyclic execution path complexity

NPATH is an objective measure of software complexity related to the ease with which software can be comprehensively tested

Edgar H. Sibley

NPATH – acyclic execution path complexity

expressions Number of && and || operators in expression if NP(<if-range>)+NP(<expr>)+1 if-else NP(<if-range>)+NP(<else-range>)+NP(<expr>) while NP(<while-range>)+NP(<expr>)+1 for NP(<for-range>)+NP(<expr1>)+NP(<expr2>)+ NP(<expr3>)+1 break 1 continue 1 return 1 sequential 1 function call 1

NPATH – example class Foo { public function example() {

if ($a == $b) { if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) { if ($a1 == $b1) { fiddle(); 1 } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) { if ($a1 == $b1) { fiddle(); 1 } else { fiddle(); 2 } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) { if ($a1 == $b1) { 2 fiddle(); 1 } else { fiddle(); 2 } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) { if ($a1 == $b1) {

2 fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) { if ($a1 == $b1) {

2 fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) { 2 if ($a1 == $b1) {

2 fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) { 2 if ($a1 == $b1) {

2 fiddle(); } else { fiddle(); } } 3

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); 1 } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { 1 fiddle(); 1 } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { 1 fiddle(); 1 } 2 } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) {

2 fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) {

2 fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { 3 for ($n = 0; $n < $h; $n++) {

2 fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { 3 for ($n = 0; $n < $h; $n++) {

2 fiddle(); } } 4 return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) {

4 for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

NPATH – example class Foo { public function example() {

if ($a == $b) {

3

if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) {

4 for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; 1 } }

NPATH – example class Foo { public function example() {

12

if ($a == $b) { if ($a1 == $b1) { fiddle(); } else { fiddle(); } }

if ($e == $f && $g == $z) { for ($n = 0; $n < $h; $n++) { fiddle(); } } return true; } }

PHP Depend PHP_Depend 0.10.6 by Manuel PichlerParsing source files:.................... 20Executing CyclomaticComplexity-Analyzer:............. 261Executing ClassLevel-Analyzer:............ 247Executing CodeRank-Analyzer:. 28Executing Coupling-Analyzer:............. 267Executing Hierarchy-Analyzer:............ 246Executing Inheritance-Analyzer:. 30Executing NPathComplexity-Analyzer:.............. 283Executing NodeCount-Analyzer:........ 174Executing NodeLoc-Analyzer:.......... 205Generating pdepend log files, this may take a moment.Time: 00:05; Memory: 25.50Mb

PHP Mess Detector

Overview pyramid

Size and complexity – direct metrics

Size and complexity – computed proportions

System coupling – direct metrics

System coupling – computed proportions

System inheritance

Complete Overview Pyramid

PHP

Metric Low Avg High CYCLO/LOC 0.16 0.20 0.24 LOC/NOM 7 10 13 NOM/NOC 4 7 10 NOC/NOP 6 17 26 CALLS/NOM 2.01 2.62 3.2 FANOUT/CALLS 0.56 0.62 0.68 ANDC 0.25 0.41 0.57 AHH 0.09 0.21 0.32

http://pdepend.org/

Metrics visualisation with Sonar

Metrics visualisation with Sonar

Violations reporting

SIG Maintainability Model

-- - 0 + ++

Very bad Bad Average Good Very good

Technical Debt

Summary

“We believe that software metrics, in general, are just tools. No single metric can tell the whole story; it’s just one more data

point. “

“Metrics are meant to be used by developers, not the other way around – the metric should work for you, you should not have

to work for the metric. “

“Metrics should never be an end unto themselves. Metrics are meant to help you think, not to do the thinking for you.”

Alberto Savoia

Resources

•  PHP Depend - http://pdepend.org/ •  PHP Mess Detector - http://phpmd.org/ •  Manuel’s home page - http://manuel-pichler.de/ •  PHPUnit - http://www.phpunit.de/ •  phploc - http://sebastianbergmann.github.com/phploc/ •  Sonar - http://www.sonarsource.org/ •  “Object-Oriented Metrics in Practice” by Michele Lanza

and Radu Marinescu (ISBN 978-3540244295)

Questions

Questions?

https://joind.in/4758

top related