$30 off During Our Annual Pro Sale. View Details »

Coding Standard

Coding Standard

Každý tým by měl mít kvalitní infrastrukturu, která poskytuje a vyžaduje konzistentní výstup všech jeho členů. Coding standard je jedna z mnoha věcí, která drží projekt pohromadě. Z kusu kódu by nemělo být zřejmé, kdo ho napsal. Tým by měl mít společné konvence jak psát a formátovat kód. V přednášce budu mluvit o nástroji PHP_CodeSniffer, psaní vlastních pravidel (sniffů) a již hotových sniffech, které můžete použít. Možná se i dozvíte pár věcí o tom, jak funguje parsování zdrojového kódu v PHP.

Ondřej Mirtes

June 03, 2016
Tweet

More Decks by Ondřej Mirtes

Other Decks in Programming

Transcript

  1. Coding Standard
    Ondřej Mirtes
    PHP Prague, 3. června 2016

    View Slide

  2. Code review
    Bez code review si neumím představit vývoj. Každý kód, co jde do masteru, by měli vidět alespoň dva lidé.
    Klesne vám míra WTF a kódu bude rozumět víc lidí.

    View Slide

  3. Code review
    • Kód dělá to, co má
    • Nezabije servery
    • Splňuje SOLID
    • Smysluplně rozšiřuje aktuální kód
    • ...
    • Je čitelný
    • Naformátovaný podle dohodnutých pravidel
    Poslední dva body jdou automatizovat, šetří to práci při code review. Pravidla jdou formalizovat. Všechen kód
    by měl vypadat stejně a nemělo by být poznat, kdo ho psal, pracují s ním všichni.

    View Slide

  4. Coding standardem proti bugům
    if ($isFoo && $isBar)

    doSomething();
    Kromě sjednocení podoby kódu lze pomocí coding standardu i zamezit některým bugům. Okolo ifu byste vždy
    měli mít složené závorky {}, i když obsahuje (právě teď) pouze jeden příkaz.

    View Slide

  5. Coding standardem proti bugům
    if ($isFoo && $isBar) {

    doSomething();

    }

    View Slide

  6. Coding standardem proti bugům
    if ($foo == 0) {


    }
    Nepřesná porovnání jsou zdrojem mnoha problémů. Zde např. bude vyhodnocena podmínka na true, pokud
    $foo bude jakýkoli string nezačínající číslicí.

    View Slide

  7. Coding standardem proti bugům
    if ($foo === 0) {


    }
    Kdykoli někde vidím == nebo !=, tak to interpretuji jako "vůbec nevím, co v té proměnné vlastně je".

    View Slide

  8. Přehlednější diffy
    $arr = [

    1,

    2

    ];
    Coding standard kromě snížení chybovosti a zpřehlednění kódu má pozitivní dopad i na verzování. Čárka za
    posledním prvkem víceřádkového pole vede k přehlednějším diffům.

    View Slide

  9. Přehlednější diffy
    $arr = [

    1,

    - 2 

    + 2,

    + 3 

    ];
    Přidal jsem jeden prvek do pole, ale diff této změny je nepřehledný.

    View Slide

  10. Přehlednější diffy
    $arr = [

    1,

    2,

    ];

    View Slide

  11. Přehlednější diffy
    $arr = [

    1,

    2,

    + 3,

    ];
    S čárkou za posledním prvkem už dává smysl.

    View Slide

  12. Continuous Integration
    • Aplikaci lze vůbec spustit – nainstalovat závislosti, zkompilovat DI kontejner…
    • Syntax errory: php -l
    • Coding standard
    • Testy
    • Další kontroly - např. doctrine orm:validate-schema
    • Kompilace a kontrola CSS, JavaScriptu, …

    View Slide

  13. Continuous Integration

    View Slide

  14. PHP_CodeSniffer
    squizlabs/php_codesniffer

    View Slide

  15. ruleset.xml




    ...



    CodeSniffer se bohužel konfiguruje pomocí XML. Do lze uvést buďto cestu k dalším rulesetům (a
    "includovat" tak další standardy) nebo konfigurovat konkrétní sniffy.

    View Slide

  16. ruleset.xml






    Při includnutí dalšího rulesetu lze vynechat některá pravidla, která obsahuje, v případě, že vám nevyhovují.

    View Slide

  17. ruleset.xml


    name="allowFullyQualifiedExceptions"

    value="true"

    />




    Konkrétní sniffy lze konfigurovat, pokud to umožňují. Tato nastavení se propisují do public properties před
    spuštěním daného sniffu.

    View Slide

  18. Kde shánět sniffy?
    • github.com/squizlabs/PHP_CodeSniffer

    nebo:
    • edorian.github.io/php-coding-standard-

    generator/#phpcs
    Sniffy se shání velmi těžko. Samotný repozitář CodeSnifferu jich hromadu obsahuje, musíte se ale orientovat
    podle jejich názvu nebo implementace, nejsou nikde sepsané. Někdy je snazší si ho napsat sám

    View Slide

  19. Z čeho se sniff skládá
    • Public properties – konfigurace
    • register()
    • process(

    \PHP_CodeSniffer_File $phpcsFile,

    $tokenPointer

    )

    View Slide

  20. Tokenizace zdrojáku
    public function doFoo(): Foo

    {

    return $this->doBar();

    }


    T_PUBLIC, T_WHITESPACE, T_FUNCTION, T_WHITESPACE, T_STRING,
    T_OPEN_PARENTHESIS, T_CLOSE_PARENTHESIS, T_COLON, T_WHITESPACE,
    T_RETURN_TYPE, T_WHITESPACE, T_OPEN_CURLY_BRACKET, T_WHITESPACE, T_RETURN,
    T_WHITESPACE, T_VARIABLE, T_OBJECT_OPERATOR, T_STRING, T_OPEN_PARENTHESIS,
    T_CLOSE_PARENTHESIS, T_SEMICOLON, T_WHITESPACE, T_CLOSE_CURLY_BRACKET

    View Slide

  21. Jaké tokeny mě zajímají?
    public function register()

    {

    return [

    T_IF,

    T_ELSEIF,

    T_DO,

    ];

    }

    View Slide

  22. Pro každý token, na který PHPCS narazí,

    se zavolá:
    public function process(

    \PHP_CodeSniffer_File $phpcsFile,

    $tokenPointer

    ) {

    $tokens = $phpcsFile->getTokens();

    $token = $tokens[$tokenPointer];

    }

    View Slide

  23. Pole s tokenem obsahuje:
    "content" => "doBar",

    "code" => 319, // T_STRING

    "type" => "T_STRING",

    "line" => 8,

    "column" => 17,

    "conditions" => [

    2 => 361, // T_CLASS

    12 => 346, // T_FUNCTION

    ],

    View Slide

  24. Metody k dispozici
    $tokenPointer = $phpcsFile->findNext(

    $types,

    $start,

    $end = null,

    $exclude = false,

    $value = null,

    $local = false

    );

    View Slide

  25. Metody k dispozici
    $tokenPointer = $phpcsFile->findPrevious(

    $types,

    $start,

    $end = null,

    $exclude = false,

    $value = null,

    $local = false

    );

    View Slide

  26. Označení chybného zdrojáku
    $phpcsFile->addError(

    $error,

    $tokenPointer,

    $code = '',

    ...

    );
    Pokud sniff reportuje více různých druhů chyb, $code slouží k jejich rozlišení. Můžete pak excludovat
    konkrétní code a nikoli celý sniff.

    View Slide

  27. Jak naimplementovat kontrolu?
    $arr = [

    1,

    2

    ];
    Zaregistruju se na otevírací závorku pole a hledám konečnou. Musím ale počítat se zanořeným polem, takže
    mě zajímá závorka na stejné úrovni (ve stejné hloubce). Jakmile na ní narazím, hledám první newhitespacový
    token, měla by to být čárka. Pokud není, nahlásím chybu.

    View Slide

  28. Jak naimplementovat kontrolu?
    if ($isFoo && $isBar)

    doSomething();
    Zaregistruju se na T_IF, najdu jeho otevírací závorku a pak hledám konečnou. Opět počítám se zanořenými
    podmínkami. Po konečné závorce by měl být první newhitespacový token {. Pokud není, nahlásím chybu.

    View Slide

  29. Jak spustit PHPCS?
    vendor/bin/phpcs

    --standard=ruleset.xml

    --extensions=php

    --tab-width=4

    -s // show sniff codes

    -p // show progress

    app

    tests

    View Slide

  30. Samoopravné sniffy
    ----------------------------------------------------------------------
    FOUND 1 ERROR AFFECTING 1 LINE
    ----------------------------------------------------------------------

    38 | ERROR | [x] Multiline arrays must have a trailing comma after the

    | | last element

    | | (SlevomatCodingStandard.Arrays.TrailingArrayComma)

    ----------------------------------------------------------------------

    PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY

    ----------------------------------------------------------------------
    Pokud je u chybové hlášky [x], znamená to, že umí prohřešek CodeSniffer i opravit.

    View Slide

  31. Samoopravné sniffy
    vendor/bin/phpcbf

    --standard=ruleset.xml

    --extensions=php

    --tab-width=4

    -s // show sniff codes

    -p // show progress

    app

    tests

    View Slide

  32. Slevomat Coding Standard
    • Nepoužité privátní properties a metody
    • Seřazené uses
    • Nepoužité uses
    • Zakázané yoda podmínky
    • Sniffy ohledně namespaces
    • Chystané PHP 7-specific sniffy (2.0)
    github.com/slevomat/coding-standard

    View Slide

  33. @OndrejMirtes

    View Slide