Współpracownik kilka razy dodał polecenie assert w naszych bibliotekach w miejscach, w których użyłbym instrukcji if i wyrzucił wyjątek. (Nigdy wcześniej nie słyszałem o twierdzeniu). Oto przykład, jak go użył:
assert('isset($this->records); /* Records must be set before this is called. */');
Zrobiłbym:
if (!isset($this->records)) {
throw new Exception('Records must be set before this is called');
}
Po przeczytaniu dokumentacji PHP na temat assert wygląda na to, że zaleca się upewnienie się, że funkcja assert jest aktywna i dodanie obsługi przed użyciem assert. Nie mogę znaleźć miejsca, w którym to zrobił.
Więc moje pytanie brzmi, czy użycie assert jest dobrym pomysłem, biorąc pod uwagę powyższe i czy powinienem używać go częściej niż jeśli i wyjątki?
Kolejna uwaga, planujemy używać tych bibliotek w różnych projektach i serwerach, w tym w projektach, których być może nawet nie jesteśmy częścią (biblioteki są open source). Czy to ma znaczenie w używaniu assert?
'isset
(wiersz kodu zassert
)? Nie tylkoisset
(bez pojedynczego cudzysłowu'
)?Odpowiedzi:
Praktyczna zasada, która ma zastosowanie w większości języków (wszystko, co niejasno wiem) jest taka
assert
, że warunek jest używany do stwierdzenia, że warunek jest zawsze prawdziwy, podczas gdy warunekif
jest odpowiedni, jeśli można sobie wyobrazić, że czasami zawiedzie.W tym przypadku powiedziałbym, że
assert
jest to właściwe (kierując się moim słabym zrozumieniem sytuacji), ponieważ zawszerecords
powinno być ustawione przed wywołaniem danej metody. Tak więc niepowodzenie w ustawieniu rekordu byłoby raczej błędem w programie niż warunkiem wykonania. W tym przypadku pomaga zapewnić (przy odpowiednim testowaniu), że nie ma możliwej ścieżki wykonania programu, która mogłaby spowodować, że kod, który jest chroniony za pomocą elementu, zostanie wywołany bez wcześniejszego ustawienia.assert
assert
records
Zaletą używania
assert
w przeciwieństwie doif
tego jest to, żeassert
można go ogólnie wyłączyć w kodzie produkcyjnym, zmniejszając w ten sposób narzut. Tego rodzaju sytuacje, z którymi najlepiej sobieif
radzi, mogą prawdopodobnie wystąpić podczas pracy w systemie produkcyjnym, więc nie można ich wyłączyć, nic tracąc.źródło
assert_options(ASSERT_BAIL)
. Jest to i tak szybsze niż ręczne obejście if / throw.Pomyśl o zapewnieniach jako o „komentarzach władzy”. Zamiast komentarza takiego jak:
// Note to developers: the parameter "a" should always be a number!!!
posługiwać się:
assert('is_numeric(a) /* The parameter "a" should always be a number. */');
Znaczenia są dokładnie takie same i są przeznaczone dla dokładnie tej samej publiczności, ale pierwszy komentarz jest łatwo zapomniany lub zignorowany (bez względu na to, ile wykrzykników), podczas gdy „komentarz mocy” jest dostępny nie tylko dla ludzi do przeczytania i zrozumienia, jest również stale testowany maszynowo podczas opracowywania i nie zostanie zignorowany, jeśli skonfigurujesz dobrą obsługę asercji w kodzie i nawykach pracy.
Widziane w ten sposób twierdzenia są zupełnie inną koncepcją niż gdyby (błąd) ... i wyjątkami, i mogą współistnieć.
Tak, powinieneś komentować swój kod i tak, powinieneś używać „power comments” (potwierdzenia), kiedy tylko jest to możliwe.
źródło
Zależy to całkowicie od Twojej strategii rozwoju. Większość programistów nie zdaje sobie sprawy z
assert()
testów jednostkowych podrzędnych i stosuje je. Ale proaktywne i wbudowane schematy testowania mogą czasami być korzystne.assert jest przydatne, ponieważ można je włączać i wyłączać. Nie obniża wydajności, jeśli nie zdefiniowano takiej obsługi potwierdzeń. Twój kolega go nie ma i powinieneś opracować jakiś kod, który tymczasowo włącza go w środowisku programistycznym (jeśli E_NOTICE / E_WARNINGs są włączone, więc powinien być program obsługi asercji). Używam go od czasu do czasu, gdy mój kod nie może znieść mieszanych typów zmiennych - zwykle nie angażuję się w ścisłe pisanie w słabo wpisanym PHP, ale są przypadkowe przypadki użycia:
function xyz($a, $b) { assert(is_string($a)); assert(is_array($b));
Co na przykład zrekompensowałoby brak specyfikatorów typu
string $a, array $b
. PHP5.4 będzie je obsługiwać, ale nie będzie sprawdzać.źródło
Assert nie zastępuje normalnej kontroli przepływu, takiej jak
if
lub wyjątków, ponieważ jest przeznaczona tylko do debugowania podczas programowania.źródło
Ważna uwaga dotycząca assert w PHP wcześniejszych niż 7. W przeciwieństwie do innych języków z konstrukcją assert, PHP nie wyrzuca całkowicie instrukcji assert - traktuje je jako funkcję (wykonaj debug_backtrace () w funkcji wywoływanej przez asercję). Wyłączenie potwierdzeń wydaje się po prostu przekręcać funkcję tak, aby nie robiła nic w silniku. Zauważ, że PHP 7 można zmusić do emulacji tego zachowania, ustawiając zend.assertions na 0 zamiast bardziej normalnych wartości 1 (włączone) lub -1 (wyłączone).
Problem pojawia się w tym, że assert przyjmie dowolny argument - ale jeśli argument nie jest łańcuchem, wtedy assert pobiera wyniki wyrażenia, niezależnie od tego, czy assert jest włączony, czy wyłączony. Możesz to zweryfikować za pomocą następującego bloku kodu.
<?php function foo($a) { echo $a . "\n"; return TRUE; } assert_options(ASSERT_ACTIVE, FALSE); assert( foo('You will see me.')); assert('foo(\'You will not see me.\')'); assert_options(ASSERT_ACTIVE, TRUE); assert( foo('Now you will see')); assert('foo(\'both of us.\')');
Biorąc pod uwagę zamiar assert, jest to błąd, i to od dawna, odkąd pojawił się w tym języku od czasu wprowadzenia assert w PHP 4.
Ciągi przekazywane do assert są poddawane ocenie, ze wszystkimi implikacjami wydajnościowymi i niebezpieczeństwami, które się z tym wiążą, ale jest to jedyny sposób, aby instrukcje assert działały tak, jak powinny w PHP (to zachowanie jest przestarzałe w PHP 7.2).
EDYCJA: Zmieniono powyżej, aby odnotować zmiany w PHP 7 i 7.2
źródło
zend.assertions
ustawienie ini, aby całkowicie wyłączyćassert()
.Assert należy używać tylko w programowaniu, ponieważ jest przydatne do debugowania. Więc jeśli chcesz, możesz ich użyć do rozwijania swojej witryny, ale powinieneś używać wyjątków dla działającej witryny.
źródło
Nie, Twój współpracownik nie powinien używać go do obsługi błędów ogólnego przeznaczenia. Zgodnie z instrukcją:
Jeśli jesteś zaznajomiony z automatycznymi zestawami testów, czasownik „assert” jest zwykle używany do weryfikacji wyniku jakiejś metody lub funkcji. Na przykład:
function add($a, $b) { return $a + $b; } assert(add(2,2) == 5, 'Two and two is four, dummy!'); assert(is_numeric(add(2,2)), 'Output of this function to only return numeric values.');
Twój współpracownik nie powinien używać go do obsługi błędów ogólnego przeznaczenia, aw tym przypadku do sprawdzania danych wejściowych. Wygląda na to, że pole rekordów nie zostało ustawione przez jakiegoś użytkownika biblioteki.
źródło
Twój współpracownik naprawdę próbuje zastosować projekt na podstawie umowy (DbC) z języka Eiffla i na podstawie książki: Object Oriented Software Construction, 2nd Edition.
Stwierdzenie, jak go użył, byłoby {P} -częścią Hoare Logic lub Hoare Triple: {P} C {Q}, gdzie {P} jest asertem (jonami) warunku wstępnego i {Q} są asercja (jon) warunku końcowego.
Chciałbym wziąć krytyczną uwagę na porady dotyczące funkcji assert w PHP zawierającej błędy. Nie chcesz używać błędnego kodu. To, czego naprawdę chcesz, to twórcy PHP, aby naprawić błąd w asercie. Dopóki tego nie zrobią, możesz używać potwierdzenia, ale używaj go, pamiętając o jego obecnym stanie błędnym.
Ponadto, jeśli funkcja assert zawiera błędy, sugeruję, aby nie używać jej w kodzie produkcyjnym. Niemniej jednak zalecam używanie go w razie potrzeby podczas programowania i testowania kodu.
Wreszcie - jeśli przeanalizujesz projekt na podstawie kontraktu, przekonasz się, że stosowanie twierdzeń boolowskich w świetle klasycznego dziedziczenia zorientowanego obiektowo - to znaczy - nigdy nie wolno osłabiać warunku wstępnego ani warunku końcowego. Może to być niebezpieczne dla twoich polimorficznych obiektów potomnych oddziałujących ze sobą. Dopóki nie zrozumiesz, co to znaczy - zostawię to w spokoju!
Co więcej - bardzo polecam twórcom PHP dokładne zbadanie projektu na zlecenie i próbę umieszczenia go w PHP jak najszybciej! Wtedy każdy z nas może skorzystać na posiadaniu kompilatora / interpretera obsługującego DbC, który poradziłby sobie z problemami wymienionymi w odpowiedziach (powyżej):
UWAGA: Nawet użycie oświadczenia
if
jako substytutu potwierdzenia (warunku wstępnego) będzie miało tragiczne konsekwencje, jeśli zostanie użyte do wzmocnienia warunku wstępnego lub osłabienia warunku końcowego. Aby zrozumieć, co to oznacza, musisz przestudiować projektowanie na podstawie umowy, aby wiedzieć! :-)Miłej nauki i nauki.
źródło