PHPMD and PHPCS Integration

About

Dokumen ini bertujuan untuk memberikan informasi integrasi phpmd dan phpcs ke dalam sublime text 3. Sehingga kita tidak perlu bulak balik ke terminal untuk menjalankan phpcs / phpmd. Integrasi dilakukan dengan cara linting, sehingga kita bisa dengan mudah mengetahui jika terdeteksi pelanggaran standard coding.

Instalasi

  • Install package ‘phpcs’ melalui package control, jika package control belum terinstall, cek dokumen tentang sublime text 3 for PHP development.
    Screen Shot 2015-11-17 at 1.25.33 PM.png
  • Setelah phpcs terinstall, cari preferences > package settings > PHP Code sniffer > settings – user.
    Screen Shot 2015-11-17 at 1.25.56 PM.png
  • Didalam file config, anda perlu menuliskan executeable php, phpmd dan phpcs, berikut dengan rule yang ingin diterapkan. Contohnya sebagai berikut
{
    "phpcs_executable_path": "/Users/libreorca/.composer/vendor/bin/phpcs",
    "phpcs_show_quick_panel": false,
    "phpcs_php_path": "/usr/local/Cellar/php53/5.3.29_4/bin/php",
    "phpmd_run": true,
    "phpmd_executable_path": "/Users/libreorca/.composer/vendor/bin/phpmd",
    "phpmd_additional_args": {
        "codesize,design,unusedcode,naming": ""
    },
}
  • Pada contoh diatas, rule yang digunakan untuk PHPMD adalah codesize,design,unusedcode,naming, untuk PHPCS mengikuti default (PSR2).
  • Setelah menulis file setting, save kemudian restart sublime text.

Contoh

  • Misalkan kita memiliki file test.php
<?php

class Test
{
    public function test_a($a,$b)
    {
        $c = 3 + $a;

        if($c>15)
        {
            $c++;
        }

        $this::test_b();

        echo $c;
    }

    private static function test_b($flag = false)
    {
        if ($flag) {
            echo 'a';
        } else {
            echo 'b';
            exit();
        }

        return;
    }
}

$objA = new Test();
$objA->test_a(1,5);
  • Sublime akan secara automatis melakukan pengecekan setiap kali kita me-save file yang di edit.
  • Jika integrasi phpmd dan phpcs sudah terinstall dengan benar, sublime akan melakukan linting pada baris baris kode yang melanggar aturan / standard kode yang ditentukan. Cek status bar untuk mengetahui pelanggaran apa yang ada di baris kode tersebut.
    Screen-Shot-2015-11-17-at-1.35.02-PM.jpg
  • Hasil perbaikan test.php
<?php
namespace Sublime\test;

class Test
{
    public function testA($varA)
    {
        $varC = 3 + $varA;

        if ($varC>15) {
            $varC++;
        }

        $this::testB();

        echo $varC;
    }

    private static function testB($flag = false)
    {
        if ($flag) {
            echo 'a';
        } else {
            echo 'b';
        }

        return;
    }
}

$objA = new Test();
$objA->testA(1, 5);

Screen Shot 2015-11-17 at 1.39.57 PM.png

Conclusion

Dengan integrasi ini kita dengan mudah bisa mendeteksi jika ada yang tidak sesuai dengan standard code. Tidak hanya membuat coding kita lebih mudah dibaca, tapi kita juga belajar untuk membuat code yang lebih terstruktur. Better programmer = better & cleaner code.

Credit to: Yusuf Irwandi

PHPMD – The mess detector

PHPMD

http://phpmd.org/

This is the project site of PHPMD. It is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD. PHPMD can be seen as an user friendly and easy to configure frontend for the raw metrics measured by PHP Depend.

What PHPMD does is: It takes a given PHP source code base and look for several potential problems within that source. These problems can be things like:

  • Possible bugs
  • Suboptimal code
  • Overcomplicated expressions
  • Unused parameters, methods, properties

Installation

Direkomendasikan install melalui composer karena sangat mudah, dan mudah untuk updatenya.
Add Requirement phpmd/phpmd:”@stable” to your composer project (or global whichever is appropiate).

composer require phpmd/phpmd:"@stable"

Usage

php vendor/bin/phpmd [php files] [report type] [rules]

PHP files file yang ingin dicek atau folder
Report type bisa menggunakan text atau xml
Rule cek bagian rule untuk lebih detail
Contohnya
php vendor/bin/phpmd test.php text cleancode,unusedcode,naming,design

Rules

cleancode

  • Tidak boleh ada boolean flag sebagai argument – karena melanggar prinsip SOLID
  • Else expression, else expression hampir selalu dihilangkan dengan melakukan refactor code.
  • Static access
  • Personally saya merasa rules ini sangat strict dan sedikit menyebalkan karena terlalu mengikat, terserah pembaca jika ingin phpmd mengecek rule ini, tambahkan cleancode ke list rules.

