Dlaczego wielu deweloperów PHP nienawidzi korzystania z isset () i / lub dowolnej z podobnie defensywnych funkcji PHP, takich jak empty ()?


27

Po przepełnieniu stosu cały czas pojawia się ten problem:

Nawet Pekka (który oferuje wiele solidnych porad PHP) natrafił na przerażającego E_NOTICEpotwora i liczył na lepsze rozwiązanie niż użycie isset(): isset () i empty () sprawiają, że kod jest brzydki

Osobiście używam isset()iw empty()wielu miejscach do zarządzania przepływem moich aplikacji. Na przykład:

public function do_something($optional_parameter = NULL) {
    if (!empty($optional_parameter)) {
        // do optional stuff with the contents of $optional_parameter
    }
    // do mandatory stuff
}  

Nawet prosty fragment taki jak ten:

if (!isset($_REQUEST['form_var'])) {
    // something's missing, do something about it.
}

wydaje mi się bardzo logiczne. Nie wygląda jak wzdęcie, wygląda jak stabilny kod. Ale wielu programistów uruchamia swoje aplikacje z E_NOTICEwłączoną funkcją, odkrywa wiele frustrujących powiadomień o „niezainicjowanym indeksie tablic”, a następnie krzywi się na myśl o sprawdzeniu zdefiniowanych zmiennych i „zaśmieceniu” ich kodu isset().

Zakładam, że inne języki traktują to inaczej. Mówiąc z doświadczenia, JavaScript nie jest tak uprzejmy jak PHP. Niezdefiniowana zmienna zwykle zatrzymuje wykonywanie skryptu. Ponadto (mówiąc z niedoświadczenia ) jestem pewien, że języki takie jak C / C ++ po prostu odmówiłyby kompilacji.

Czy więc deweloperzy PHP są po prostu leniwi? (nie mówiąc o tobie, Pekka, wiem, że refaktoryzowałeś starą aplikację). Czy też inne języki obsługują niezdefiniowane zmienne z większą wdzięcznością niż wymaganie od programisty sprawdzenia, czy zostały zdefiniowane?

(Wiem, że istnieją inne E_NOTICEkomunikaty oprócz niezdefiniowanych zmiennych, ale te wydają się być tymi, które powodują najwięcej rozczarowania)

Dodatek
Z dotychczasowych odpowiedzi nie jestem jedyną osobą, która uważa, że isset()to nie wzdęcia. Zastanawiam się teraz, czy są problemy z programistami w innych językach, które odzwierciedlają ten język? Czy jest to wyłącznie kwestia dotycząca kultury PHP?


4
Niestety widziałem, jak deweloperzy php pracują z wyłączonymi „ostrzeżeniami”.
Viper_Sb,

Ojej. To jest smutne
Stephen

1
Nie będąc użytkownikiem PHP zastanawiam się: dlaczego miałbyś sprawdzać niezdefiniowane zmienne?
Winston Ewert,

2
@Winston: Problem z PHP (w przeciwieństwie do wielu innych języków) polega na tym, że PHP pozwala na wiele kombinacji konfiguracji. Na przykład programista może zignorować ostrzeżenia, powiadomienia i powiadomienia o wycofaniu. Bardziej doświadczeni programiści będą pracować z zestawem raportowania błędów, aby raportować wszystko. PHP ma również wiele funkcji, które generują błędy i zwracają kody stanu zamiast wyjątków. Trzeba być bardzo intymnym z językiem, aby móc skutecznie i skutecznie kodować. Wiele innych języków nie pozwala na wybór. Ścisła jest zwykle domyślną i jedyną opcją.
Wil Moore III

1
Nie podoba mi się isset () z powodu gadatliwości, którą dodaje. Lepsza forma @ byłaby dobrą alternatywą.
Kzqai

Odpowiedzi:


34

Koduję do E_STRICTi nic więcej.

