Wpis z mikrobloga

Ruby-pytanie do ruby-mirków: jak sobie radzicie z brakiem interfejsów / klas abstrakcyjnych?

Sytuacja jest taka: mam zbiór klas, które mają odpowiadać za internacjonalizację. Klasy sa pogrupowane w modułach (i18n::pl, i18n::en, i18n::de itp), ale klasy o tych samych nazwach w różnych modułach powinny mieć te same metody.

Sprawdzanie obiektu za pomocą respond_to? przed każdym wywołaniem metody wydaje mi się marnowaniem miejsca na dysku. To się musi dać zrobić łatwiej, tylko jak?

#ruby #programowanie
  • 21
@singollo:

Pisać testy, które wywołują te metody? :)

Te metody w różnych modułach się w ogóle różnią? Wydaje mi się, że źle używasz modułów, ale tego nie powiem z powyższego opisu,
@Ragnarokk: ciekawe, jak to działa przy używaniu kodu 3rd party. Trzeba sprawdzać pokrycie kodu testami? Pytam zupełnie poważnie - jak sprawdzić, czy kod, który dostałem od znajomego implementuje konieczne metody.

Druga, powiązana sprawa - IDE i podpowiadanie składni. Jakoś się przyzywczaiłem do tego, że IDE mi podpowiada nazwy metod i listę parametrów. Może chociaż to się da uzyskać? Używam Aptana Studio 3
@paffnucy: no np. ja wiem. Ale IDE nie wie, i mi nie przypomni, jeśli o niej zapomnę, implementując ustawienia dla np. języka rosyjskiego. Jeśli taką klasę będzie tworzył zewnętrzny programista, to on może nawet nie być do końca świadomy, że metoda jest wymagana; albo zrobi literówkę w nazwie i jego testy będą działały prawidłowo.

Nie chce mi się tu wnikać, dlaczego i do czego używa się interfejsów w programowaniu obiektowym, chodzi
@singollo:

W Ruby to się raczej robi na odwrót - unifikuje metody, wrzuca metody do modułów i dołącza się ten modul do klas. Chyba że jednak nie rozumiem, co chcesz osiągnąć. Tutaj masz metody, które wywołują metodę o tej samej nazwie, o tych samych parametrach i pobierających dane z tego samego źródła (pliku tekstowego, yml - zgaduję)
@Ragnarokk: może dałem zły przykład. Załóżmy, że masz klasę file, która jest abstrakcją pliku. Ta klasa ma metodę save(), która zapisuje plik. Metoda save przyjmuje jako parametr adapter zapisu, który wykonuje zapis pliku: LocalAdapter::save(file) zapisuje na dysk, FtpAdapter::save(file) na ftpie, DropboxAdapter::save(file) na dropboxie itp. Metoda File::save() wie tylko tyle, że przekazuje się jej adapter i ma on metodę save. W PHP napisałbym, że istnieje interfejs

interface IFileSaver { public function save(File
@singollo: Jeśli nie implementuje oczekiwanej metody to się wysypie program. Taka wada języków skryptowych, większość rzeczy wychodzi w runtime, nie w czasie kompilacji :( Co do samych interfejsów to na 99% da się osiągnąć to czego potrzebujesz z pomocą metaprogramowania. W Pythonie zrobiłbym sprawdzenie czy wszystkie z tych klas implementują jakąś metodę jeszcze na poziomie kompilacji (metaklasy, albo chociaż dekorator na klasę) co dałoby zerowy narzut w czasie wykonania. Nie znam
Taka wada języków skryptowych, większość rzeczy wychodzi w runtime, nie w czasie kompilacji :(


@Kiro: no mówią, że PHP taki skryptowy. Heheszkują, że nie programowanie. A tu taki klops :(

@paffnucy, @Ragnarokk, @Hauleth: znalazłem częściowe rozwiązanie z użyciem obiekt.class.ancestors; ale tak naprawdę to chodziło mi o to, jak z problemem mierzą się praktycy. Trochę mnie zaskoczył fakt, że praktycy nie widzą problemu...
@singollo: praktycy rozwiązują to testami i nie martwią się tym, że nad ich kodem będą pracować głąby, które nie skumają, że metoda

Jesus#save()
nie może zostać użyta w kontekście zapisywania do plików.
nie martwią się tym, że nad ich kodem będą pracować głąby


@paffnucy: to się sprawdza w zespołach max. 3 osobowych o minimalnej rotacji. W większych firmach prędzej czy później trafi się głąb, który nie dotestuje, nie doczyta, nie sprawdzi - a błąd wyjdzie dopiero w jakichś szczególnych okolicznościach po roku, kiedy głąba już w firmie nie ma...
@singollo: Dokładnie tak jak pisze @paffnucy: jesteśmy dżentelmenami, jeśli w dokumentacji nas proszą o zaimplementowanie określonego zestawu metod - robimy to. Jednocześnie ufamy że jeśli kogoś poprosimy o to samo to on też to zrobi i nie będzie wrzucał syfu do kodu :) Poza tym jak coś nie działa to nie idzie na produkcje/do mastera, to jest bardziej problem organizacyjny.
@singollo: a jeszcze co do tego fragmentu:

W większych firmach prędzej czy później trafi się głąb, który nie dotestuje, nie doczyta, nie sprawdzi


w większych firmach (i nie tylko) stosuje się code review i continuous integration, więc prawdopodobieństwo, że takie kwiatki dostaną się do głównego brancha jest minimalne... tym bardziej, że dokładniej przegląda się zwłaszcza kod osób nowych w zespole
@Kiro: @paffnucy: panowie, to po co piszemy wyjątki, rozróżniamy je, po cholerę cała ta obsługa błędów? Przecież nie popełniamy błędów ;)

Ja jestem właśnie po implementacji obsługi SEPA, do której miałem nawet dwie dokumentacje, przygotowane przez dwie wielkie instytucje bankowe. Szkoda tylko, że pierwsze uruchomienie systemu "na żywo" zwróciło kody błędów, których nie było w dokumentacji, ani w jednej ani w drugiej (a w każdej był trochę inny zestaw). Było
po cholerę cała ta obsługa błędów


@singollo: w takim razie zamknij wywołania tych metod w bloku

try..except
pod kątem

MethodMissing
czy jak to tam macie w Ruby (też Pythoniarz here)

Jeżeli tak Ci zależy na wyłapywaniu błędów na poziomie kompilacji, to może warto rozważyć zmianę języka na Javę, C#, C++ czy coś w ten deseń?