Projektowanie stron WWW od podszewki

Artykuły na każdy temat

[PHP] Standardy kodowania

Dodano 27.05.2010r. o 13:35
Zacznę swoją wypowiedź od tego samego co napisałem w innym artykule dotyczącym standardów kodowania arkuszy stylu CSS. Jak wiemy budowanie aplikacji WWW opiera się na ustalonych wcześniej zasadach. Każdy z nas pisząc jakikolwiek skrypt używa standardów własnych bądź wymuszonych odgórnie. Swoje standardy wypracowaliśmy w pierwszym kontakcie z tym językiem. Zapewne w czasie ulegały one zmianom. Te reguły gry pełnia ważną rolę w pracy grupowej. To dzięki tym zasadom kod jest czytelny dla każdego z uczestników projektu. Jest to także bardzo istotne w momencie pisania kolejnych linijek kodu jak i szukaniu bądź poprawianiu istniejących. Poniżej zostaną przedstawione przykłady w jaki sposób kod powinno się pisać, a w jaki nie. Naturalnie przedstawię swoje własne standardy oraz inne najczęściej spotykane. Liczę na to, że bazując na tym artykule przeanalizujecie i wypracujecie własne zasady pisania kodu.

Nota

Na początku wypadałoby wskazać listę źródeł, z których to czerpało się inspiracje, prawda? Oto i ona:

Nazewnictwo plików

W gąszczu katalogów i plików nazewnictwo jest bardzo istotne gdyż w znacznym stopniu ułatwia odnajdywania poszukiwanej rzeczy. Pamiętajmy aby nazywać pliki zgodnie z ich przeznaczeniem czyli np. klasa z mechanizmem pamięci podręcznej powinna nosić nazwę cache.class.php. Ponadto do oznaczania plików powinno się używać znaków z zakresu a-z i _ czyli znaku podkreślenia. Naturalnie wszystkie nazwy piszemy z małych liter. Rozszerzenia powinny być używane zgodnie z ich przeznaczeniem. Często można spotkać także pliki z końcówką inc.php, które są przeznaczone do includowania. Innym przykładem są pliki z rozszerzeniem tpl odpowiedzialne niejako za szablon strony. Czasami można się także natchnąć na końcówkę test.php oznaczającą klasę testową określonego modułu.

Zachowanie spójności nazwy klasy i jej pliku

Staraj się zachować spójność miedzy nazwa klasy i zawartością pliku. Oznacza to, że pakujemy do pliku tylko rzeczy niezbędne do działania określonej klasy i nic poza tym.

Znaczniki PHP

Pamiętajmy aby używać znaczników PHP w stylu XML czyli <?php na początek i ?> na koniec. W przyszłości zapobiegnie to marnowaniu czasu na zbędne edycje plików. Dlaczego właściwie styl XML? Chociażby dlatego, że działa on zawsze, a styl krótki czyli <? ?> działa tylko gdy w dyrektywa short_open_tag ma wartość 1. W przyszłości prawdopodobnie styl krótki nie będzie obsługiwany.

Nagłówek pliku

Bazując na narzędziach typu PHPDocumentor, Doxygen bądź Javadoc nagłówek pliku powinien wyglądać mniej więcej tak:
Kod:
<?php
/**
*
* @author Pierwszy autor persona1@example.com
* @author Drugi autor persona2@example.com
*
* @package Nazwa paczki
* @version $Id:$
* @copyright (c) 2009 Nazwa Twojej grupy/projektu
* @license http://creativecommons.org/licenses/by-sa/3.0/pl/
*
*/
?>
Powyższy zapis pomoże w zorientowaniu się z czym tak naprawdę mamy doczynienia.

Definicje wstępne

Czasami zdarza się, że musimy zdefiniować parę stałych na początku pliku zaraz po nagłówku. Według mojego standardu wyglądać to powinno tak:
Kod:
<?php
/**
* {HEADER}
*/

/**
* @ignore
*/
define("PIERWSZA"true);
define("DRUGA"false);
?>

Stałe

Przy definiowaniu stałych starajcie się nie używać __ na początku i końcu aby nie spowodować kolizji z innymi stałymi np. __FILE__, __LINE__ etc.

Apostrof VS cudzysłów

Jeżeli tylko macie możliwość to używajcie apostrofów zamiast cudzysłowu ponieważ jest szybsze. Oczywiście są przypadki, w których nie ma wyjścia i trzeba wykorzystać " jednak starajcie się aby apostrof był priorytetem.