Używanie pustych i kontrolnych ustawień nie powoduje, że kod jest brzydki, ale sprawia, że ​​kod jest bardziej szczegółowy. Moim zdaniem, co jest absolutnie najgorszą rzeczą, która może się wydarzyć z ich używania? Wpisuję jeszcze kilka znaków.

Sprawdza konsekwencje ich nieużywania, a przynajmniej ostrzeżenia.


7
Moje środowisko programistyczne również E_STRICT. Pomijam wszystkie błędy w produkcji, ale to po to, aby upewnić się, że nic nie przeszło mi w rozwoju.
Stephen

2
+1 Josh, jestem taki sam. Kiedy programujesz w E_STRICT, wiesz , że nigdy nie będziesz mieć niespodzianek w kodzie. Jedyny sposób na latanie, imo.
EricBoersma,

3
@ Stephen: Zawsze wyłączaj błędy produkcyjne. To tylko siatka bezpieczeństwa. Rozwój powinien zawsze być (IMO) E_STRICT. Napisz kod i rozwiąż wszystkie ostrzeżenia i błędy.
Josh K

papugujesz mnie? :)
Stephen

@Stephen: Zgadzam się. :)
Josh K

17

Myślę, że powiadomienia o nieznanych elementach są błędem projektowym w PHP. Nie jestem pewien, czy można teraz naprawić błąd, ale generuje dużo kodu typu „kocioł” if(isset($foo['abc']) && $foo['abc'] == '123')- taki kod nie powinien mieć isset, ponieważ chodzi o sprawdzenie, czy w pewnym miejscu jest „123”, $fooa jeśli nic tam nie ma, zdecydowanie nie „123”. Jedynym powodem, dla którego musisz napisać dwa razy więcej kodu, jest ten niefortunny błąd projektowy w PHP. A powiadomienia są bardzo drogie w PHP, niestety, więc wyłączenie ich nie jest opcją dla kodu, w którym wydajność ma znaczenie.

Więc tak, to czyni kod brzydkim IMHO i denerwuje mnie. I to nie z powodu braku doświadczenia - używam PHP od 1998 roku i pamiętam, kiedy było .php3rozszerzenie i oznaczało to „nie PHP 2”. Może jestem leniwy :) Ale lenistwo - przynajmniej pewien jego rodzaj - jest cnotą dla programisty.

Z drugiej strony prawidłowe użycie isseti empty- podobnie jak w oryginalnym poście - jest w porządku. Po prostu uważam, że PHP jest zbyt gorliwy w przypadku ostrzeżeń w miejscach, w których isset/emptytak naprawdę nie są potrzebne.


3
Dobrze. To kwestia gadatliwości. $eg = isset($_GET['eg'])? $_GET['eg'] : null;jest absurdalnie gadatliwy. Naprawdę chciałbym, aby istniał inny operator, który nie byłby „tłumieniem błędów” jako taki, który zastąpiłby krótkie znaczenie $eg = @$_GET['eg'];„zaakceptuj nieistnienie-tego-klucza-tablicy-jako-zerowej”. Obecnie używam krótkiej funkcji.
Kzqai

7
Zgoda. 4 lata później wejdź do Null Coalesce Operator: wiki.php.net/rfc/isset_ternary, podając nam$eg = $_GET['eg'] ?? null;
Steve

Lub po prostu zrób to teraz z operatorem eliminacji błędów, np $eg = @$_GET['eg'] ?: null;. Zasadniczo go nie używam, ale w tym przypadku wyraźnie oczekujemy tego błędu i postanawiamy go zignorować. Jest jedną postacią dłuższą niż wartość zerowa i nie jest tak dobra (tłumi wszystkie błędy, a ArrayAccess może robić tam fajne rzeczy, nie tylko tablicę), ale ogólnie robi to.
El Yobo,

12

Wierzę, że PHP, jako wolny język, który jest interpretowany i używany w Internecie, ma bardzo wysoki odsetek nieprofesjonalnych, nieprzeszkolonych programistów, którzy nie są w pełni świadomi, dlaczego powinni kodować w sposób defensywny i widzą ostrzeżenia jako kolejny niepotrzebny błąd .

