Cs: Różnice pomiędzy wersjami
Przejdź do nawigacji
Przejdź do wyszukiwania
m (Zabezpieczył Cs ([edit=sysop] (na zawsze) [move=sysop] (na zawsze))) |
(Brak różnic)
|
Aktualna wersja na dzień 07:29, 18 paź 2012
PROPOZYCJE STANDARDU KODOWANIA
Spis treści
Ścieżki
- Wszystkie podane katalogi wskazane są relatywnie do katalogu głównego skryptu.
- Wszystkie klasy znajdują się w katalogu classes/ oraz mają nazwy identyczne jak nazwa klasy (ważna jest wielkość liter!), przykład: PierwszaKlasa.php
- Pliki językowe znajdują się w katalogu language/. Nazwa pliku zawiera 2 litery charakterystyczne dla języka, znak _ oraz kategorię językową, np. pl_parts.php. Do obsługi plików językowych służy klasa Language (singleton).
- Pliki z danymi specyficznymi dla projektu znajdują się w katalogu data/. Do obsługi tych danych służy klasa DataCollector (singleton).
- Szablony znajdują się się w katalogu smarty/templates/. Do obsługi szablonów używana jest klasa MySmarty, dodatkowo główna aplikacja może korzystać z singletona MainTemplate.
- Wszystkie pozostałe pliki źródłowe znajdują się w katalogu głównym.
Konwencje nazewnicze
- Każda nazwa klasy powinna rozpoczynać się wielką literą, każdy następny człon nazwy również (np MainTemplate).
- Każda funkcja/metoda/zmienna/pole klasy powinny rozpoczynać się małą literą, każdy następny człon nazwy wielką (np. $myGreatVariable).
Przykład:
class ObiektKlasy { private $poleKlasy; public $drugiePoleKlasy; //... public function metodaKlasy { //EMPTY BODY } //... } $nowyObiekt=new ObiektKlasy(); $nowaZmienna=$nowyObiekt->getJakiesPole();
- Każde celowo puste ciało pętli, funkcji etc. powinno być odpowiednio oznaczone. Dzięki temu ktoś, kto będzie czytać kod i zobaczy np. pustą pętlę, nie będzie się zastanawiał, czy tak musi być, czy jest to przeoczenie programisty, czy też powinien to sam zaimplementować. Przykład zaprezentowany powyżej (//EMPTY BODY).
Zapytania SQL
- wszystkie polecenia SQL powinny być pisane dużymi literami (SELECT, INSERT, SET, WHERE, LIMIT itd)
- wszystkie nazwy pól powinny być zawarte między znakami ``, np. `actExp`, `id`
- wszystkie wartości pól powinny być zawarte między znakami (chyba, że używana jest funkcja $db->quote()).
- jeśli oczekujemy że zapytanie zwróci znaną przez nas liczbę rekordów (np równą jakiejś zmiennej lub liczbie), należy zastosować LIMIT, przykładowo dla 1 rekordu:
SELECT * FROM `tabela` LIMIT 1;
- każde zapytanie zawarte w kodzie PHP powinno być przyporządkowane do jakiejś zmiennej (np $query), ułatwia to obsługę błędów (np poprzez wypisanie zawartości zapytania). Każde zapytanie powinno kończyć się średnikiem.
$query = "treść zapytania;"; $rezultat = $db->exec(query); echo $query; // DEBUG
Obsługa błędów i wyjątki
- W żadnym skrypcie bezpośrednio związanym z projektem gry (oprócz skryptów wykonywanych niezależnie od użytkownika np skryptu aktualizacji rankingu) nie powinno pojawić się exit ani die. Zamiast tego powinien zostać rzucony wyjątek.
Przykład:
$db->beginTransaction(); $query = "UPDATE `chars` SET `actExp`=`actExp`+'$expDst' WHERE `id`='$me->id' LIMIT 1;"; $rows = $db->exec($query); if ($rows != 1) { $db->rollBack(); throw new Exception($query); } $db->commit();
UWAGA!!!
Rzucenie wyjątku oznacza przerwanie skryptu, wylogowanie użytkownika oraz wysłanie komunikatu o błędzie na maila kg@bwteam.pl. W związku z tym należy to robić tylko wtedy, gdy przewiduje się, że dane zachowanie skryptu oznacza błąd, w wyniku wystąpienia którego skrypt pod żadnym pozorem nie może być kontynuowany.
- W przypadku wielokrotnych instrukcji warunkowych (poziom zagłębienia powyżej 3), powinniśmy utworzyć funkcję sprawdzającą każdy warunek po kolei oraz zwracającą false w przypadku gdy dalsze sprawdzanie nie może być wykonywane lub nie jest potrzebne. Przykład:
function funkcjaSprawdzajaca($playerId, $playerName) { global $smarty; $db = Database::getInstance(); $lang = Language::getInstance(); if ($playerId == $me->id) { $smarty->assign('error', $lang->trade_cantOfferYourself); return false; } // sprawdz czy taki gracz w ogole istnieje $query = "SELECT `name` FROM `chars` WHERE `id`='$playerId' LIMIT 1;"; $playerName = $db->get($query); if (!$playerName) { $smarty->assign('error', $lang->trade_invalidPlayerId); return false; } // dalszy kod który wykona się w przypadku niewystąpienia tych błędów ... return true; // wszystko ok }
Klamry i formatowanie kodu
- Każdy blok kodu zaznaczony klamrami { i } powinien zaczynać się od nowej linii, a instrukcje/deklaracje w nim zawarte powinny zaczynać się od tabulacji. Bardzo pomocne w zachowaniu tego punku standardu jest ustalone standardowo formatowanie kodu środowiska Eclipse.
- W przypadku pętli ustalamy że możliwe są dwie konwencje:
if (warunek) { // tresc }
lub
if (warunek) { // tresc }
- W przypadku funkcji ustalamy że otwierająca klamra ma znajdować się zawsze w nowej linijce:
function jakasFunkcja() { // ciało }
Niezaklasyfikowane/pozostałe
- Każda pętla lub instrukcja warunkowa powinna dotyczyć bloku pomiędzy dwoma klamrami ({ i }). Język pozwala pominąć klamry w pętlach i instrukcjach warunkowych, jeśli dotyczą pojedynczej linijki zakończonej znakiem ';'. Mimo to zastosowanie nawet w tym przypadku klamer ma dwie zalety. Po pierwsze poprawia czytelność kodu, a po drugie sprawia, że na pewno nie zapomnimy o dostawieniu klamer, jeśli liczba instrukcji w pętli zwiększy się.
- Każdy blok switch powinien zawierać etykietę default. Jeśli nie ma sensownej logiki do umieszczenia w tej etykiecie, to kod w niej zawarty będzie obsługiwał nieprzewidziane wartości sprawdzanego wyrażenia. Nie da się przewidzieć wszystkiego - nawet, jeśli ktoś robi switch na zmienną wyliczeniową, która może przyjmować tylko kilka wartości, to przecież nikt nie powiedział, że nie trzeba będzie kiedyś tego typu rozszerzyć - wtedy taki default wychwyci ewentualne zapomnienia w uzupełnieniu instrukcji switch. Jeśli warunek default nie powinien się nigdy zdarzyć w danej konstrukcji switch, obsługa takiego nieprzewidzianego powinna polegać na rzuceniu wyjątku wraz z treścią wskazującą na wartość sprawdzanego parametru.