Zen of Python - uwagi

Opublikowane przez Jarosław Zabiełło Mon, 01 Sep 2008 11:42:00 GMT

Filozofię języka Python najlepiej oddaje tzw. Zen of Python. Jest ono dostępne w jęz. angielskim z poziomu interpretera.

>>> import this
  • Beautiful is better than ugly.
  • Explicit is better than implicit.
  • Simple is better than complex.
  • Complex is better than complicated.
  • Flat is better than nested.
  • Sparse is better than dense.
  • Readability counts.
  • Special cases aren’t special enough to break the rules.
  • Although practicality beats purity.
  • Errors should never pass silently.
  • Unless explicitly silenced.
  • In the face of ambiguity, refuse the temptation to guess.
  • There should be one—and preferably only one—obvious way to do it.
  • Although that way may not be obvious at first unless you’re Dutch.
  • Now is better than never.
  • Although never is often better than right now.
  • If the implementation is hard to explain, it’s a bad idea.
  • If the implementation is easy to explain, it may be a good idea.
  • Namespaces are one honking great idea—let’s do more of those!

W języku polskim brzmiałoby to mniej więcej tak:

  • Piękny jest lepszy niż brzydki.
  • Jawny jest lepszy niż domyślny.
  • Prosty jest lepszy niż złożony.
  • Złożony jest lepszy niż skomplikowany.
  • Płaski jest lepszy niż zagnieżdżony.
  • Rzadki jest lepszy niż zagęszczony.
  • Czytelność ma znaczenie.
  • Sytuacje wyjątkowe nie są na tyle wyjątkowe, aby łamać reguły.
  • Aczkolwiek pragmatyzm wygrywa z puryzmem sztywnego trzymania się reguł.
  • Błędy zawsze powinny być sygnalizowane.
  • No chyba, że zostaną celowo ukryte.
  • W obliczu dwuznaczności odrzuć pokusę aby zgadywać.
  • Powinien istnieć jeden, i najlepiej tylko jeden, oczywisty sposób do zrobienia danej rzeczy.
  • Chociaż sposób ten nie musi być początkowo oczywisty jeśli nie jesteś Holendrem.
  • Teraz jest lepsze niż nigdy.
  • Chociaż nigdy jest często lepsze niż właśnie teraz.
  • Źle, jeśli implementację jest trudno wyjaśnić.
  • Dobrze, jeśli implementację jest łatwo wyjaśnić.
  • Przestrzenie nazw są świetnym pomysłem – stwórzmy ich więcej!

Explicite vs. implicite

W przeciwieństwie do Rubiego, Python podkreśla wyższość kodu explicite nad implicite (jawnego nad domyślnym). W wypadku Pythona, wszelka informacja odnośnie symboli obecnych w kodzie źródłowym jest (zwykle) jednoznacznie określona i nie trzeba otwierać dziesiątków innych plików, aby się domyślić skąd się dana funkcja, czy zmienna, wzięła. Ilość symboli dostępnych globalnie w Pythonie (w przestrzeni __builtins__) jest relatywnie mała i łatwa do zapamiętania. Reszta zaś może być wydedukowana z deklaracji importu.

(Istnieje co prawda możliwość zaciemnienia tej przejrzystości za pomocą konstrukcji from moj_modul import * ale generalnie nie zaleca się jej stosowania. W Ruby, a w Rails w szczególności, próba zlokalizowania kodu źródłowego jest dosyć mozolnym zajęciem. Z samej deklaracji require 'jakis_plik' (podobnie jak w PHP) nie wynika nic na temat dostępnych symboli w bieżącej przestrzeni nazw. Trzeba otworzyć plik i zobaczyć co zostało zadeklarowane. W wypadku wielokrotnych zagnieżdżeń konstrukcji require trzeba bawić się w Sherlocka Holmesa aby dojść co się tam dzieje (swoją drogą nadmiar zagnieżdżeń jest sprzeczny z punktem “Płaski jest lepszy niż zagnieżdżony”). Konkurencyjny do Rails framework – Merb – postanowił zm zminimalizować ilość magii (tj. domyślnych deklaracji) w kodzie do minimum. Więc, jak widać, da się. Osobiście Merb jest moim faworytem jeśli chodzi o webowe frameworki. Jest szybki, prosty i czytelny. Zbudowany na solidnych, pragmatycznych, inżynierskich zasadach. Na 11 października 2008 zapowiadana jest wersja końcowa 1.0.)

Jak większość rzeczy, istnieje też druga strona medalu. “Magiczne” podejście przyjęte w Rubim może nie wpływa dodatnio na kwestię oczywistości (pkt. 1 Zen of Python) ale daje za to możliwość uzyskania piękniejszego kodu (pkt.1 Zen of Python) Uzyskanie tak ładnego DSL’a jak RSPec jest w Pythonie (i większości języków) po prostu niemożliwe. Zobacz też Business Natural Languages (oraz prezentację) Programiści Rubiego podkreślają walory estetyczne składni Rubiego i tu mają rację.