Ciągle słyszę te uwagi od młodszych programistów i samouków, którzy są programistami skryptów:

  • Po co inicjować zmienną, jeśli i tak powstanie?
  • Po co sprawdzać, czy coś istnieje, zanim go użyjemy, i tak niezdefiniowany równa się fałszowi?
  • Jeśli prefiks @ naprawia mój kod, po co komplikować?

Jeśli nigdy nie doświadczyli silnie typowanego języka ani nie doświadczyli pułapek niezadeklarowanych / niezainicjowanych zmiennych, wówczas przekonują się. Uważam, że zwykle się poddają, gdy odczuwają przyjemność debugowania kodu przez około godzinę, i okazało się, że to literówka w nazwie zmiennej powodująca problemy.

Innym silnym czynnikiem jest wykorzystanie PHP w przemyśle internetowym, który jest znacznie bardziej zainteresowany wydajnością niż bezpieczeństwem i jakością kodu.


10
„Wierzę, że PHP [...] ma bardzo wysoki odsetek nieprofesjonalnych, nieprzeszkolonych programistów” Jako oddany deweloper PHP nie mogę się z tobą więcej zgodzić. +1
Stephen

@Stephen Cóż, ostatnio piszę głównie w PHP i jQuery, chociaż mam formalne wykształcenie, ale kod, który widzisz jako profesjonalistę, przed którym stajesz się odpowiedzialny, ... czasami czasami przeczy. ;-)
Orbling

1
Myślę, że to prawdziwy problem z PHP. Oprócz niektórych dziwactw w języku (które powoli rozwiązują w każdej nowej wersji), jest w nim atmosfera amatorstwa. Mogę sobie wyobrazić, że bycie profesjonalnym deweloperem PHP może czasem być frustrujące, ponieważ porównuje się cię do „siostrzeńca szefa zza rogu”.
Erik van Brakel

1
@Erik PHP był dość biednym krewnym Perla dziesięć lat temu, jest teraz dość rozsądnym tłumaczonym językiem, szczególnie do użytku w sieci. Jest powód, dla którego firmy takie jak Facebook korzystają z niego. Ale ponieważ jest dostępny wszędzie, amatorski zestaw używa go w szerokim zakresie, co szkodzi reputacji.
Orbling

5

Tak, są leniwi. W każdym razie wiele z nich ...

Niestety mentalność wielu programistów PHP brzmi: „Nie ma sensu kodować defensywnie, jeśli można uzyskać ten sam rezultat końcowy szybciej, polegając na języku do obsługi błędów spowodowanych brakującymi zmiennymi itp.” Wiem, pracowałem z kilkoma z nich.

Są też tymi, którzy w tajemniczy sposób udają się na wczesny lunch, gdy ich brak prawidłowej obsługi błędów i raportowania usuwa serwery na żywo na kilka godzin ...


5
-1 za subiektywną opinię na temat koderów PHP.
Josh K

4
@Josh, będąc starszym programistą PHP od 4 1/2 lat i kodując PHP z przerwami od 1999 roku, obawiam się, że jestem nieco subiektywny. Powinienem był zakwalifikować się z „Z drugiej strony, bardziej doświadczeni koderzy PHP nie są leniwi i robią wszystko poprawnie” ...
Gruffputs

1
To powinieneś mieć.
Josh K

5

Staram się unikać używania isset () i empty (), unikając używania tablic jako obiektów do przesyłania danych. Utwórz klasę, którą można skonfigurować tak, aby akceptowała ograniczony zestaw właściwości z rozsądnymi wartościami domyślnymi i sprawdzała poprawność danych wejściowych dla tych właściwości. Może nawet zaimplementować interfejs ArrayAccess, dzięki czemu można go używać jak z tablicy. Pozwala to również na użycie podpowiedzi typu w podpisach metod w celu wychwycenia błędów, gdy ktoś próbuje przekazać do metody niewłaściwy typ encji.


