Zastanawiam się nad tym zagadnieniem od dłuższego czasu i byłbym ciekawy opinii innych programistów.
Mam tendencję do bardzo defensywnego stylu programowania. Mój typowy blok lub metoda wygląda następująco:
T foo(par1, par2, par3, ...)
{
// Check that all parameters are correct, return undefined (null)
// or throw exception if this is not the case.
// Compute and (possibly) return result.
}
Ponadto podczas obliczania sprawdzam wszystkie wskaźniki przed ich odwołaniem. Mój pomysł jest taki, że jeśli jest jakiś błąd i jakiś wskaźnik NULL powinien się gdzieś pojawić, mój program powinien sobie z tym poradzić i po prostu odmówić kontynuowania obliczeń. Oczywiście może powiadomić o problemie z komunikatem o błędzie w dzienniku lub innym mechanizmie.
Mówiąc bardziej abstrakcyjnie, moje podejście jest takie
if all input is OK --> compute result
else --> do not compute result, notify problem
Inni programiści, w tym moi koledzy, używają innej strategii. Np. Nie sprawdzają wskaźników. Zakładają, że fragment kodu powinien mieć poprawne dane wejściowe i nie powinien być odpowiedzialny za to, co się stanie, jeśli dane wejściowe są nieprawidłowe. Ponadto, jeśli wyjątek wskaźnika NULL spowoduje awarię programu, błąd zostanie łatwiej znaleziony podczas testowania i będzie miał większe szanse na naprawienie.
Moja odpowiedź na to pytanie jest normalna: ale co jeśli błąd nie zostanie wykryty podczas testowania i pojawi się, gdy produkt będzie już używany przez klienta? Jaki jest preferowany sposób ujawnienia się błędu? Czy powinien to być program, który nie wykonuje określonej czynności, ale może nadal działać, czy program, który ulega awarii i wymaga ponownego uruchomienia?
Zreasumowanie
Które z dwóch podejść do obsługi niewłaściwych danych wejściowych doradziłbyś?
Inconsistent input --> no action + notification
lub
Inconsistent input --> undefined behaviour or crash
Edytować
Dziękuję za odpowiedzi i sugestie. Jestem również fanem projektowania na podstawie umowy. Ale nawet jeśli ufam osobie, która napisała kod wywołujący moje metody (być może to jestem ja), nadal mogą występować błędy, które prowadzą do błędnych danych wejściowych. Więc moim podejściem jest, aby nigdy nie zakładać, że metoda została poprawnie przesłana.
Ponadto użyłbym mechanizmu, aby złapać problem i powiadomić o nim. W systemie programistycznym np. Otwiera okno dialogowe, aby powiadomić użytkownika. W systemie produkcyjnym po prostu zapisuje pewne informacje w dzienniku. Nie sądzę, że dodatkowe kontrole mogą prowadzić do problemów z wydajnością. Nie jestem pewien, czy stwierdzenia są wystarczające, czy są wyłączone w systemie produkcyjnym: być może wystąpi jakaś sytuacja w produkcji, która nie wystąpiła podczas testowania.
W każdym razie byłem naprawdę zaskoczony, że wiele osób postępuje w odwrotny sposób: pozwalają aplikacji na awarię „celowo”, ponieważ utrzymują, że ułatwi to znalezienie błędów podczas testowania.