Jedna droga do celu

Pythonowcy mocno podkreślają zasadę “Powinien istnieć jeden, i najlepiej tylko jeden, oczywisty sposób do zrobienia danej rzeczy.” Niestety, zasada ta nie zawsze jest stosowana. Najlepszym przykładem jest SQLAlchemy, który wydaje się kompletnie ignorować tą zasadę. Nie ujmując jego możliwości, sposób jego użycia jest tak nieoczywisty, że powstały nawet nakładki na warstwę API SQLAlchemy (Elixir). Także sposób użycia wątków w Jythonie niespecjalnie pasuje do jednego, oczywistego rozwiązania. Ale pomijając takie przypadki, ogólnie zasada “jednego sposobu” wydaje się dobra.

Osoby poznające Rubiego na początku mogą być zdezorientowania setkami dostępnych metod w prawie każdym obiekcie. Początkowo także i mi wydawało się oczywiste, że powyższa zasada Zen Pythona jest lepsza niż, dziedziczone po Perlu, nastawienie na możliwość wielu rozwiązań tego samego zagadnienia. Jednakże, w miarę “otrzaskania” się ze składnią i metodami Rubiego, zasada “jednej drogi” przestała być aż tak ważna. Faktem jest że Ruby dysponuje większym arsenałem metod i konstrukcji niż Python (i przez to trudniej się go opanować niż Pythona), ale dzięki nim można pisać znacznie bardziej zwarty kod i to bez większej utraty czytelności tak charakterystycznej dla Perla. Ruby świetnie się nadaje na jednolinijkowe skrypty zamiast Basha czy Pythona.

Programowanie jest sztuką

Nawet najlepsze zasady na jakich z budowany byłby język nie zagwarantują że kod w tym języku automatycznie będzie czytelny i ładny. Nawet w Pythonie można stworzyć “potworki” składniowe. Programista może być wyrobnikiem albo artystą. Na pewno tym drugim nie zostanie ten, kto programowania po prostu nie lubi. Tak nawiasem mówiąc, w obecnych czasach, kiedy trudno jest znaleźć dobrych programistów, dobrym wskaźnikiem może być to, na ile programowanie jest czyjąś pasją. Pasjonaci bardzo szybko się uczą i prześcigają tych, co traktują programowanie tylko jako zajęcie do zarabiania pieniędzy.

Znajomość języka to nie tylko nauczenie się na pamięć jego składni i bibliotek. Każdy język ma swój “sposób myślenia”. Np. sposób optymalnego użycia Pythona/Rubiego bardzo się różni od sposobu pracy w językach takich jak Java/C++. Bywa też, że to, co tam jest tak gloryfikowane, w języku dynamicznym staje się śmiesznie łatwe albo zbędne. Ruby nie potrzebuje “dependency injection” bo to samo można uzyskać znacznie prościej na bazie samej swej składni. Python z kolei nie potrzebuje specjalnych konstrukcji dla stworzenia “singletona”, bo wystarczy mu do tego zwykły moduł. Itp. itd. Z praktyki widzę, że trzeba mniej więcej około roku aby javowiec pozbył się starych nawyków i “poczuł” Ruby Way.

Tagi ,  | 7 comments

