Upload
sebastian-marek
View
1.891
Download
1
Embed Size (px)
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.
Citation preview
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