Czy konwencjonalne jest zgłaszanie błędu NotImplementedError dla metod, których wdrożenie jest w toku, ale nie jest planowane jako abstrakcyjne?

34

Lubię podnosić NotImplementedErrormetodę, którą chcę wdrożyć, ale tam, gdzie jeszcze się nie udało. Mogę już mieć częściową implementację, ale dodaj ją, raise NotImplementedError()ponieważ jeszcze jej nie lubię. Z drugiej strony lubię też przestrzegać konwencji, ponieważ ułatwi to innym osobom utrzymanie mojego kodu, a konwencje mogą istnieć z dobrych powodów.

Jednak dokumentacja Python dla NotImplementedError stwierdza:

Ten wyjątek pochodzi od RuntimeError. W klasach podstawowych zdefiniowanych przez użytkownika metody abstrakcyjne powinny zgłaszać ten wyjątek, gdy wymagają klas pochodnych w celu zastąpienia metody.

Jest to o wiele bardziej konkretny, formalny przypadek użycia niż ten, który opisuję. Czy to dobry, konwencjonalny styl, aby podnieść NotImplementedErrorpo prostu, aby wskazać, że ta część interfejsu API jest w toku? Jeśli nie, to czy istnieje inny znormalizowany sposób na wskazanie tego?

gerrit
źródło
Co rozumiesz przez „odpowiedni”?
Robert Harvey
1
@RobertHarvey Przypuszczam, że mam na myśli konwencjonalne, po powszechnym użyciu. Teraz sformułowałem moje pytanie.
gerrit
1
Używamy tutaj C #, ale ten typ zgłaszania wyjątków jest tutaj idiomatyczny i spodziewałbym się gdzie indziej. Przerwij wcześnie i przerwij głośno to dobra wskazówka do szybkiego identyfikowania potencjalnych problemów (czytaj: niedrogo).
Telastyn
Ogólnie, jeśli tworzę klasę, po prostu umieszczam komentarze TODO w niezaimplementowanych metodach, dopóki nie zacznę implementować tej funkcjonalności. Gdyby klasa miała zostać dopuszczona do produkcji, zanim to się stanie, rozważyłbym wprowadzenie wyjątków.
5
Jeśli chodzi o to, co jest warte, to właśnie robi Microsoft Visual Studio domyślnie, gdy używasz IDE do „implementacji interfejsu”. Według Roberta Harveya wynik jest dobrze zrozumiany.
catfood

Odpowiedzi:

34

Warto zauważyć, że chociaż dokumentacja Pythona zawiera przypadek użycia (i prawdopodobnie kanoniczny) dla tego wyjątku, nie wyklucza on wyraźnie jego zastosowania w innych scenariuszach.

Uznałbym za stosowne zgłoszenie wyjątku NotImplementedError, jeśli nie przesłano jeszcze metody w klasie bazowej (aby spełnić „interfejs”).

Pobieżna kontrola w Google sugeruje, że ludzie zrozumieją, co masz na myśli, jeśli zastosujesz wyjątek w ten sposób. Nie znam żadnych skutków ubocznych ani niezamierzonych konsekwencji; metoda po prostu wyrzuci wyjątek, jeśli zostanie wywołany, i wyrzuci wyjątek, który jest dobrze zrozumiały dla wszystkich.


Dokumentacji dla Pythona 3 odzwierciedla dokładnie ten wykorzystania:

W klasach podstawowych zdefiniowanych przez użytkownika metody abstrakcyjne powinny zgłaszać ten wyjątek, gdy wymagają klas pochodnych w celu zastąpienia metody lub podczas opracowywania klasy w celu wskazania, że ​​należy jeszcze dodać rzeczywistą implementację . [Podkreślenie dodane]

Robert Harvey
źródło
+1, ale dodam też, że w przypadku tego rodzaju konwencji trochę dokumentacji może przejść długą drogę. Jak notatka w jednym wierszu na wiki dla programistów, repozytorium readme lub wytyczne dotyczące stylu - coś w tym rodzaju - wyjaśniające, do czego używasz tego wyjątku.
Ben Lee,
8

Będzie to zrozumiałe, niezależnie od tego, czy to zrobisz, czy nie, powinno to zależeć od lokalnych konwencji (zespołu lub firmy). Zauważ, że ma to mniej sensu w kontekście TDD, ponieważ TEST powinien określać, że metoda nie jest zaimplementowana.

Krótka wersja to: użyj, jeśli Ty i Twój zespół uznacie to za właściwe.

jmoreno
źródło
5
FWIW, Zgłoszenie wyjątku powinno być dobrym sposobem na niepowodzenie testu, jeśli z jakiegoś powodu musisz wymusić takie zachowanie. (
Przydałoby się to
1

Wygląda na NotImplementedErrorto, że zwykle jest podnoszony dla samego rozwoju funkcji Pythona, jak poniżej:

@classmethod
def fromkeys(cls, iterable, v=None):
    # There is no equivalent method for counters because setting v=1
    # means that no element can have a count greater than one.
    raise NotImplementedError(
        'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')

Dokumentacja

fromkeys (iterable)

Ta metoda klasy nie jest zaimplementowana dla obiektów Counter.

Źródło

Collections.Counter.fromkeys

Emma
źródło