The document discusses code metrics that can be used to evaluate code quality in PHP projects. It introduces various metrics like lines of code, test coverage, cyclomatic complexity, coupling metrics, lack of cohesion in methods, Halstead complexity measures, and maintainability index. It recommends always using tools like PHP Code Sniffer and PHPUnit for testing and recommends adopting tools like PHPSpec, Behat, PHP Copy/Paste Detector and PHPMetrics. It also suggests giving tools like Humbug for mutant testing a try and considering SaaS options with customization efforts.
2. ● Julio Martinez
● Developing PHP since 2001
● 1.5 years working at Ulabox
● Find me: @liopic
Code metrics in PHP: 0. Introduction
Who am I?
3. ● El antisúper!
● 6-years-old startup
● 11 developers
● monolith & new services
● #rigor
● We are hiring!
Code metrics in PHP: 0. Introduction
What is Ulabox?
4. ● Evaluate quality!
● We need objective, reproducible and quantifiable metrics
Could you tell me some examples of metrics?
Code metrics in PHP: 1. Looking for quality
Why do we need software metrics?
5. ● number of bugfixes per month
● lines of code
● test coverage
● number of user stories covered
● follows clean code’s rules
● documentation lines / total of code lines
● etc
Code metrics in PHP: 1. Looking for quality
Some examples?
10. 1. Cyclomatic complexity (paths of execution)
2. Coupling metrics (relations between “modules”)
3. Lack of cohesion, LCOM (relations between methods)
4. Halstead’s metrics (operands and operators)
5. Maintainability Index
Code metrics in PHP: 5. Code semantic
Code semantic analysis
11. Code metrics in PHP: 5. Code semantic
Cyclomatic complexity
abstract class BaseBird
{
private $eggs = 0;
public function makeEgg()
{
$this->eggs++;
}
public function crackEgg()
{
if ($this->eggs <=0) {
throw new NoEggsException();
}
$this->eggs--;
}
public function fly()
{
return 'flap-flap';
}
abstract public function sound();
}
class Duck extends BaseBird
{
public function sound()
{
return 'quack';
}
public function swim()
{
return 'splash';
}
}
class Parrot extends BaseBird
{
public function sound()
{
$friend = new Duck();
if($friend->sound()){
return 'Err '.$friend->sound();
}
return '';
}
}
12. Code metrics in PHP: 5. Code semantic
Cyclomatic complexity
abstract class BaseBird
{
private $eggs = 0;
public function makeEgg()
{
$this->eggs++;
}
public function crackEgg()
{
if ($this->eggs <=0) {
throw new NoEggsException();
}
$this->eggs--;
}
public function fly()
{
return 'flap-flap';
}
abstract public function sound();
}
class Duck extends BaseBird
{
public function sound()
{
return 'quack';
}
public function swim()
{
return 'splash';
}
}
class Parrot extends BaseBird
{
public function sound()
{
$friend = new Duck();
if($friend->sound()){
return 'Err '.$friend->sound();
}
return '';
}
}
2
2
1
13. ● Afferent couplings (Ca) - “they use you”
● Efferent couplings (Ce) - “you use them”
● Instability, resilience to change (I): I = Ce / (Ce + Ca)
○ I=0 is a completely stable package
○ I=1 is a completely unstable package
Code metrics in PHP: 5. Code semantic
Coupling metrics
14. ● Abstractness (A): ratio of abstract classes
○ A=0 is a completely concrete package
○ A=1 is a completely abstract package
● Examples:
○ BaseBird: Ce=1 (uses NoEggsException), Ca=0; A=1, I=1
○ Parrot, Ce=1 (uses Duck), Ca=0; A=0, I=1
○ Duck, Ce=0, Ca=0; A=0, I=0
Code metrics in PHP: 5. Code semantic
Coupling metrics
15. ● Distance from the main sequence (D): D = |A+I-1|
○ Balance between abstractness and stability
○ Ideal packages: (I=1, A=0), (I=0, A=1)
Code metrics in PHP: 5. Code semantic
Coupling metrics: main sequence
16. ● Groups of methods
● LCOM = 1 is ideal
Code metrics in PHP: 5. Code semantic
Lack of cohesion of methods (LCOM)
abstract class BaseBird
{
private $eggs = 0;
public function makeEgg()
{
$this->eggs++;
}
public function crackEgg()
{
if ($this->eggs <=0) {
throw new NoEggsException();
}
$this->eggs--;
}
public function fly()
{
return 'flap-flap';
}
abstract public function sound();
}
17. ● Groups of methods
● LCOM = 1 is ideal
● BaseBird LCOM = 3
Code metrics in PHP: 5. Code semantic
Lack of cohesion of methods (LCOM)
abstract class BaseBird
{
private $eggs = 0;
public function makeEgg()
{
$this->eggs++;
}
public function crackEgg()
{
if ($this->eggs <=0) {
throw new NoEggsException();
}
$this->eggs--;
}
public function fly()
{
return 'flap-flap';
}
abstract public function sound();
}
18. ● η1
= number of distinct operators
● η2
= number of distinct operands
● N1
= the total number of operators
● N2
= the total number of operands
● Program vocabulary: η = η1
+ η2
● Program length: N = N1
+ N2
Code metrics in PHP: 5. Code semantic
Halstead complexity measures (1977)
19. ● Volume: V = N × log2
η (linearly with length, log with vocabulary)
● Difficulty : D = η1
/2 × N2
/η2
(half distinct operators, scarcity of operands)
● Effort: E = D × V
● Time required to program: T = E/18 seconds
● Delivered bugs:
Code metrics in PHP: 5. Code semantic
Halstead complexity measures
20. ● University of Idaho, Oman and Hagemeister
● Volume (V), Cyclomatic Complexity (G), Lines of Code (LOC)
● Original MI = 171 - 5.2*ln(V) - 0.23*G - 16.2*ln(LOC)
Code metrics in PHP: 5. Code semantic
Maintainability Index (1991)
21. ● phpmetrics
○ Let’s see all those indexes!
Code metrics in PHP: 5. Code semantic
Coupling + LCOM + Halstead + MI
Maintainability.................... 65.83 / 100
Accessibility for new developers... 41.03 / 100
Simplicity of algorithms........... 42.57 / 100
Volume............................. 64.90 / 100
Reducing bug's probability......... 65.57 / 100
22.
23.
24.
25. ● MUST!
○ phpcs - code sniffer - No extra effort need; always
○ phpunit - integration & unit tests - Write tests; always
● Adopt
○ phpspec - unit/specs - Write tests; always
○ behat - user stories (functional tests) - Write user stories; always
○ phpcpd - copy & paste - No effort; always
○ phpmetrics - No effort; main indexes weekly, others when refactor
● Give a try
○ humbug - test your tests - No effort; often
○ SaaS options - Customization effort; always
Code metrics in PHP: 6. Summing up!
RADAR of tools (how? when?)