Winuser's Blog

11 grudnia 2011

część II : Logicznie błędny kod – PHP

Filed under: PHP,Programowanie — winuser @ 15:11
Tags: ,

Wpis jest kontynuacją poprzedniego postu o błędach logicznych w kodzie programu. Ponieważ ostatnio zmuszony byłem do ostrego siedzenia nad kodem w języku PHP, przez pewnego klienta, dlatego wpis będzie właśnie traktował o tym języku. Okazuje się, że w PHP niewiele trzeba aby pisać kod logicznie błędny, jednocześnie trudny do poprawienia, szczególnie gdy projekt jest większy niż te kilkaset linijek.
Na początek klasyka gatunku pod tytułem „błąd z pętlą” :

while (cos_tam);
{
 // jakis kod
 int a = 1 + 2;
}

Klasyka tym razem dla operatora równości :

if ($nextRowID = $rowID)
 break;

Jak widać, tym razem programista tak się śpieszył, że napisał tylko jeden znak „=”, w wyniku czego wyszedł mu operator przypisania. Efektem tego będzie zawsze true, czyli warunek jest bezsensowny.

Programiści języków z rodzaju C/C++ automatycznie dodają znak średnika na końcu wiersza. Zdarza im się to nawet poza kodem.
Kolejny przykład, jeden z moich faworytów. Przykład typowy dla języka PHP w którym zmienna tworzona jest w miejscu pierwszego użycia :

$installler[$row['ID']] = $row['value'];
// kilkaset linii dalej lub w innym pliku
echo $installer['1'];

Dla tych którzy jeszcze nie zauważyli co z powyższym kodem jest źle, już śpieszę z wytłumaczeniem. Chodzi o potrójną literkę `l` w nazwie zmiennej. W wyniku tej pomyłki interpreter PHP utworzy dwie zmienne, jedną $installler oraz drugą $installer. Oczywiście w $installer nie będzie tego co chcieliśmy osiągnąć w linii numer 1 🙂
Czas na przejście do kolejnego przykładu. Jest on również typowy dla PHP. Typowy, ponieważ w języku C kompilator rzuciłby warning „not all paths return a value”.

function Worker($arg_1)
{
 if ($arg_1 < 1024)
 return false;
}

function Another()
{
 // gdzieś w innym, odległym miejscu..
 $result = Worker(300);
 if ($result == true)
 {
 // nigdy się nie wywoła..
 }
}

Ten błąd akurat można w całkiem prosty sposób wykryć, wystarczy zajrzeć w ciało funkcji „Worker”.
Kolejny przykład dotyczy zapytania MySQL. Z bazami danych programista PHP ma doczynienia praktycznie ciągle, więc przykład również się nadaje.

$ret = $db->query("SELECT * FROM `usr` WHERE `uid` = '$uid' AND `field` = $var;");
if ($ret == false || $ret->num_rows == 0)
{
 echo "error";
}

Co będzie wynikiem tego zapytania gdy zmienna $var nie będzie miała wartości nadanej ? Zapytanie będzie błędne. Rozwiązaniem jest branie wszystkiego co możliwe, w cudzysłowy pojedyncze, czyli ostatni kawałek zapytania wyglądałby :

AND `field` = '$var';

Jak widać PHP jest bardzo podatny na błędy w logice kodu. Dzieje się tak w dużej mierze z tego powodu że nie ma on określonych na sztywno typów danych, czyli zmienna która przed chwilą przechowywała tekst, za chwilę może już przechowywać liczbę typu double albo zmienną typu bool. Ta właściwość może być błogosławieństwem albo zmorą. Być może ja osobiście mam takie problemy podczas programowania w PHP, ponieważ jestem dość silnie związany z C / C++ w których to językach jak wiadomo panuje dość silna typizacja zmiennych. Dodatkowym powodem problemów jest to że interpreter PHP nie zwraca uwagi czy funkcja zwraca jakąś wartość, czy może zwraca tylko czasami, ponieważ nie istnieje prototyp funkcji do której kod musi być dopasowany (czyli że funkcja zwraca typ bool i koniec). Na dłuższą metę programując w PHP chyba być zwariował 😉

Reklamy

Dodaj komentarz »

Brak komentarzy.

RSS feed for comments on this post. TrackBack URI

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: