Czytelne instrukcje warunkowe Drukuj
Ocena użytkowników: / 0
SłabyŚwietny 
Wpisany przez Patryk yarpo Jar   
piątek, 30 lipca 2010 17:56

Prosta instrukcja if czy switch. No przecież tu nie da się zrobić niczego lepiej. No, niekoniecznie. Da radę i zaraz to pokażę.
Przykłady będą w PHP, ale odnosi się do większości języków.

 

Instrukcja if

Myślę, że nie potrzebuje zbyt długo tłumaczyć jak działa if. Ale chciałbym pokazać, co można zrobić, aby był czytelniejszy. Pamiętaj - kod pisze się raz, a czyta wiele razy. Warto zatem odpowiednio go napisać.

01.// jest to juz trzecia proba polaczenia
02.// i juz bylo blednie podane haslo
03.if ($a == 3 && $b > 0)
04.{
05.    $file = fopen('file', 'w+');
06.    flock($file, LOCK_EX);
07.    $n = fwrite($file, $b);
08.    flock($file, LOCK_UN);
09.    $a += n;   
10.}
11. 
12. 
13.    

No i co tu jest nie tak? Przeciez komentarz ladnie opisuje wszystko, mamy wciecia, mamy wszystko czego potrzebujemy... No właśnie, ale czy nie da się lepiej?

 

Krok 1 - wyrzuć magiczne liczby

01.// jest to juz trzecia proba polaczenia
02.// i juz bylo blednie podane haslo
03.if ($connection_attemps == MAX_CONNECTION_ATTEMPTS && $wrong_passwords > 0)
04.{
05.    ...
06.}
07. 
08. 
09.    

Prawda, że już czytelniej. W sumie można teraz usunąć komentarz. Nie podobają mi się jeszcze 2 rzeczy.

 

Krok 2 - kolejność porównań i jednoznaczność

Ile razy zdarzył ci się taki błąd:

1.if ($tmp = true) {...}

i przez godzinę szukałeś błędu. To jest bezsensowne, bo jeśli do `$tmp' przypiszesz 3 to warunek będzie spełniony. Zawsze. Dlatego warto zamienić kolejność: najpierw stała, potem zmienna. Tak jak tu:

 

1.if (MAX_CONNECTION_ATTEMPTS === $connection_attemps && $wrong_passwords > 0)
2.{
3.    ...
4.}
5. 
6. 
7.    

Dodatkowo w językach skryptowych często występują dwa operatory porównania: "jest równe" (==) i "jest identyczne" (===). Jeśli coś piszesz, to powinieneś wiedzieć, jakiego typu coś będzie i jaka jest oczekiwana wartość. W takich sytuacjach powinieneś porównywać właśnie z taką wartością i wykorzystywać operator "jest identyczny".

 

Krok 3 - Osobna funkcja (metoda)

Bardzo często się zdarza, że taki warunek staje się niejako "stanem". I występuje w kilku miejscach. Jest niewiele rzeczy gorszych od powtarzającego się kodu. Z takim kodem najpiej jest... wrzucić go do funkcji (metody) i wywoływać.

O ile w obiekcie ma to większe uzasadnienie (szczególnie, jeśli warunek opiera się na właściwościach obiektu), o tyle w kodzie strukturalnym jest to czasem utrudnienie - jeśli do funkcji przekazujesz 5 parametrów, to przestaje to być czytelne.

01.define('MAX_CONNECTION_ATTEMPTS', 3);
02. 
03.function maxConnectionAttemptsAndWrongPass($connection_attemps, $wrong_passwords) {
04.    return MAX_CONNECTION_ATTEMPTS === $connection_attemps && $wrong_passwords > 0;
05.}
06. 
07. 
08.function logger($content) {
09.    $file = fopen('file', 'w+');
10.    flock($file, LOCK_EX);
11.    $n = fwrite($file, $content);
12.    flock($file, LOCK_UN);
13.    return n;
14.}
15. 
16.if (maxConnectionAttemptsAndWrongPass($connection_attemps, $wrong_passwords)) {
17.    logger($wrong_passwords);
18.}
19. 
20. 
21.    

Tu trochę na siłę jest wprowadzona jest funkcja `maxConnectionAttemptsAndWrongPass()'. Ale chciałem pokazać zasadę.