Ruby: if variable vs if variable.nil?

11

Jestem nowy w Ruby i byłem zaskoczony, gdy dowiedziałem się, że wszystkie przedmioty są prawdziwe oprócz zera i fałszu. Nawet 0 jest prawdą.

Zaletą tej właściwości języka jest to, że możesz pisać:

if !variable
  # do stuff when variable is nil
end

Moi koledzy, którzy są bardziej doświadczonymi programistami Ruby, nalegają, żebym wybrał to zamiast używać .nil? tak:

if variable.nil?
  # do stuff when variable is nil
end

Uważam jednak, że ta druga opcja jest lepsza z dwóch powodów: 1. Myślę, że jest bardziej zorientowana obiektowo, szczególnie w języku takim jak Ruby, w którym wszystko jest przedmiotem i wymianą wiadomości. 2. Moim zdaniem jest bardziej czytelny, nawet jeśli jest mniej zwarty.

Czy popełniam tutaj błąd „początkujący”?

Javier Holguera
źródło
4
Czy testujesz na zero? czy fałszywa wartość?
Testuję na zero. Zasadniczo, jeśli zmienna ma wartość zero, robię coś (lub nie)
Javier Holguera,
3
Jeśli testujesz na zero, dlaczego chcesz, aby test na fałsz również wprowadzał ten blok?
Zgadzam się, wskazałem to jako kolejny powód, aby preferować .nil? Podkreślali jednak, że „jeśli zmienna do x” jest bardziej idiomatyczna niż „jeśli zmienna.nil? Do x” i jest lepsza, gdy wiesz, że zmienna nie ma wartości logicznej
Javier Holguera,

Odpowiedzi:

17

Napisz, co masz na myśli. Znaczy to, co piszesz.

Weźmy inny test. .vowel?

if char == 'a'
   # do stuff
end

vs

if char.vowel?
   # do stuff
end

Teraz jest oczywiste, że nie robią tego samego. Ale jeśli tylko spodziewa charsię aczy bto będzie działać. Ale to dezorientuje następnego programistę - drugi blok zostanie wprowadzony dla warunków, w których [eiou]również występuje char . Ale na ato będzie działać poprawnie.

Tak, tak jest nili falsesą jedynymi wartościami fałszowania w Ruby. Jeśli jednak testujesz, niltestując nil || false, nie masz na myśli tego.

Oznacza to, że następny programista (który akurat jest szalonym mordercą z siekierą, który zna twój adres domowy) przeczyta kod i zastanowi się, dlaczego też falsetam powinien się udać.

Napisz kod, który przekazuje dokładnie to , co masz na myśli.

Per Lundberg
źródło
3

Rozważ następujące:

response = responses.to_a.first

Zwróci pierwszy element responseslub nil. Następnie, ponieważ instrukcje warunkowe traktujemy niljak falsemożemy napisać:

response = responses.to_a.first
if response
  # do something ('happy path')
else
  # do something else
end

Który jest bardziej czytelny niż:

if response.nil?
  # do something else
else
  # do something ('happy path')
end

if (object)Wzór jest bardzo często w kodzie Ruby. Ładnie prowadzi również do refaktoryzacji, np .:

if response = responses.to_a.first
  do_something_with(response)
else
  # response is equal to nil
end

Pamiętaj również, że metoda Ruby nildomyślnie zwraca wartość. Więc:

def initial_response
  if @condition
    @responses.to_a.first
  else
    nil
  end
end

można uprościć:

def initial_response
  if @condition
    @responses.to_a.first
  end
end

Abyśmy mogli dalej refaktoryzować:

if response = initial_response
  do_something_with(response)
else
  # response is equal to nil
end

Teraz możesz argumentować, że powrót nilnie zawsze jest najlepszym pomysłem, ponieważ oznacza sprawdzanie nilwszędzie. Ale to kolejny czajnik z rybami. Biorąc pod uwagę, że testowanie „obecności lub nieobecności” obiektu jest tak częstym wymogiem, prawdziwość przedmiotów jest użytecznym aspektem języka Ruby, choć zaskakuje początkujących użytkowników języka.

zetetyczny
źródło
2

Nie tylko if variable.nil?czyta się bardziej jak język naturalny, ale także chroni programistę przed przypadkowym przypisaniem mu falsewartości i wpadnięciem w twoją ifwypowiedź, ponieważ Ruby jest językiem luźno wpisanym.

Greg Burghardt
źródło
1
Więc początkowy komentarz w pierwotnym pytaniu był błędny? Powinno być „robić rzeczy, gdy zmienna jest zerowa lub fałszywa”? A ponieważ kod niepasujący do komentarza jest błędem, od razu jest błąd?
gnasher729,
Poprawny. Prosty test prawdziwości mógłby wprowadzić błędy logiczne.
Greg Burghardt
0

Idiomatycznie, unless variablelepiej niż if !variable. Negatywne ifstwierdzenia są często uważane za zapach kodu, ponieważ łatwiej jest pominąć negację podczas przeglądania.

Większy obraz tutaj polega na tym, że wykonywanie niltakich kontroli jest również trochę zapachem kodu. Aby uzyskać prawidłowe OO, staraj się używać wzorca obiektu zerowego, aby tego rodzaju sprawdzanie nigdy nie było potrzebne. http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

Powiedz obiektom, co mają robić, nie pytaj ich, czym one są. Czasami nazywa się to informowaniem, nie pytaj

Matt Gibson
źródło