Ruby/Komentarze i organizacja kodu

Komentarze i organizacja kodu

edytuj

Ten rozdział zawiera kilka praktycznych porad, przydatnych w dalszym poznawaniu Rubiego.

Separatory instrukcji

edytuj

Niektóre języki wymagają pewnego rodzaju znaków przestankowych, często średników (;), by zakończyć każdą instrukcję w programie. Zamiast tego Ruby podąża za konwencją używaną w powłokach systemowych takich jak sh i csh. Wiele instrukcji w jednej linii musi być odseparowanych średnikami, ale nie są one wymagane na końcu linii. Znak końca wiersza traktowany jest jako średnik. Jeżeli linia kończy się znakiem odwróconego ukośnika (\), znak końca linii jest ignorowany, co pozwala na utworzenie jednej linii logicznej podzielonej na kilka częsci.

Komentarze

edytuj

Po co pisać komentarze? Chociaż dobrze napisany kod ma tendencję do dokumentowania samego siebie, skrobanie po marginesach jest często pomocne. Błędem jest sądzić, że inni będą w stanie spojrzeć na nasz kod i natychmiast zobaczyć go w ten sposób co ty. Poza tym, praktycznie rzecz biorąc, ty też jesteś inną osobą co parę dni... Któż z nas nie wrócił kiedyś do kodu programu, by go poprawić lub rozszerzyć i nie powiedział: wiem, że to napisałem, ale co to u licha znaczy?

Niektórzy doświadczeni programiści wskażą, całkiem słusznie, że sprzeczne lub przestarzałe komentarze mogą być gorsze niż żadne. Z pewnością komentarze nie powinny być substytutem czytelnego kodu. Jeżeli twój kod jest nieczytelny, prawdopodobnie zawiera również błędy. Możesz odkryć, że potrzebujesz więcej komentować, gdy uczysz się Rubiego, a mniej, jak staniesz się lepszy w wyrażaniu pomysłów w prostym, eleganckim, czytelnym kodzie.

Ruby podąża za ogólną konwencją skryptów, która używa symbolu # by oznaczać początek komentarza. Wszystko co występuje za znakiem # do końca linii jest ignorowane przez interpreter.

Również, by ułatwić wprowadzanie dużych bloków komentarzy, interpreter Rubiego ignoruje wszystko pomiędzy linią zaczynającą się od "=begin" a drugą linią zaczynającą się od "=end".

#!/usr/bin/env ruby

=begin
**********************************************************************
  To jest komentarz blokowy. Cos co piszesz dla innych czytelnikow,
  i rowniez dla siebie. Interpreter zignoruje ten tekst. Nie trzeba
  w nim uzywac '#' na poczatku kazdej linii.
**********************************************************************
=end

Organizacja kodu

edytuj

Niezwykle wysoki poziom dynamizmu Rubiego oznacza, że klasy, moduły oraz metody istnieją tylko, gdy definiujący je kod zostanie uruchomiony. Jeżeli nawykłeś do programowania w bardziej statycznym języku, może to czasami prowadzić do niespodzianek.

# Ponizszy kod zwraca blad: "undefined method":

puts nastepca(3)

def nastepca(x)
  x + 1
end

Chociaż interpreter sprawdza, czy w skrypcie nie występują błędy składniowe przed wykonaniem go, kod "def nastepca ... end" musi być zinterpretowany w celu utworzenia metody nastepca. Tak więc kolejność kodu w skrypcie może mieć istotne znaczenie.

Nie zmusza to, jak mogło by się wydawać, do organizacji ściśle według stylu "od dołu do góry". Kiedy interpreter napotka definicję metody, może ona bezpiecznie zawierać niezdefiniowane referencje, dopóki będziesz pewny, że będą one zdefiniowane nim metoda zostanie wywołana.

# Konwersja stopni ze skali Fahrenheita do Celsiusza, podzielona
# na dwie czesci.

def f_na_c(f)
  skala(f - 32.0)  # To jest referencja do niezdefiniowanej jeszcze metody, ale to nie szkodzi.
end

def skala(x)
  x * 5.0 / 9.0
end

printf "%.1f jest komfortową temperaturą.\n", f_na_c(72.3)

To podejście może wydawać się to mniej wygodne niż to, które możesz znać z Perla czy Javy, ale jest mniej restrykcyjne niż próbowanie pisania w C bez prototypów (co zawsze zmuszałoby cię do częściowego zarządzania kolejnością, co wskazuje na co). Umieszczanie kodu na najwyższym poziomie zagnieżdżenia, na końcu pliku źródłowego zawsze działa. I sprawia mniej kłopotu, niż można sądzić. Sensownym i bezbolesnym sposobem, by wymusić określone zachowanie, jest zdefiniowanie funkcji main na górze pliku i wywołanie jej z dołu.

#!/usr/bin/env ruby

def main
  # tutaj logika najwyższego poziomu
end

# ... dodatkowy kod ...

main # ... start main.

Pewna pomoc płynie również z faktu, że Ruby dostarcza narzędzi do dzielenia skomplikowanych programów w czytelne, nadające się do powtórnego użycia, logicznie powiązane klocki. Widzieliśmy już użycie słowa include by uzyskać dostęp do modułów. Również mechanizmy load i require są bardzo użyteczne. Instrukcja load działa tak, jakby plik do którego się ona odnosi został skopiowany i wklejony (coś jak dyrektywa preprocesora #include w C). Instrukcja require jest nieco bardziej zaawansowana, powodując, że kod będzie załadowany tylko raz i tylko wtedy, gdy będzie to konieczne.