codesize

  • cyclomatic complexity harus rendah, cyclomatic complexity disebabkan oleh terlalu banyak control statement di dalam sebuah function, if else, while, foreach, do while. Pisahkan kode menjadi method terpisah apabila complexity mencapai lebih dari 10.
  • NPath complexity harus rendah, npath adalah jumlah kemungkinan path di dalam sebuah function. Pisahkan kode menjadi method / class terpisah jika NPath complexity mencapat lebih dari 200.
  • ExcessiveMethodLength, jangan gunakan nama method yang terlalu panjang (mengindikasikan terlalu banyak tanggung jawab).
  • ExcessiveClassLength, jangan gunakan nama class yang terlalu panjang (mengindikasikan terlalu banyak tanggung jawab).
  • ExcessiveParameterList, jangan define suatu method dengan parameter list yang panjang, sederhanakan menjadi lebih compact.
  • ExcessivePublicCount, kurangi kompleksitas sebuah class dengan melakukan refactor pada public method, terlalu banyak public method mengindikasikan terlalu banyak tanggung jawab dan sulit untuk di test.
  • TooManyFields, properties di class bisa disederhakan menjadi lebih compact, misalnya memisahkan menjadi class terpisah, atau melakukan grouping untuk field field yg mirip.
  • TooManyMethods, class yang memiliki terlalu banyak adalah kandidat bagus untuk di refactor untuk tujuan mengurangi kompleksitas.
  • ExcessiveClassComplexity. WMC(Weighted Method Count) dari sebuah class adalah indikator bagus berapa banyak effort dan waktu yang digunakan untuk mengedit dan memaintain class tersebut. Hitungan WMC didefine sebagai jumlah kompleksitas dari semua method yang dideklarasikan di dalam sebuah class.

controversial

  • Superglobal, mengakses superglobal dianggap sebagai bad practice. Variabel ini harus di enkapsulasi di dalam objek yang diberikan oleh framework contohnya.
  • CamelCase untuk class, property, method, parameter dan variable name dianggap sebagai best practice.

design

  • ExitExpression, statement exit di dalam code tidak bisa ditest oleh sebab itu harus dihindari.
  • EvalExpression, statement eval tidak bisa ditest, security risk dan bad practice oleh sebab itu harus dihindari.
  • GotoStatement, statement goto membuat kode lebih sulit dibaca dan sulit dimengerti, oleh sebab itu harus dihindari.
  • NumberofChildren, class dengan jumlah children yang terlalu banyak adalah indikator ketidak seimbangan dalam hierarki class.
  • DepthOfInheritance, class yang memiliki banyak parent  adalah indikator ketidakseimbangan dalam hierarki class.
  • CouplingBetweenObjects. class yang memiliki dependency terlalu banyak memiliki impact buruk dalam beberapa aspek kualitas dari sebuah class.

naming

  • ShortVariable, hindari nama variabel yang terlalu pendek.
  • LongVariable, hindari nama variabel yang terlalu panjang.
  • ShortMethodName, hindari nama method yang terlalu pendek.
  • ConstructorWithNameAsEnclosingClass, constructor sebaikinya menggunakan constructor method.
  • ConstantNamingConventions, konstanta seharusnya selalu uppercase.
  • BooleanGetMethodName, jika sebuah method mengembalikan boolean, refactor method ini menjadi isX atau hasX bukan getX.

unusedcode

  • UnusedPrivateField, jika ada private property tapi tidak digunakan.
  • UnusedLocalVariable, jika ada variable yang dideklarasikan tapi tidak digunakan.
  • UnusedPrivateMethod, jika ada private method tapi tidak digunakan di dalam class.
  • UnusedFormalParameter, hindari passing parameter ke method atau constructor tetapi tidak menggunakannya.

Remark

  • Rules rules tersebut sangat membantu dalam development sehari hari tapi bisa juga menyebalkan.
  • Tapi ingat warning dari phpmd bukan berarti error codenya, direkomendasikan untuk dibetulkan tapi bisa saja diabaikan.
  • Rules yang saya gunakan: codesize,design,naming,unusedcode

Contoh

// file test.php
<?php

class Test
{
    public function test_a($a,$b)
    {
        $c = 3 + $a;

        if($c>15)
        {
            $c++;
        }

        $this::test_b();

        echo $c;
    }

    private static function test_b($flag = false)
    {
        if ($flag) {
            echo 'a';
        } else {
            echo 'b';
            exit();
        }

        return;
    }
}

$objA = new Test();
$objA->test_a(1,5);

Kemudian kita run phpmd menggunakan command berikut