Nazewnictwo zmiennych

Nazewnictwo zmiennych odgrywa bardzo ważną rolę w pisaniu kolejnych linijek jak i szukaniu bądź poprawianiu istniejących. Ze względu na to, że bardzo często współpracuję z ludźmi z różnych zakątków świata dlatego też dobrym pomysłem jest pisanie aplikacji WWW w języku angielskim włącznie z dokumentacją. Praktycznie każdy język programowania opiera się na języku angielskim. Mam tutaj na myśli chociażby nazwy funkcji, które stworzono ze skróconych nazw określonych operacji. Najprostszym przykładem będzie chociażby taki strrev() czyli string reverse (odwrócenie ciągu). Oczywiście głównym powodem stosowania się do tej zasady jest uniwersalność. Jak wiemy prawdziwy programista cechuje się dobra znajomością angielskiego. Moim zdaniem każdy piszący skrypty winien pisać po angielsku. Dzięki takiemu zabiegowi nikt nie będzie musiał tłumaczyć kodu na inny język.

Sensowne nazewnictwo jest bardzo ważne. To dzięki niemu szybko zorientujemy się w kodzie i tym co zawierają poszczególne zmienne. Poniżej znajdują się pzykłady złego nazewnictwa zmiennych.
Kod:
<?php
$currentuser;
$currenttime;
$externalvariable;

$CurrentUser;
$CurrentTime;
$ExternalVariable;

$Current_User;
$Current_Time;
$External_Variable;
?>
A teraz zestaw, który jest poprawny i buduje mój standard:
Kod:
<?php
$current_user;
$current_time;
$external_variable;
?>
Odpowiednie nazwy nośników danych gwarantują ergonomiczne poruszanie się po stosie linijek. Dla przykładu taka zmienna jest źle nazwana:
Kod:
<?php
$current_date_and_time;
?>
a ta dobrze:
Kod:
<?php
$now;
?>
Czasami można się spotkać także ze szkołą mówiącą, że z wielkiej litery zaczynamy kolejne słowa w zmiennej czyli w praktyce np. $external_variable powinno być napisane tak: $external_Variable. Moim zdaniem tym więcej optymalizacji tym lepiej dla wszystkich. Mnie zawsze uczono aby pisać wszystko z małej i tak mi zostało. Przynajmniej palców nie mecze nerwowym sięganiem co chwile do shifta Wink Drugim powodem stosowania zasady pisania wszystkiego z małych liter jest fakt, że $zmienna nie jest tym samym co $Zmienna oraz nie jest równoznaczne z $ZMIENNA.

PascalCase

PascalCase jest zasada mówiącą o tym, że każdą pierwszą literę słowa piszemy dużą literą czyli np. ButterflyStatus.

CamelCase

CamelCase jest zasadą mówiącą o tym, że pierwszą literę słowa piszemy małą literą oraz pierwsze litery kolejnych słów dużymi literami. W praktyce wygląda to np. tak: listCursors.

Mieszanie języków

Jeżeli już ustaliliście język w który będzie stosowany przy nazewnictwie funkcji, klas i metod oraz komentarzy to trzymajcie się go. Potem przynajmniej nie powstaną kwiatki typu GetMotylStyle().

Notacja węgierska

Pewien programista z Microsoft wymyślił notacje węgierską, która narzuca nijako sposób nazewnictwa obiektów i zmiennych. W PHP bardzo rzadko spotykane. Istniała także zasada mówiąca, że pola prywatne klasy winny zostać oznaczone przedrostkiem _. Czasami można także spotkać się z zasada, która mówi, że przed nazwa jakiegokolwiek pola klasy należy użyć _ niezależnie od operatora widoczności. Jestem w stanie zrozumieć ową notacje przy pisaniu programów w C++ jednak w PHP nie ma najmniejszej potrzeby jej stosowania dlatego też odradzam używanie.

Litery podobne do cyfr i odwrotnie

Starajcie się unikać sytuacji, która została przedstawiona poniżej. Przy takiej konfiguracji łatwo o omyłkę związanej ze złym rozpoznaniem znaku.
Kod:
<?php
$lO1 "1I";
?>

Używamy skrótów z głową

Jeżeli macie możliwość stosowania skrótów starajcie się z niej korzystać. Taki zabieg ułatwia poruszanie się po pliku oraz nieco zmniejsza jego objętość. Przykładem takiego skrótu może być np. ShowUI czyli Show UserInterface.

Zmienne i odstępy

