php benelux 2012: magic behind the numbers. software metrics in practice
Post on 14-Dec-2014
1.892 Views
Preview:
DESCRIPTION
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