php vendor/bin/phpmd test.php text unusedcode,design,naming,codesize 

/Users/libreorca/Htdocs/test/phpmd/test.php:5	Avoid unused parameters such as '$b'.
/Users/libreorca/Htdocs/test/phpmd/test.php:5	Avoid variables with short names like $a. Configured minimum length is 3.
/Users/libreorca/Htdocs/test/phpmd/test.php:5	Avoid variables with short names like $b. Configured minimum length is 3.
/Users/libreorca/Htdocs/test/phpmd/test.php:7	Avoid variables with short names like $c. Configured minimum length is 3.
/Users/libreorca/Htdocs/test/phpmd/test.php:25	The method test_b() contains an exit expression.

Line 5: ada warning tentang variabel b dideklarasikan tapi tidak digunakan, kemudian ada warning juga kalau nama variabel terlalu pendek dan warning
Line 25: method test_b mengandung statement exit. Maka kita lakukan refactor

// file test.php
<?php

class Test
{
    public function test_a($varA,$varB)
    {
        $varC = 3 + $varA + $varB;

        if($varA>15)
        {
            $varC++;
        }

        $this::test_b();

        echo $varC;
    }

    private static function test_b($flag = false)
    {
        if ($flag) {
            echo 'a';
        } else {
            echo 'b';
        }

        return;
    }
}

$objA = new Test();
$objA->test_a(1,5);

Kemudian kita run ulang phpmd sebagai berikut

php vendor/bin/phpmd test.php text unusedcode,design,naming,codesize

*empty result*

Jika phpmd tidak mengeluarkan output apa apa artinya kode kita memenuhi rules yang didefinisikan (unusuedcode,design,naming,codesize), now your code is much better than the previous one, YAY!!

Lakukan pengecekan phpmd berulang selama development untuk menjaga kualitas kode.

PHPCS – PHP Code Sniffer

https://github.com/squizlabs/PHP_CodeSniffer/wiki

About

PHP Codesniffer adalah set dari dua script PHP: phpcs adalah script yang mendeteksi file PHP, javascript dan CSS dari pelanggaran standard coding yang ditentukan, kemudian yang kedua phpcbf adalah script untuk melakukan perbaikan secara automatis dari standard coding yang ditentukan. PHP Codesniffer adalah tool development esensial yang menjamin kode tetap bersih dan konsisten.

Requirement

PHP Codesniffer membutuhkan PHP versi 5.1.2 atau lebih baru, beberapa aturan sniff mungkin membutuhkan requirement lain.

Installation

Recommended: composer

composer global require "squizlabs/php_codesniffer=*"

pastikan /.composer/vendor/bin ada di PATH

Usage

Untuk mengecek apakah file melanggar standard coding PEAR, execute command berikut di shell.

$ phpcs /path/to/code/myfile.php

FILE: /path/to/code/myfile.php
--------------------------------------------------------------------------------
FOUND 5 ERROR(S) AFFECTING 2 LINE(S)
--------------------------------------------------------------------------------
  2 | ERROR | Missing file doc comment
 20 | ERROR | PHP keywords must be lowercase; expected "false" but found "FALSE"
 47 | ERROR | Line not indented correctly; expected 4 spaces but found 1
 51 | ERROR | Missing function doc comment
 88 | ERROR | Line not indented correctly; expected 9 spaces but found 6
--------------------------------------------------------------------------------

 

Atau jika ingin mengecek semua file PHP di dalam direktori, bisa dispesifikasikan direktori saja

$ phpcs /path/to/code
FILE: /path/to/code/myfile.php
--------------------------------------------------------------------------------
FOUND 5 ERROR(S) AFFECTING 5 LINE(S)
--------------------------------------------------------------------------------
  2 | ERROR | Missing file doc comment
 20 | ERROR | PHP keywords must be lowercase; expected "false" but found "FALSE"
 47 | ERROR | Line not indented correctly; expected 4 spaces but found 1
 51 | ERROR | Missing function doc comment
 88 | ERROR | Line not indented correctly; expected 9 spaces but found 6
--------------------------------------------------------------------------------

FILE: /path/to/code/yourfile.php
--------------------------------------------------------------------------------
FOUND 1 ERROR(S) AND 1 WARNING(S) AFFECTING 1 LINE(S)
--------------------------------------------------------------------------------
 21 | ERROR   | PHP keywords must be lowercase; expected "false" but found
    |         | "FALSE"
 21 | WARNING | Equals sign not aligned with surrounding assignments
--------------------------------------------------------------------------------

Rekomendasi

  • Gunakan PSR 2 sebagai standard untuk pengecekan code standard violation.
  • Gunakan integrasi dengan IDE atau text editor untuk mempermudah development.

Contoh