Kiedyś spotkałem się z kodem, w którym to zastosowano zasadę wyrównywania do znaku równa się. Niby wszystko pięknie wygląda jednak na dłuższą metę gdy mamy ze 100 zmiennych i nagle pojawia się zmienna dłuższa od najdłuższej obowiązującej to trzeba powkładać nowe odstępy.
Kod:
<?php
$x                           = array("a""b""c");
$bardzo_bardzo_dluga_zmienna array_flip($x);
$krotka_zmienna              "whatever";
?>

Nazewnictwo funkcji, klas i metod

Nazwy klas powinny odzwierciedlać to czym się zajmują. To samo tyczy się nazw funkcji oraz metod. Tak więc metodę pobierającą status osoby nazywamy get_status(), a nie show_member_status() (skrajne rozwiązanie dla psychopatów Wink ).

Dodatkowo przy nazewnictwie klas powinniśmy używać rzeczownika w liczbie pojedynczej. W praktyce oznacza to, że klasa opisująca członków powinna nazywać się Member, nie Members.

Tablice i odstępy

Zasadniczo mam 2 style definiowania tablic. Jednoliniowy stosowany w momencie gdy elementów w tablicy nie jest dużo.
Kod:
<?php
$dziwne_cyferki = array(169453);
?>
I drugi styl używany gdy tablica zawiera dużo elementów.
Kod:
<?php
$krzywe_bity = array("pierwszy" => "lewy",
                     "drugi" => "płaski",
                     "trzeci" => "długi");
?>

Definiowanie funkcji, klas i metod

Odnośnie definiowania funkcji nie ma żadnych kruczków prawnych. Jeżeli jest potrzeba użycia dyrektywy global wtedy robimy to na początku funkcji lub po określonym if'ie jeżeli zmienna która ma być globalna ma zostać wykorzystana tylko w określonym fragmencie funkcji/metody. Jak widać na poniższym listingu miedzy global, a instrukcją warunkową jest odstęp. Taki sam odstęp miąłby miejsce gdyby pojawiła się tam definicja zmienna tablica.
Kod:
<?php
function udziwnij_ciag($str// nie miałem pomysłu na nazwę Razz
{
 global $config;
 
 if(strlen($str) > 0)
 {
  /*** ciach, tu cos kiedyś było, chyba? ***/
  return $config["hash"].$str.date("H");
 }
 else
 {
  return null;
 }
}
?>
Wiem, że mogłem to rozwiązać za pomocą operatora trójkowego lecz nie miałem dobrego pomysłu na przykład i ... Chce także napomknąć, że wartości typu null, false, true piszemy zawsze z małych liter.

Odnośnie definiowania metod to zasada jest taka sama tylko z tą różnicą, że stosujemy public, private i protected zgodnie z ich przeznaczeniem. Dodatkowo jeżeli korzystamy z metod magicznych to starajmy się je definiować na początku klasy. Ja mam swoją zasadę, że pierw definiuje pola. Następnie oczywiście metody według operatora widoczności. Moja kolejność wygląda tak:
  1. public
  2. protected
  3. private
Kod:
<?php
class example
{
 $memory null;
 
 public function calc() { /* Ciało metody */ }
 
 protected function load_config() { /* Ciało metody */ }
 
 private function add_event() { /* Ciało metody */ }
}
?>

Nazewnictwo argumentacji funkcji i metod

Nazewnictwo te winno odzwierciedlać to co do danej funkcji zostaje przekazane. Oznacza to, że argumenty powinny wyglądać tak:
Kod:
<?php 
function auth($username$password) { }
?>
a nie tak:
Kod:
<?php
function auth($a$b) { }
// lub
function auth($name$pass) { }
?>

Komentarze

Odnośnie komentarzy to preferuje używanie wielo-liniowego /* */ oraz jednoliniowego //. Czasami zdarza mi się używać # jako elementu grupującego na przykład w konfiguracji skryptu.
Kod:
<?php
# MySQL
$config["mysql"]["host"] = "localhost";
$config["mysql"]["database"] = "database";
$config["mysql"]["login"] = "prosty_login";
$config["mysql"]["password"] = "trudne_haslo";
$config["mysql"]["prefix"] = "no_i_prefiks_";
# Dir config
$config["dir"]["langs"] = "langs"// Folder with langs files
$config["dir"]["logs"] = "logs"// Folder with any logs
?>

Wcięcia i tabulacja

Standardowo programiści powinni używać 4 spacji jako wcięć czyli jak na poniższym listingu.
Kod:
<?php
    // początek wcięcia podstawowego
        // początek wcięcia poziomu pierwszego
            // początek wcięcia poziomu drugiego
            do_something();
            // koniec wcięcia poziomu drugiego
        // koniec wcięcia poziomu pierwszego
    // koniec wcięcia podstawowego
?>
Osobiście preferuje wcięcia składające się z jednej spacji. Przynajmniej nie trzeba machać na lewo i prawo wzrokiem. W czasach kiedy rozdzielczości były mniejsze duże wcięcia powodowały problemy z poruszaniem się po kodzie. Poniżej znajduję się moja wersja standardu wcięć.
Kod:
<?php
 // początek wcięcia podstawowego
  // początek wcięcia poziomu pierwszego
   // początek wcięcia poziomu drugiego
   do_something();
   // koniec wcięcia poziomu drugiego
  // koniec wcięcia poziomu pierwszego
 // koniec wcięcia podstawowego
?>

Wywołanie funkcji i metod

Poniżej przedstawiam w jaki sposób powinno się wywoływać funkcje i metody zgodnie z moim standardem.
Kod:
<?php
$result foo($bar);
$result do_something($foo$bar);

$post_office -> send_msg($to$message);
?>
A na poniższym listingu jak nie powinno się tego robić:
Kod:
<?php
$result foo$bar );
$result do_something$foo$bar );
$result do_something$foo $bar );
$result do_something($foo,$bar);
$result=do_something($foo,$bar);

