Measuring maintainability; software metrics explained

3,612 views 41 slides Aug 12, 2015
Slide 1
Slide 1 of 44
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44

About This Presentation

In a world of ever-changing business requirements, how can you keep your software moving at the same pace?
If you keep adding lines of code around the previous iteration to add new functionality, things can become complex quite fast.
By measuring complexity, you can resolve and prevent bugs, while m...


Slide Content

Measuring Maintainability
Dennis de Greef

Dennis de Greef
Software Developer at TransIP
Meetup addict
Tech enthousiast
Occasional speaker Bass player
Domotica Software architect Hardware hacker
Infrastructure engineer

Talk roadmap
- About static software analysis
- Measuring lines of code
- Measuring complexity
- Measuring coupling

About software statistics

Measuring Lines of Code

How many lines of code?
1 <?php
2
3 /* this is a for-loop */
4 for ($i = 0; $i < 100; $i++)
5 {
6 printf("hello");
7 }

How many lines of code?
1 <?php
2
3 /**
4 * This is a for-loop
5 */
6 for ($i = 0; $i < 100; $i++) printf("hello");

Depends on your definition

LOC: Physical lines of code
LLOC: Logical lines of code
CLOC: Comment lines of code
NCLOC: Non-comment lines of code
Different types:

How many lines of code?
7 physical lines of code
3 logical lines of code
1 comment lines of code
6 non-comment lines of code
1 <?php
2
3 /* this is a for-loop */
4 for ($i = 0; $i < 100; $i++)
5 {
6 printf("hello");
7 }

How many lines of code?
6 physical lines of code
3 logical lines of code
3 comment lines of code
3 non-comment lines of code
1 <?php
2
3 /**
4 * This is a for-loop
5 */
6 for ($i = 0; $i < 100; $i++) printf("hello");

Some statisticsLOC

Physical
CLOC

Comment
NCLOC

Non-Comment
LLOC

Logical
symfony-standard 371490
102161

(27.50%)
269329

(72.50%)
84262

(22.68%)
zend-framework2 306097
112498

(36.75%)
193599

(63.25%)
56053

(18.31%)
laravel-framework 78191
35156
(44.96%)
43035

(55.04%)
11970
(15.31%)
cakephp 93455
42454
(45.43%)
51001
(54.57%)
17235
(18.44%)
phploc 2.1.2-17-gb6bfd40
PSR-2
PSR-2
PSR-2
PSR-2

WARNING!
Don’t use these statistics as a form
of measuring quality or productivity!
People will just ‘game’ the system
*applies different codestyle*

Use it to gain more insight
about the application
“Measuring programming progress by lines of code
is like measuring aircraft building progress by weight.”
--Bill Gates

composer require phploc/phploc
$ phploc loc1.php
phploc 2.0.2 by Sebastian Bergmann.
!
Size
Lines of Code (LOC) 7
Comment Lines of Code (CLOC) 1 (14.29%)
Non-Comment Lines of Code (NCLOC) 6 (85.71%)
Logical Lines of Code (LLOC) 3 (42.86%)
Classes 0 (0.00%)
Average Class Length 0
Average Method Length 0
Functions 0 (0.00%)
Average Function Length 0
Not in classes or functions 3 (100.00%)

Measuring Complexity
•Cyclomatic Complexity
•N-path Complexity
Complexity and quality are strongly related

Cyclomatic Complexity
“It is a quantitative measure of the number of
linearly independent paths through a program's source code.”
M = E − N + 2P
E = the number of edges of the graph.
N = the number of nodes of the graph.
P = the number of connected components.
http://www.literateprogramming.com/mccabe.pdf

Simply put:
Counting of decision trees:
-function
-for(each)
-while
-if
-case

Cyclomatic Complexity
1 <?php
2
3 function foo($a, $b) {
4 if($a) {
5 if($b) {
6 echo "Hello World";
7 }
8 }
9 }
10
5 edges
4 nodes
1 compound
M = 5 − 4 + 2x1 = 3
M = E − N + 2P

Cyclomatic Complexity
8 edges
7 nodes
1 compound
M = 8 − 7 + 2x1 = 3
M = E − N + 2P
1 <?php
2
3 function foo() {
4 if($a) {
5 echo '1';
6 } else {
7 echo '2';
8 }
9 if($b) {
10 echo '3';
11 } else {
12 echo '4';
13 }
14 }

