Narzędzia użytkownika

Narzędzia witryny


ewdphpstyle

Standardy programowania w PHP

Formatowanie kodu

  • Bloki kodu wcinamy tabulacją.
  • Nie mamy nic przeciwko wyrównywaniu spacjami/tabulacjami, jeśli poprawia to czytelność kodu, np.
    $zmienna1          = 'a';
    $zmiennaDlugaNazwa = 'b';
  • Stawiamy spacje wokół operatorów
    // ŹLE
    $a=1;
    if($a==1){...}
    
    // DOBRZE
    $a = 1;
    if($a == 1){...}
  • Nawiasy blokowe stawiamy, jak lubimy, byle konsekwentnie
    // DOBRZE
    if($a == 1){
      ...
    }
    
    // TEŻ DOBRZE
    if($a == 1)
    {
      ...
    }
  • Unikamy nadmiernie długich linii. Łamiąc je robimy to tak, aby zachować czytelność kodu
    // ŹLE
    if($zmienna1 == 'wartość1' && ($zmienna2 == 'wartość2' || $zmienna3 == 'wartość3') && in_array($zmienna4, array(1, 2, 3))){
      ...
    }
    
    // DOBRZE
    if(    $zmienna1 == 'wartość1'
        && ($zmienna2 == 'wartość2' || $zmienna3 == 'wartość3')
        && in_array($zmienna4, array(1, 2, 3))
    ){
      ...
    }
  • Formatujemy bloki kodu tak, by poprawnie liczyło się pokrycie testami (patrz rozdział o testach)

Konwencje nazw

  • Klasy, właściwości, metody, zmienne nazywamy po polsku
    • Wiem, że to kontrowersyjne, ale po pierwsze w tej konwencji pisany był cały dotychczasowy kod, po drugie baza danych też operuje polskim nazewnictwem, a po trzecie miejscami obijać będziemy się o terminy, dla których wymyślanie angielskich tłumaczeń będzie jak sięganie prawą ręką do lewej kieszeni.
  • Nazwy klas, metod i właściwości tworzymy w konwencji camelCase, przy czym:
    • nazwy klas zaczynają się wielką literą;
    • nazwy metod, właściwości zaczynają się małą literą.

Zmienne globalne

  • Nie tworzymy samemu zmiennych globalnych
    • tzn. zmienne w kontekście globalnym możemy tworzyć, ale nigdy nie używamy słowa kluczowego global
      // ŹLE
      $a = 1;
      function mojaFunkcja($b){
        global $a;
        ...dalszy kod...
      }
      
      // DOBRZE
      function mojaFunkcja($a, $b){
        ...dalszy kod...
      }
  • Nie sięgamy do zmiennych globalnych (np. $_POST, $_GET, itp. w kontekście innym niż globalny. Wszelkie funkcje i metody klas powinny działać niezależnie od kontekstu wykonania (jest to zresztą niezbędny warunek ich testowalności).
    // ŹLE
    function mojaFunkcja(){
      if($_GET['parametr'] == 1){
        ...
      }
      ...dalszy kod...
    }
    
    // DOBRZE
    function mojaFunkcja($parametr){
      if($parametr == 1){
        ...
      }
      ...dalszy kod...
    }

Obiektowość

  • Programujemy obiektowo
  • Nie wystawiamy publicznych właściwości klasy
    • Pracowicie piszemy potrzebne setery i getery
      • Metody seterów i geterów powinny nazywać się ustawNazwaWłaściwości() i zwrNazwaWłaściwości()
    • Jedyny wyjątek to klasy będące tylko i wyłącznie kontenerami na dane (klasy pozbawione jakichkolwiek metod)
      // ŹLE
      class mojaKlasa{
        $wlasciwosc;
        
        ...reszta definicji klasy...
      }
      
      // DOBRZE
      class mojaKlasa{
        private $mojaWlasciwosc;
        
        public function zwrMojaWlasciwosc(){
          return $this->mojaWlasciwosc;
        }
        public function ustawMojaWlasciwosc($wartosc){
          $this->mojaWlasciwosc = $wartosc;
        }
        
        ...reszta definicji klasy...
      }
  • Używamy przestrzeni nazw:
    • prezentacja wskaźników (elipsy): EWD\Prezentacja
    • baza szkół: EWD\BazaSzkol
    • baza wyników: EWD\BazaWynikow
    • bank zadań: EWD\BankZadan
  • Używamy ładowarki klas (nie korzystamy z require_once() do ładowania klas)

Testy

  • Dla tworzonych klas piszemy testy PHP Unit - https://phpunit.de/manual/3.7/en/index.html
  • Dążymy do 100% pokrycia kodem.
    • Pamiętamy, że do poprawnego obliczania pokrycia musimy stosować odpowiednią konwencję zapisu kodu:
      // ŹLE
      if(warunek) zróbCoś;
      
      for(i = 0; i < próg; i++) zróbCoś;
      
      // ŹLE
      if(warunek)
        zróbCoś;
      
      for(i = 0; i < próg; i++) 
        zróbCoś;
      
      // DOBRZE
      if(warunek){
        zróbCoś;
      }
      
      for(i = 0; i < próg; i++){
        zróbCoś;
      }

Dokumentacja

  • Dokumentujemy kod źródłowy w konwencji Doxygen

Obsługa błędów

  • Błędy obsługujemy rzucając wyjątki (w przeciwieństwie do zwracania przez funkcje umówionych wartości oznaczających błędy).
  • Tworzymy specjalizowane klasy wyjątków zamiast rzucać wyjątkami klasy Exception.

Komunikacja z bazami danych

  • Używamy rozszerzenia PDO.
  • Używamy zapytań parametrycznych wszędzie tam, gdzie treść zapytania nie jest stałą.
  • Jeśli jest taka możliwość unikamy wykonywania dużej liczby małych zapytań na rzecz mniejszej liczby bardziej złożonych.
    // ŹLE
    $zapytanie1 = $PDO->query("SELECT * FROM tablica1 WHERE kolumna1 = wartość1");
    $zapytanie2 = $PDO->prepare("SELECT * FROM tablica2 WHERE kolumna2 = ?");
    while($wiersz = $zapytanie1->fetch()){
      $zapytanie2->execute($wiersz['kolumna2']);
      ...dalsza część kodu...
    }
    // DOBRZE
    $zapytanie1 = $PDO->query("SELECT * FROM tablica1 JOIN tablica2 USING (kolumna2)");
    while($wiersz = $zapytanie->fetch()){
      ...dalsza część kodu...
    }
  • Łamiemy kod zapytań SQL tak, by był czytelny
    // ŹLE
    $zapytanie = $PDO->query("SELECT t1.kolumnaG, count(*) FROM tablica1 t1 JOIN tablica2 t2 USING (kolumna) WHERE t1.kolumna1 = wartość 1 AND t2.kolumna2 = wartość 2 GROUP BY 1 ORDER BY 1");
    
    // DOBRZE
    $zapytanie = $PDO->query("
      SELECT t1.kolumnaG, count(*) 
      FROM 
        tablica1 t1 
        JOIN tablica2 t2 USING (kolumna) 
      WHERE 
        t1.kolumna1 = wartość 1 
        AND t2.kolumna2 = wartość 2 
      GROUP BY 1 
      ORDER BY 1
    ");
ewdphpstyle.txt · ostatnio zmienione: 2014/09/08 10:08 przez zozlak