$post_office -> send_msg$to$message );
$post_office -> send_msg$to $message );
$post_office -> send_msg($to,$message);
$post_office->send_msg($to,$message);
?>

Wygląd struktur kontrolnych

Do struktur kontrolnych zaliczamy instrukcje warunkowe if oraz inne szmery bajery typu for, while, switch itp. Poniżej znajduje się najprostszy przykład jak powinny wyglądać poprawnie. Chce także wspomnieć, że według mojego standardu lepiej pisać else if aniżeli elseif.
Kod:
<?php
if($a && $b)
{

}
else if(!$a || $b)
{

}
else
{
 // default
}

if($c)
{
 if($d)
 {

 }
 else
 {

 }
}

switch($condition)
{
 case "one":
  do_something();
  do_something_else();
 break;
 
 case "two":
 case "three":
  exit;
 break;
 
 default:
 
 break// Dla czystości sumienia można dodać Smile
}
?>
I znów listing w którym tym razem pokazuje jak nie powinien wyglądać kod.
Kod:
<?php
if ($a && $b// Niepotrzebnie zrobiony odstęp
{

}
else if(!($a) || $b// Niepotrzebnie użyty nawiasy
{

}

if($c)
{
 if($ddo_something(); // Brak klamer
}

switch($condition)
{
 case "one":
 do_something(); // Brak wcięcia
 do_something_else(); // Jak wyżej
 break;
 
 case "two": case "three"// Warunki w tej samej linijce
 exit// Brak wcięcia
 break;
}
?>

Nawiasy klamrowe w instrukcjach sterujących

Jest kilka stylów programowania odnoszących się do zapisu nawiasów klamrowych w instrukcjach warunkowych, klasach, funkcjach, pętlach itp. Za chwile przedstawię Wam najpopularniejsze z nich. Styl pisania nawiasów klamrowych wchodzący w mój standard został przedstawiony powyżej.

Styl BSD

Styl ten charakteryzuje się tym, że nawias otwierający jest umieszczony w wierszu po warunku i oba nawiasy są wyrównane do lewej strony słowa kluczowego.
Kod:
<?php
if ($condition)
{
    // Instructions
}
?>

Styl GNU

Styl w którym nawias otwierający jest umieszczony w następnym wierszu oraz jest wcięty o połowę poziomu wcięcia.
Kod:
<?php
if ($condition)
  {
    // Instructions
  }
?> 

Styl K&R

Nazwa tego pochodzi od nazwisk Kerninghan oraz Ritchie. Są oni autorami książki "Programowanie w języku C", w której stosowany jest właśnie ten styl.
Kod:
<?php
if ($condition) {
    // Instructions
}
?>

Styl Wishart (Whitesmiths)

Styl ten pochodzi od firmy Whitesmiths, która jest autorem pierwszego komercyjnego kompilatora języka C. Pierwszym miejscem, w którym zastosowano ten styl była dokumentacja kompilatora.
Kod:
<?php
if ($condition)
        {
        do_something(); 
        }
?>

Grupowanie wyrazów

Aby zwiększyć czytelność kodu powinniśmy umiejętnie grupować wyrażenia.
Kod:
<?php
if(!($object instanceof class_name))
{

}
?>
Kod:
<?php
if((!$a && $b) || ($c && !$d))
{

}
?>
Nie używajcie nawiasów przed każdym wykrzyknikiem. To tylko zmniejsza czytelność kodu. Dodatkowo nie róbcie odstępów miedzy nawiasami tak jak na poniższym listingu:
Kod:
<?php
if( !( $a ) && $b )
{

}
?>
Z pewnością kod w ten sposób nie staje się bardziej czytelny.
Kod:
<?php
for($h 0$tmp['how'] = (count($random_array) - 69)$h $tmp['how']; ++$h)
{

}
?>
Dzięki użyciu nawiasów wiemy gdzie kończy się przypisanie wartości do tablicy.

Typ zmiennej i rzutowanie

Przypominam, że PHP rzutuje dane niejawnie więc powinniśmy odpowiednio dobierać operatory porównania.
Kod:
<?php
$boolean_var true;
$string_var "true";
$other_var null;

if($boolean_var)
{
 if($string_var == true)
 {
  if($other_var == false)
  {
   echo "O really?";
  }
 }
}
?>
Tym przykładem chce tylko wskazać różnicę miedzy ===, ==, !==, !=, null, false, true i tym podobnych Smile

Operator trójkowy

Poniżej przykład z użyciem operatora trójkowego.
Kod:
<?php
function some_inline_function($param)
{
 return ($param 999 true false);
}
?>

Pętle

Znam trzy szkoły odnośnie pętli. Wszystkie z nich rozbijają się o nazewnictwo kursora elementu. Pierwsza mówi o tym aby zaczynać od $h i iść dalej. Inna szkoła mówi o tym aby zaczynać literki $i i przemieszczać się do przodu. Trzecia szkola nakazuje zaś nam zaczynanie od literki $a. Osobiście używam tej pierwszej i według mnie jest najbardziej racjonalna i wygodna.
Kod:
<?php
for($h 0$h $first_size; ++$h)
{
 for($i 0$i $second_size; ++$i)
 {
  for($j 0$j $third_size; ++$j)
  {
   // Do something!
  }
 }
}
?>
Przypominam także aby stosować preinkrementację, która jest nieco szybsza aniżeli postinkrementacja.

Korzystając z okazji napomknę także jak powinna wyglądać pętla foreach() oraz while().
Kod:
<?php
foreach($some_array as $key => $value)
{

}
?>
Kod:
<?php
$h 1;

while($h 10)
{
 echo ++$h;
}
?>
Jeszcze raz przypominam, że stosowanie się do standardów pomaga w pracy zespołowej. Powyżej zostały przedstawione własne standardy kodowania i liczę na to, że na podstawie tego artykułu wypracujecie własne.

PS
Nie robiłem zrzutów ekranów odnośnie wyglądu kodu ze względu na to, że sami możecie je zrobić bądź po prostu oddalić się od monitora i ocenić czy kod jest czytelny.

Komentarze

Publikowane komentarze są prywatnymi opiniami użytkowników serwisu. Serwis nie ponosi odpowiedzialności za treść opinii. W trosce o zachowanie poziomu dyskusji wszystkie komentarze podlegają akceptacji przed ich publikacją dlatego proszę cierpliwie czekać aż komentarz zostanie opublikowany.

CapaciousCore

Dodano 16.01.2012r. o 23:48
@soanvig to jakoś mam z automatu Razz

soanvig

Dodano 16.01.2012r. o 22:37
"Przynajmniej palców nie mecze nerwowym sięganiem co chwile do shifta"

A jak wpisujesz podłogę? Very Happy

komi92

Dodano 27.05.2010r. o 20:33
Bardzo ciekawy artykuł ;> Fajnie się czytało, pozdrawiam i dziękuję za info o nim ;]

Dodaj komentarz

Zostaw komentarz jeżeli możesz! Nie bądź przysłowiowym botem! Nie bądź obojętny! Ciebie to nic nie kosztuje, a mi sprawi uśmiech na twarzy.
Zezwolono używać: BBCode
Zabroniono używać:
znaczników HTML

(Wymagany)

(Wymagany, niepublikowany)

(Nie wymagana)

Token:

Obrazek dla bota

(Przepisz tylko cyfry!)

(Wymagana)