2012-03-08 12 views
6

Ostatnio dodawałem asserts do niemal każdej funkcji, którą robię, aby sprawdzić każde dane wejściowe jako rodzaj zamiennika dla osoby biednej w celu sprawdzenia typu lub aby zapobiec przypadkowemu wprowadzeniu zniekształconych danych podczas rozwijania. Na przykład,Czy możesz mieć zbyt wiele assertów (w języku Python)?

def register_symbol(self, symbol, func, keypress=None): 
    assert(isinstance(symbol, basestring)) 
    assert(len(symbol) == 1) 
    assert(callable(func)) 
    assert(keypress is None or type(keypress) is int) 
    self.symbols_map[symbol] = (func, keypress) 
    return 

Jednak obawiam się, że to sprzeczne z ideą kaczka wpisywanie, i że może być zbyt dzieje burtę lub zwężania się niepotrzebnie. Czy możesz mieć kiedykolwiek zbyt wiele twierdzeń? Kiedy jest dobry czas, aby przestać?

+0

Nota boczna: Powinieneś używać pisania kaczkami (nie sprawdzaj typu, sprawdź "zdolności" jak dostępne metody). Również, że 'return' jest całkowicie niepotrzebny. –

+1

Prawdziwe pytanie brzmi: czy to ci pomaga, czy też utrudnia pracę. Jeśli wiele zapewnień pomoże Ci śledzić błędy - zrób dużo potwierdzeń w swoim kodzie. Jeśli potrzebujesz statycznego pisania, dlaczego wybrałeś Python do swojego projektu? –

+3

@Niklas Podoba mi się jednak powrót. To mnie uszczęśliwia w środku: D – Michael0x2a

Odpowiedz

7

Używam tylko assert s, jeśli zapewniają one o wiele lepszą diagnostykę niż komunikaty o błędach, które w przeciwnym razie wystąpiłyby. Twój trzeci assert

assert(callable(func)) 

może być przykładem dla takiego assert - jeśli func nie jest wymagalne, otrzymasz komunikat o błędzie w zupełnie innej linii kodu niż gdzie rzeczywisty błąd jest i nie może być oczywiste, jak nieopłacalny obiekt zakończył się w self.symbols_map. Piszę "może", ponieważ zależy to od reszty kodu - jeśli jest to jedyne miejsce, w którym self.symbols_map zostaje zaktualizowany, asembler może być niepotrzebny.

Pierwszy i ostatni stwierdzenie zdecydowanie są sprzeczne z ideą kaczki, , a drugi jest zbędny. Jeśli symbol nie jest łańcuchem o długości 1, istnieje prawdopodobieństwo, że self.symbols_map[symbol] podniesie wartość KeyError, więc nie będzie potrzeby stosowania znaków.

Ostatnia twierdzenie również jest błędne - type(keypress) nie może być None, a kontrole typu powinny być wykonywane z isinstance(). Mogą istnieć bardzo wyspecjalizowane aplikacje, w których nie można dopuścić podtypów, ale kontrola powinna być przeprowadzona z type(x) is int zamiast z type(x) == int. Sprawdzenie dla None powinno być wykonane przez x is None, a nie przez type(x) is NoneType.

Powinieneś prawdopodobnie napisać dobry zestaw testów jednostkowych - będą one znacznie bardziej użyteczne niż twierdzenia i mogą sprawić, że prawie wszystkie twoje zapewnienia będą zbędne.

+0

Ups, przepraszam. Poprawię ostatni dowód. – Michael0x2a

+0

Hm, jeśli 'symbols_map' jest dyktando, nie powinno wywoływać' KeyError'. –

+0

@NiklasB .: Czy możesz wyjaśnić to nieco dalej? –

3

Potwierdzenia w kodzie nie są tak przydatne, jak emisje. Zrób więcej tego ostatniego, mniej tego pierwszego.

2

Należy pamiętać, że instrukcje assert są usuwane, gdy Python generuje zoptymalizowany kod bajtowy! Ponieważ tak jest w większości środowisk produkcyjnych, instrukcje assert nie mogą być używane do sprawdzania danych wejściowych. W rzeczywistości doszedłem do wniosku, że nie mogę ich w ogóle użyć do niczego, jeśli nie mogę polegać na ich egzekucji. Więc jeśli potrzebuję sprawdzić jakiś warunek, zamiast tego używam "jeśli ... podnieś ...", a jeśli chcę tylko przetestować mój kod, piszę unittests.

Powiązane problemy