Misalkan ada file PHP sebagai berikut

<?php

class Test_My_class
{
    public function index_test()
    {
        $varA = TRUE;

        if($varA) {
            echo 'T';
        }
    }

    private function test_argument($test1,$test2)
    {
        $array = array(1,2);

        if($test1)
        {
            foreach($array as $value){
                echo $value;
            }
        }
    }
}

 

Jika kita jalankan pengecekan phpcs terhadap file tersebut

phpcs --standard=PSR2 test.php 

FILE: /Users/libreorca/Htdocs/test/phpcs/test.php
----------------------------------------------------------------------
FOUND 11 ERRORS AFFECTING 7 LINES
----------------------------------------------------------------------
  3 | ERROR | [ ] Each class must be in a namespace of at least one
    |       |     level (a top-level vendor name)
  3 | ERROR | [ ] Class name "Test_My_class" is not in camel caps
    |       |     format
  5 | ERROR | [ ] Method name "Test_My_class::index_test" is not in
    |       |     camel caps format
  7 | ERROR | [x] TRUE, FALSE and NULL must be lowercase; expected
    |       |     "true" but found "TRUE"
  9 | ERROR | [x] Expected 1 space after IF keyword; 0 found
 14 | ERROR | [ ] Method name "Test_My_class::test_argument" is not
    |       |     in camel caps format
 14 | ERROR | [x] Expected 1 space between comma and argument
    |       |     "$test2"; 0 found
 18 | ERROR | [x] Expected 1 space after IF keyword; 0 found
 18 | ERROR | [x] Expected 1 space after closing parenthesis; found 9
 20 | ERROR | [x] Expected 1 space after FOREACH keyword; 0 found
 20 | ERROR | [x] Expected 1 space after closing parenthesis; found 0
----------------------------------------------------------------------
PHPCBF CAN FIX THE 7 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Time: 19ms; Memory: 3.5Mb

 

Sesuai dengan standard PSR2, kode diatas banyak melanggar standard coding. Ada beberapa pelanggaran yang bisa difix dengan phpcbf secara automatis. Hasilnya bisa dicek dibawah

phpcbf --standard=PSR2 test.php 
Changing into directory /Users/libreorca/Htdocs/test/phpcs
Processing test.php [PHP => 116 tokens in 25 lines]... DONE in 4ms (7 fixable violations)
        => Fixing file: 0/7 violations remaining [made 6 passes]... DONE in 20ms
Patched 1 file
Time: 59ms; Memory: 3.75Mb

phpcs --standard=PSR2 test.php 

FILE: /Users/libreorca/Htdocs/test/phpcs/test.php
----------------------------------------------------------------------
FOUND 4 ERRORS AFFECTING 3 LINES
----------------------------------------------------------------------
  3 | ERROR | Each class must be in a namespace of at least one level
    |       | (a top-level vendor name)
  3 | ERROR | Class name "Test_My_class" is not in camel caps format
  5 | ERROR | Method name "Test_My_class::index_test" is not in camel
    |       | caps format
 14 | ERROR | Method name "Test_My_class::test_argument" is not in
    |       | camel caps format
----------------------------------------------------------------------

Time: 25ms; Memory: 3.5Mb

 

Hasil file setelah difix phpcbf secara automatis

<?php

class Test_My_class
{
    public function index_test()
    {
        $varA = true;

        if ($varA) {
            echo 'T';
        }
    }

    private function test_argument($test1, $test2)
    {
        $array = array(1,2);

        if ($test1) {
            foreach ($array as $value) {
                echo $value;
            }
        }
    }
}

 

Beberapa pelanggaran sudah di fix automatis oleh phpcbf, tapi file tersebut masih ada pelanggaran terhadap standard PSR2, kita perlu melakukan refactor manual.

<?php
namespace Phpcs\Test;

class TestMyClass
{
    public function indexTest()
    {
        $varA = true;

        if ($varA) {
            echo 'T';
        }
    }

    private function testArgument($test1, $test2)
    {
        $array = array(1,2);

        if ($test1) {
            foreach ($array as $value) {
                echo $value;
            }
        }
    }
}

 

Jika kita re-run phpcs dan hasilnya kosong, maka file PHP sudah mengikuti standard yang ditentukan (dalam kasus ini PSR2).

phpcs --standard=PSR2 test.php
*empty string*

Remark

  • Perhatikan kode hasil refactor phpcs tidak mendeteksi unusued code (function testArgument, dan argumen test2), oleh sebab itu phpcs digunakan berdampingan dengan phpmd untuk hasil yang optimum.
  • Lakukan phpcs secara berkala untuk menjaga kualitas koding – atau integrasikan dengan IDE / text editor masing masing.

Credit to: Yusuf Irwandi