Comments

  1. Avatar Eluś powiedział about 5 hours later:

    Dobry wpis. Zwłaszcza w kontekście ostatniej dyskusji na p.c.l.python.

    Mimo podobnej natury Rubiego i Pythona języki te różni przytoczona przez Ciebie filozofia. To ona w znaczne mierze określa styl podejścia do programowania (a nawet kierunek dalszego rozwoju) każdego z nich.

  2. Avatar Jiima powiedział 1 day later:

    @Eluś

    Natura Ruby i Pythona jest zupełnie inna. To, że języki te są częścią “skryptowej rewolucji” nie oznacza to, że mają jakieś cechy wspólne, poza faktem że są skryptowe.

    Pomijam już takie kwestie jak konserwatywny GC w Pythonie vs generacyjny w Ruby, czy kwestię pól, które w Pythonie są publiczne a w Ruby nieodwołalnie prywatne (o ile nie bawimy się w metaprogramowanie).

    Ruby generalnie ma dwóch rodziców i widać to na pierwszy rzut oka. Jednym jest Smalltalk (filozofia przekazywania sygnałów, bloki, otwarte obiekty, iteratory blokowe) zaś drugim Perl (mnóstwo “perlizmów” w języku jak magiczne zmienne $-cośtam, stanowe zakresy itp.). Dziedzictwo Perla jest stopniowo wypierane, ale nie da się ukryć, że Perl ze “starych” języków jest jednym z lepszych narzędzi do tworzenia DSL (i wszelkich innych zabiegów dotyczączych zaciemniania kodu niestety – generalnie wielu hackerów Perla (na szczęście nie ja, więc chyba nie mam prawa nazywać się hackerem perla) zakłada że im krótszy i bardziej wymyślny kod tym lepiej).

  3. Avatar Jiima powiedział 1 day later:

    @JZ

    “Dependency injection” jest tylko pewnym stylem rozwiązywania problemów. To, że w Rubym da się go zrobić badziewnie łatwo, a w Javie trzeba się namęczyć, nie oznacza że cała idea jest bez sensu.

    Co do singletona, sprawa jest bardziej złożona. Zależy po prostu co chcesz osiągnąć. Generalnie singleton jest mocno przereklamowanym sposobem na obejście pewnych błędów konstrukcyjnych aplikacji i w Javie też się go wystrzegam.

    Poza tym każdy język ma swoją “filozofię” i ciężej się programuje gdy działa się wbrew niej. To co wciąż mi się wymyka to filozofia C++. Na szczęście rzadko cokolwiek w nim piszę. Za to lubię języki wieloparadygmatowe, takie jak Scala na ten przykład, czy… Javascript. Fajna jest Lua (i niezwykle szybka), zastanawiam się czemu ten język jeszcze nie zdobył szerszego uznania…

  4. Avatar Hibernaculus powiedział 2 days later:

    @Jiima “Lua” to nie “kobieta” :) – to po portugalsku znaczy “księżyc”... Co do popularności to język ten jest bardzo popularny w środowisku gier/graczy MMORPG (WoW), łatwo się go wbudowywuje w aplikacje i jest bardzo prosty tylko trzeba zmienić nieco sposób pisania kodu (np. tablice asocjacyjne są wszechobecne) Jak dla mnie jest to język przejrzysty i baardzo szybki (wystarczy tylko spojrzeć na http://shootout.alioth.debian.org/gp4/lua.php), słowem język który jeszcze nie miał swoich 5 minut w sferze “web-deweloperki” jestem pewien że niebawem wszystko się zmieni, jak tylko mod_wombat (lua for apache) okrzepnie.

  5. Avatar Jan Koprowski powiedział 2 days later:

    Ja za ten wpis dziękuję :]

  6. Avatar Jiima powiedział 2 days later:

    @Hibernaculus

    Wiem co znaczy “lua” ale jako polskojęzyczny odruchowo nadaję rodzaj żeński rzeczownikom na “a”. I też uważam że język ma szansę zabłysnąć. Jeśli chodzi o szybkość i “lekkość” miałby spore szanse w walce z PHP (prosta składnia, prawdziwy garbage collector, no i tablice asocjacyjno – indeksowe powinny być dobrze znane fanom PHP, choć w Lua zachowują się one zupełnie inaczej).

    Co do wbudowywania, Lua powstał(a/o) jako język do wbudowywania, dopiero ostatnimi laty robi się popularny jako język standalone. Ja poznałem go pisząc modyfikacje do edytorka SciTE.

    Lua ma sporo cech języka funkcyjnego (koprocedury, każda funkcja to domknięcie, funkcja jest jednym z podstawowych typów języka, wbudowana optymalizacja tail-call), co lubię. Oprócz mod_wombat (w sumie zawsze jest jeszcze Xavante) czekam na okrzepnięcie kompilatora metalua, który pozwala na łatwiejsze metaprogramowanie i tworzenia DSL-i. Ale fakt, że obok Scali i Javascriptu 2.0 to język który może mieć świetlaną przyszłość…

  7. Avatar Hibernaculus powiedział 6 days later:

    @Jiima a wracając do lua… widzę że Kolega też jest fanem w/w. Jakis czas temu postanowiłem napisać własny packer dla javascript’u – szukałem różnych rozwiązań, na python i ruby to nie do końca jest to, dopiero po przyjrzeniu się lua, poczułem że to może być to czego szukam (zwłaszcza jeśli dodam, że lua posiada coś takiego co się nazywa LPeg – moduł PEG napisany w c dla lua – dla mnie bomba). Nigdy wcześniej nie chciałem się uczyć żadnych “c-podobnych” językow (te wskaźniki brrr), ale dzięki czemus co zowie toluaxx (http://toluaxx.luaforge.net) jest zrobienie bindings bibliotek w c/c++ do lua jest dziecinnie proste – wystarczą podstawy c/c++... a jeśli chodzi o rozwiązania webowe – tu jest gorzej, sądze że takie rozwiązanie jak Kepler (“all in one” dla web’u w lua), Nanoki czy Sputnik (wiki engine w lua) przyjeły niezbyt udany paradygmat rozwoju (brak wykorzystania MVC z prawdziwego zdarzenia – why??!!) przypominający bardziej niezgrabne bękarty ze stajni php’a niż profesjonalne środowisko do pracy – właśnie te niszę planuję zagospodarować i stworzyć coś wielkiego – gdyby ktoś chciał wspomóc – zapraszam hibernaculus[tu małpa]gmail.com – zróbmy framework MVC w lua! :) /przepraszam, ze tresc komentarza odbiegła od tematu posta/

    ...no cóż niuanse lingwistyczne :)

(leave url/email »)

   Pomoc języka formatowania Obejrzyj komentarz