Cyclomatic Complexity
How many tests do we need?
M = 8 − 7 + 2x1 = 3
Complete branch coverage:
foo(true, false)
foo(false, true)

Code Coverage
1 <?php
2
3 function foo($a, $b) {
4 if($a) {
5 // ...
6 }
7
8 if($b) {
9 // ...
10 }
11 }
12
13 foo(true, false);
14 foo(false, true);
All paths are tested with these two
function calls.
This implies 100% code coverage.
!
Or does it? What about:
foo(false, false)
foo(true, true) ?

Code Coverage
Path coverage:
http://derickrethans.nl/path-branch-coverage.html
Xdebug 2.3.0
PHP_CodeCoverage: not supported

N-path Complexity
“The NPath complexity of a method is the number of
acyclic execution paths through that method.”

“The NPath complexity of a method is the number of
acyclic execution paths through that method.”
N-path Complexity

“The NPath complexity of a method is the number of
acyclic execution paths through that method.”
N-path Complexity

N-path Complexity
Path coverage
M = E − N + 2P
E = the number of edges of the graph.
N = the number of nodes of the graph.
P = the number of connected components.

N-path Complexity
foo(false, false)
foo(true, false)
foo(false, true)
foo(true, true)
Cyclomatic Complexity = 3
N-path Complexity = 4
N-path is exponential

N-path Complexity
foo(false, false)
foo(true, false)
foo(false, true)
foo(true, true)
Cyclomatic Complexity = 3
N-path Complexity = 4
N-path is exponential
Number of unique paths

N-path Complexity
// …
$count['staticMethods'],
$count['methods'] > 0 ? ($count['staticMethods'] / $count['methods']) * 100 : 0,
$count['publicMethods'],
$count['methods'] > 0 ? ($count['publicMethods'] / $count['methods']) * 100 : 0,
$count['nonPublicMethods'],
$count['methods'] > 0 ? ($count['nonPublicMethods'] / $count['methods']) * 100 : 0,
$count['functions'],
$count['namedFunctions'],
$count['functions'] > 0 ? ($count['namedFunctions'] / $count['functions']) * 100 : 0,
// …

N-path Complexity
The method printResult() has an NPath complexity
of 47683715820312500.
The configured NPath complexity threshold is 200.

Measuring Coupling
http://www.codemanship.co.uk/parlezuml/metrics/OO%20Design%20Principles%20&
%20Metrics.pdf
Martin’s Metrics

Measuring Coupling
Coupling between packages
Packages being either a namespace or composer package

Measuring Coupling
Afferent Coupling (Ca):"
Amount of other packages depending on this class (incoming)
!
Efferent Coupling (Ce):"
Amount of dependencies of this class
!
Instability (I):"
Resilience to change, metric between 0 and 1. Where 0 is stable.
I = Ce / (Ce + Ca)

Measuring Coupling
Ca = 2
Ce = 3
I = Ce / (Ce + Ca)
I = 3 / (3+2)
I = 0,6
I = 0,0 = Completely stable
I = 1,0 = Completely unstable

Measuring Coupling
Abstract:"
Either an abstract class or interface
!
Concrete:"
Any class that is neither abstract or final
!
Abstractness (A):"
How abstract a package is, ratio between 0 and 1. Where 0 is concrete.
A = Abstract / (Abstract + Concrete)

Measuring Coupling
PHPMD (PHP Mess Detector)
Can detect (code size rules):
-Cyclomatic complexity
-N-path complexity
-Excessive method length
-Too many methods
-etcetera
10
200
100
10
And other things
-Clean Code
-Design Rules
-Naming Rules
-Unused Code Rules

Integrating it all
http://jenkins-php.org/

Questions?

Thank you
Big thanks to:
!
Derick Rethans (Xdebug)
Sebastian Bergmann"
(PHPLOC, PHPunit,
PHP_CodeCoverage)
Thomas J. McCabe Sr:
Cyclomatic Complexity
Robert C. Martin: Lots of things!

(nicknamed ‘Uncle Bob’)
!
Many more…
Twitter: @dennisdegreef
Blog: dennisdegreef.net
IRC (Freenode): link0
Github: dennisdegreef / link0
PHPNL-Slack: link0
Joind.in: https://joind.in/14991