2012-06-02 9 views
5

Mam na myśli najlepsze praktyki kontroli przepływu. Którą drogą mam iść?Sterowanie przepływem ruby: wyrzuć wyjątek, wróć do zera lub pozwól mu zawieść?

1) Nie zaznaczaj niczego i niech program nie (czystsze kod, naturalne komunikaty o błędach):

def self.fetch(feed_id) 
    feed = Feed.find(feed_id) 
    feed.fetch 
    end 

2) Fail cicho wracając nil (jednak "Clean Code", mówi, że ciebie nigdy nie powinien powrócić null):

def self.fetch(feed_id) 
    return unless feed_id 
    feed = Feed.find(feed_id) 
    return unless feed 
    feed.fetch 
    end 

3) generują wyjątki (bo to wyjątkowy nie znaleźć paszę przez ID):

def self.fetch(feed_id) 
    raise ArgumentError.new unless feed_id 
    feed = Feed.find(feed_id) 
    raise ArgumentError.new unless feed 
    feed.fetch 
    end 

Innymi słowy: czy powinienem aktywnie korzystać z warunków ochronnych, czy lepiej polegać na metodach Ruby/Rails i pozwolić im rzucić wyjątek, jeśli coś złego się dzieje?

+1

jeśli to ActiveRecord, 'find' będzie dmuchać, jeśli' id' nie istnieje, 'find_by_id' nie wieje. – tokland

Odpowiedz

6

1) Nie zaznaczaj niczego i niech program nie (czystsze kod, naturalne komunikaty o błędach):

to OK, aby "pozwolić programowi fail" ze znanymi udokumentowanych wyjątkami, ale uzyskanie nieprzyjemnego NoMethodError, ponieważ próbujesz użyć obiektu nil jest po prostu nieostrożne. W danym przykładzie ActiveRecord#find podnosi udokumentowany ActiveRecord::RecordNotFound wyjątek, więc IMO jest to do zrobienia:

def self.fetch(feed_id) 
    Feed.find(feed_id).fetch 
end 

2) Fail cicho wracając zero ("Clean Code", mówi jednak, że zalecana never return null):

To dobra ogólna wskazówka, ale Ruby jest zapchany metodami, które zwracają nil; i to jest w porządku (znowu, o ile jest to udokumentowane), oznacza to po prostu "Nic" (i pozwala na bardzo kompaktowy wzór something_that_can_be_nil || another_value). W tym przypadku będę pisać zwięźle użyciu Ick na maybe:

def self.fetch(feed_id) 
    Feed.find_by_id(feed_id).maybe.fetch 
end 

3) generują wyjątki (bo to wyjątkowy nie znaleźć paszę przez ID):

Tak, ale potem niech metoda podniesie znany wyjątek RecordNotFound, a nie niestandardowy (chyba, że ​​chcesz abstrahować fakt, że pracujesz z AR, co może być bardzo uciążliwe).

2

Myślę, że właściwą odpowiedzią jest: to zależy. Użytkownik teoretycznie nigdy nie powinien napotykać żadnego komunikatu o błędzie z frameworka. Musisz zawsze być przygotowany na te wyjątki. Wybór należy do Ciebie (jeśli nie jest to zewnętrzny interfejs lub coś takiego).

Jeśli zdecydujesz się na pierwszą trasę, myślę, że powinieneś zapytać, czy istnieje jakikolwiek plik danych z tym identyfikatorem, a następnie spróbuj go pobrać. Jeśli kanał zniknie między tymi dwoma, może to być prawdziwy problem do zgłoszenia. Trzeci jest w zasadzie taki sam. Musisz upewnić się, że załatwiłeś każdą sytuację, a w tym wyjątku rzucania możesz zapobiec wyświetlaniu błędu przez użytkownika.

Drugim rozwiązaniem jest zasadniczo to, ale z wewnętrzną obsługą. Z zerą sygnalizujesz, że jest jakiś problem. Musi również być obsługiwany, zgłaszany użytkownikowi lub coś podobnego. Wadą jest, jeśli zapomnisz o tym, możesz wprowadzić użytkownika w błąd.

Użyłbym pierwszej metody z dodatkowym sprawdzeniem przed upewnieniem się, że istnieje. Ale to zależy od użycia.

+0

Tak, to zależy. Jeśli wystąpił błąd krytyczny, aby operacja zakończyła się sukcesem, uruchom program lub uruchom wyjątek. W przeciwnym razie po prostu zwróć zero – texasbruce

2

Wybrałbym czystą wersję.

Jeśli nie dostarczysz feed_id metody fetch, rubin sam podniesie ArgumentError: wrong number of arguments(0 for 1), więc pierwsza część # 3 jest bezcelowa.

Jeśli nie dostarczy ważnego feed_id, następnie wywołanie Feed.find(feed_id) podniesie inny wyjątek, najprawdopodobniej ActiveRecord::RecordNotFound z komunikatem albo mówią, że nie może znaleźć paszę z dostarczonym ID, lub jeżeli nie zostało dostarczone ID (parametr feed_id to nil), który nie mógł znaleźć kanału bez identyfikatora.

Dla mnie wydaje się trochę głupie, aby wywołać metodę z feed_id = nil, więc prawdopodobnie twierdziłbym, że "jeśli wyślesz nieprawidłowe dane wejściowe, może się zepsuć", i w takim przypadku, myślę, że ActiveRecord::RecordNotFound da ci dużo więcej informacji o tym, co poszło nie tak, jak podnieść ArgumentError.

Powrót wartości pustej rzadko jest dobrą rzeczą, ponieważ nie powie Ci, co faktycznie było nie tak. Dlatego też wykluczyłbym # 2.

Powiązane problemy