Bardzo ciekawe podejście.
Toby

2

Jedno z zadawanych pytań jest moje, więc powtórzę.

Wielu programistów myli obecność wielu isset()jako znaku jakości. Daje wrażenie niezawodności, a niektórzy uważają to nawet za zabezpieczenie.

Musisz jednak wziąć pod uwagę, że PHP nie jest językiem skompilowanym. Jest to język skryptowy z dynamicznym systemem typów. Błędy E_NOTICE to tylko błędy z nazwy. A jeśli wiele z nich issetjest używanych wyłącznie w celu zlikwidowania powiadomień, to tak naprawdę po prostu kodujesz przeciwko językowi .

Czy więc deweloperzy PHP są po prostu leniwi?

Tak jest rzeczywiście w przypadku, gdy pojawi się mnóstwo powiadomień i ostrzeżeń. Wielu początkujących nie przejmuje się powiadomieniami i zwykle jest to wynikiem całkowicie wyłączonego error_reporting(0).

Mylisz się jednak, że inni programiści nie rozpoznawali E_NOTICE tylko dlatego, że nie byli @ ani tłumieni. Przynajmniej taka była moja intencja stojąca za pytaniem dotyczącym zatrzymujących powiadomień . Nie są czymś, czego można się pozbyć, ale czasami ważne informacje debugowania.

Jak wszystkie uogólnienia, nierozważne użycie isset nie prowadzi do optymalnego kodu. Ważne jest, aby odróżnić, gdzie isseti gdzie emptysą potrzebne, i gdzie są one składnią soli .

Czy jest to wyłącznie kwestia dotycząca kultury PHP?

Nie, niezdefiniowane „błędy” zmiennych nie są samym problemem PHP. Bash, TCL i Perl lub JavaScript pozwalają na użycie niezdefiniowanych zmiennych. Ta funkcja języka immanentnego nie jest jednak postrzegana jako wada. Istnieją podobne konstrukcje językowe do sprawdzania nieokreślonych wartości. Jednak nie są one tak często używane jak w PHP, ponieważ wartości undef nie są błędnie określane jako „błąd”.


1

Ciekawy. Prawie nigdy nie używam isset (). Mój kod PHP rzadko znajduje się w stanie, w którym nie wiem, czy zmienna została ustawiona w pierwszej kolejności. Dostęp do każdej użytej zmiennej GET lub POST można uzyskać za pomocą funkcji, która zapewni jej wartość domyślną, jeśli nie istnieje. Domyślne wartości w wywołaniach funkcji są zazwyczaj jawnie ustawione na 0 lub puste ciągi.


+1. Przekazywanie do funkcji lub metody klasowej jest dobrym rozwiązaniem. I faktycznie NIE to zrobić, ale w kropce moje powyższe przykłady nadal wyglądało na czyste i nie-nadęty do mnie.
Stephen

0

Używam isset i pustej ilości. Ale głównie są to miejsca, o których wspominasz, na przykład przetwarzanie $ _REQUEST, na wypadek, gdyby ktoś bałaganił parametry. W przypadkach, w których mam kontrolę nad wszystkimi zmiennymi latającymi, okazuje się, że zwykle ich nie potrzebuję.


0

Nie lubię używać isset, ale jeśli jest mnóstwo mas wykonanych przez inny kod, może to być oszczędność. Napisałem poniższy kod wee, aby pomóc w rozwiązaniu tego problemu, zamiast używania isset () isseter ($ a, $ b) zwróci $ b, jeśli $ a nie jest zdefiniowane lub puste, lub funkcja zwraca wartość null. Wszelkie ulepszenia, mile widziane:

//returns var or NULL (if undefined)
//$reserve optional second value is returned as $default if undefined
function isseter(&$default,&$reserve=NULL)
{
$default = isset($default) ? $default : NULL;
$reserve = isset($reserve) ? $reserve : NULL;
if ((!$default) && ($reserve)) $default=$reserve;
return $default;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.