Czy dobrą praktyką jest wdrażanie bezużytecznej obsługi wyjątków, na wypadek, gdyby inna część kodu nie została poprawnie zakodowana?
Podstawowy przykład
Prosty, więc nie tracę wszystkich :).
Powiedzmy, że piszę aplikację, która wyświetli informacje o osobie (imię i nazwisko, adres itp.), Dane zostaną wyodrębnione z bazy danych. Powiedzmy, że to ja koduję część interfejsu użytkownika, a ktoś inny pisze kod zapytania DB.
Teraz wyobraź sobie, że specyfikacje Twojej aplikacji mówią, że jeśli dane osoby są niekompletne (powiedzmy, że brakuje nazwy w bazie danych), osoba kodująca zapytanie powinna to obsłużyć, zwracając „NA” dla brakującego pola.
Co jeśli zapytanie jest źle zakodowane i nie obsługuje tego przypadku? Co jeśli facet, który napisał zapytanie, poradzi sobie z niekompletnym wynikiem, a gdy spróbujesz wyświetlić informacje, wszystko się zawiesi, ponieważ twój kod nie jest przygotowany do wyświetlania pustych rzeczy?
Ten przykład jest bardzo prosty. Wierzę, że większość z was powie „to nie jest twój problem, nie jesteś odpowiedzialny za tę awarię”. Ale to wciąż twoja część kodu ulega awarii.
Inny przykład
Powiedzmy teraz, że to ja piszę zapytanie. Specyfikacje nie mówią tego samego, co powyżej, ale że facet piszący zapytanie „wstaw” powinien upewnić się, że wszystkie pola są wypełnione podczas dodawania osoby do bazy danych, aby uniknąć wstawienia niepełnych informacji. Czy powinienem chronić moje zapytanie „wybierz”, aby upewnić się, że przekazuję facetowi interfejsu użytkownika pełne informacje?
Pytania
Co się stanie, jeśli specyfikacje nie mówią wprost „ten facet jest odpowiedzialny za poradzenie sobie z tą sytuacją”? Co się stanie, jeśli osoba trzecia zaimplementuje inne zapytanie (podobne do pierwszego, ale na innym DB) i użyje twojego kodu interfejsu użytkownika, aby go wyświetlić, ale nie obsługuje tego przypadku w swoim kodzie?
Czy powinienem zrobić wszystko, co konieczne, aby zapobiec możliwej awarii, nawet jeśli to nie ja mam zająć się złym przypadkiem?
Nie szukam odpowiedzi typu „on (on) jest odpowiedzialny za awarię”, ponieważ nie rozwiązuję tutaj konfliktu, chciałbym wiedzieć, czy powinienem chronić swój kod przed sytuacjami, to nie moja odpowiedzialność Poradzić sobie? Tutaj wystarczyłoby proste „jeśli coś pustego zrobić”.
Zasadniczo to pytanie dotyczy zbędnej obsługi wyjątków. Pytam o to, ponieważ kiedy pracuję sam nad projektem, mogę kodować 2-3 razy podobną obsługę wyjątków w kolejnych funkcjach, „na wszelki wypadek” zrobiłem coś złego i przepuściłem zły przypadek.
Odpowiedzi:
Mówisz tutaj o granicach zaufania . Czy ufasz granicy między aplikacją a bazą danych? Czy baza danych ufa, że dane z aplikacji są zawsze wstępnie sprawdzane?
Jest to decyzja, która musi być podjęta w każdej aplikacji i nie ma dobrych i złych odpowiedzi. Zwykle mylę się po stronie nazwania zbyt wielu granic granicą zaufania, inni programiści z radością ufają interfejsom API innych firm, aby robili to, czego oczekujesz, przez cały czas, za każdym razem.
źródło
Zasada solidności „Bądź konserwatywny w tym, co wysyłasz, bądź liberalny w tym, co akceptujesz” jest tym, czego szukasz. Jest to dobra zasada - EDYCJA: dopóki jej aplikacja nie ukrywa poważnych błędów - ale zgadzam się z @pdr, że zawsze zależy od sytuacji, czy powinieneś ją zastosować, czy nie.
źródło
To zależy od tego, co testujesz; ale załóżmy, że zakresem twojego testu jest tylko twój własny kod. W takim przypadku powinieneś przetestować:
W tym celu nie można użyć komponentu kolegi: zamiast tego należy użyć kpiny , czyli zastąpić resztę aplikacji „fałszywymi” modułami, którymi można sterować z poziomu środowiska testowego. To, jak dokładnie to zrobisz, zależy od sposobu interfejsu modułów; wystarczy po prostu wywołać metody modułu z zakodowanymi na stałe argumentami i może stać się tak skomplikowane, jak napisanie całego frameworka, który łączy publiczne interfejsy innych modułów ze środowiskiem testowym.
Ale to tylko przypadek testu jednostkowego. Chcesz także testów integracyjnych, w których wszystkie moduły będą testowane wspólnie. Ponownie, chcesz przetestować zarówno szczęśliwy przypadek, jak i niepowodzenia.
W przypadku „Podstawowego przykładu”, aby przetestować kod w jednostce, napisz próbną klasę, która symuluje warstwę bazy danych. Twoja próbna klasa tak naprawdę nie trafia do bazy danych: po prostu wstępnie załaduj ją oczekiwanymi danymi wejściowymi i stałymi danymi wyjściowymi. W pseudokodzie:
A oto jak przetestowałbyś brakujące pola, które są poprawnie zgłaszane :
Teraz sprawy stają się interesujące. Co się stanie, jeśli prawdziwa klasa DB zachowa się źle? Na przykład może zgłosić wyjątek z niejasnych powodów. Nie wiemy, czy tak, ale chcemy, aby nasz własny kod obsługiwał go z wdziękiem. Nie ma problemu, wystarczy, że nasz MockDB zgłosi wyjątek, np. Dodając taką metodę:
A potem nasz przypadek testowy wygląda następująco:
To są twoje testy jednostkowe. Do testu integracji nie używasz klasy MockDB; zamiast tego łączysz obie rzeczywiste klasy razem. Nadal potrzebujesz osprzętu; na przykład przed uruchomieniem testu należy zainicjować testową bazę danych do znanego stanu.
Teraz, jeśli chodzi o zakres obowiązków: Twój kod powinien oczekiwać, że reszta bazy kodu zostanie zaimplementowana zgodnie ze specyfikacją, ale powinna być również przygotowana do obsługi z wdziękiem, gdy reszta się psuje. Nie jesteś odpowiedzialny za testowanie inny kod niż własną rękę, ale ty jesteś odpowiedzialny za swój kod odporne na niewłaściwie kod na drugim końcu, a ty jesteś odpowiedzialny za testowanie odporności na kodzie. Tak właśnie działa trzeci test powyżej.
źródło
Istnieją 3 główne zasady, które staram się kodować:
SUCHY
POCAŁUNEK
YAGNI
Pominięcie tych wszystkich polega na tym, że ryzykujesz pisanie kodu weryfikacyjnego, który jest powielany w innym miejscu. Jeśli reguły sprawdzania poprawności ulegną zmianie, należy je zaktualizować w wielu miejscach.
Oczywiście, w pewnym momencie w przyszłości, to może replatform bazy danych (zdarza się), w którym to przypadku można by pomyśleć o kod w więcej niż jednym miejscu byłoby korzystne. Ale ... piszesz coś, co może się nie wydarzyć.
Każdy dodatkowy kod (nawet jeśli nigdy się nie zmienia) jest narzutem, ponieważ będzie musiał zostać napisany, odczytany, zapisany i przetestowany.
Wszystkie powyższe informacje są prawdą, dlatego niedopuszczalne byłoby, abyś nie dokonywał żadnej weryfikacji. Aby wyświetlić pełną nazwę w aplikacji, potrzebujesz podstawowych danych - nawet jeśli nie zweryfikujesz samych danych.
źródło
Słowami laika.
Nie ma czegoś takiego jak „baza danych” lub „aplikacja” .
Jeszcze raz:
źródło