Přejít k navigační liště

Zdroják » Různé » Meta-ekosystém Ruby

Meta-ekosystém Ruby

Články Různé

V jazyce Ruby se příjemně pracuje, protože má okolo sebe silný ekosystém různých nástrojů, knihoven a frameworků. Ke vzniku takového ekosystému je ale potřeba meta-ekosystém nástrojů, které zjednodušují život vývojářům jeho součástí. Ruby takovýto meta-ekosystém má a v článku si ukážeme jeho nejdůležitější součásti.

Nálepky:

Jeden z důvodů, proč je příjemné pracovat v jazyce Ruby, je ekosystém nástrojů, knihoven a frameworků, který okolo tohoto jazyka existuje. Takový ekosystém ale nevznikne jen tak náhodou. Pokud by bylo napsání, otestování, zdokumentování a zveřejnění např. vlastní knihovny těžké, dělal by to málokdo a ekosystém by se nikdy nerozvinul.

Ukazuje se, že ve světě Ruby existuje meta-ekosystém nástrojů, které právě s těmito úlohami pomáhají. Programátor se tak může soustředit na samotný kód knihovny a nestráví spoustu času řešením nezábavných podružností. Psaní a zveřejňování knihoven v Ruby je tak velmi snadné a ekosystém díky tomu vzkvétá.

Pojďme si tento meta-ekosystém Ruby stručně představit a ukázat si, jak konkrétně programátorům ulehčuje práci. Projdeme přitom stručně jednotlivé aspekty psaní typické knihovny: kód, testy, dokumentaci a zveřejnění.

Kód

Meta-ekosystém Ruby se projevuje už při psaní kódu. Na rozdíl od mnoha jiných jazyků má totiž Ruby poměrně jasně dané konvence, jak kód psát a jak ho rozdělit do souborů a adresářů. Vyvinuly se živelně, ale existují i různá shrnutí, z nichž nejznámější je asi to od GitHubu.

Díky konvencím prakticky všechny knihovny vypadají co do stylu a struktury stejně a dá se v nich jednoduše zorientovat. To nesmírně usnadňuje přispívání do nich, což v důsledku vede k rozvoji ekosystému.

Testy

V mnohých jazycích se na psaní testů používá nějaký JUnit-like framework. Ten obvykle dovoluje testy strukturovat jen do dvojúrovňové hierarchie třída-metoda a neumožňuje je detailněji popisovat (krom komentářů v kódu). Tato omezení často vedou k nechuti psát testy a k jejich špatné struktuře.

V Ruby jde díky jeho expresivitě testy psát lépe. Řada rubyistů používá RSpec, což je DSL, ve kterém lze testy neomezeně strukturovat podle jednotlivých testovaných aspektů a popisovat je.

Pro ukázku, takto popisně můžou vypadat třeba testy jednoduchého zásobníku (strukturované podle jednotlivých metod a jejich funkcionality):

describe SimpleStack do
  # Před každým testem si připravíme prázdný a plný zásobník.
  before :each do
    @empty_stack = SimpleStack.new

    @full_stack = SimpleStack.new
    @full_stack.push "A"
    @full_stack.push "B"
    @full_stack.push "C"
  end

  # Popis metody pop.
  describe "pop" do
    it "raises an exception on an empty stack" do
      lambda { @empty_stack.pop }.should raise_error(RuntimeError)
    end

    it "returns top item" do
      @full_stack.pop.should == "C"
    end

    it "removes top item" do
      @full_stack.pop
      @full_stack.top.should == "B"
    end
  end

  # Popis metody push.
  describe "push" do
    it "adds item to the top" do
      @full_stack.push "D"
      @full_stack.top.should == "D"
    end
  end
end

Takovéto testy je snadné psát i číst. I to je jeden z důvodů, proč testy obsahuje drtivá většina knihoven v Ruby.

Pokud je váš projekt zveřejněn na GitHubu, můžete ho nechat testovat automaticky po každém commitu pomocí veřejného continuous integration serveru Travis CI. Ten umí testy spouštět proti různým verzím a implementacím Ruby (Rubinius, JRuby), a také proti různým verzím jiných knihoven či frameworků (typicky Rails). Obojí velmi usnadňuje vývoj.

Pro pořádek je nutno dodat, že v Travis CI jde testovat projekty v mnoha běžných jazycích. Možnosti nastavení pro Ruby jsou ale nejbohatší.

Máte Ruby rádi nebo byste se ho chtěli naučit? V pražské pobočce SUSE v něm děláme mnoho projektů, velkou část z nich open source. Přidejte se k nám.

Dokumentace

Každá knihovna, má-li být použitelná nejen pro autora, potřebuje dokumentaci. Asi nejčastěji používaným nástrojem pro generování dokumentace v Ruby je YARD. Zvládá jak dokumentaci vysokoúrovňovou (REDAME, popis principů, příklady,…), tak nízkoúrovňovou (popis API jednotlivých tříd a metod). Dokumentace tříd a metod syntakticky trochu připomíná JavaDoc:

# Exception raised when a command execution fails.
class ExecutionFailed < StandardError
  # ...

  # Initializes a new {ExecutionFailed} instance.
  #
  # @param [Array<Array<String>>] commands the executed commands
  #   as an array where each item is again an array containing
  #   an executed command in the first element and its arguments
  #   in the remaining ones
  # @param [Process::Status] status the executed command exit status
  # @param [String, nil] stdout the output the executed command
  #   wrote to stdout
  # @param [String, nil] stderr the output the executed command
  #   wrote to stderr
  # @param [String, nil] message the exception message
  def initialize(commands, status, stdout, stderr, message = nil)
    super(message)
    @commands = commands
    @status   = status
    @stdout   = stdout
    @stderr   = stderr
  end
end

YARD toho umí celkem hodně. Pro pohodlné psaní dokumentace je ale nejdůležitější funkcí živý náhled. Stačí spustit yard server --reload v adresáři vašeho projektu a nasměrovat prohlížeč na adresu localhost:8808. Po každém uložení zdrojových souborů se dokumentace přegeneruje a vy hned vidíte změny.

Vzhled dokumentace vygenerované YARDem

Po napsání dokumentace obvykle vyvstane problém – kam s ní? Ruby má jednoduchou odpověď: RubyDoc.info. Pokud máte svůj projekt na GitHubu, můžete na tento server jeho dokumentaci nahrát několika kliknutími. Pokud jste projekt vydali jako gem (o tom za chvíli), bude tam dokonce automaticky. U vydaných gemů je automaticky k dispozici i dokumentace ke starším verzím (to často jinde chybí).

Existence RubyDoc.info znamená, že u dokumentace není vůbec třeba řešit hosting a uživatelé mají dokumentaci ke všem knihovnám soustředěnou na jednom místě. Opět plus pro rozvoj ekosystému.

Zveřejnění

Po dopsání, otestování a zdokumentování kódu nastane čas ho zveřejnit. Na rozdíl od mnoha jiných prostředí je to v Ruby záležitost na dvě minuty (pokud to neděláte úplně poprvé).

Ruby na distribuci kódu používá systém balíčků – “gemů”. Podobně jako u dokumentace existuje centrální server RubyGems.org, kam můžete svůj balíček nahrát a ostatní si ho odsud můžou stáhnout. K vytvoření gemu stačí přidat do vašeho projektu soubor s metadaty (název projektu, popis, verze, autor, seznam souborů,…) a následně spustit dva jednoduché příkazy, které vytvoří balíček a nahrají ho na server. 

Nemusíte tedy ručně řešit žádné balení, vymýšlet kam knihovnu nahrát apod. Asi nemusím říkat, jak klíčový vliv to má na množství zveřejněných knihoven a na jejich rychlý vývoj.

Závěr

Věřím, že se mi podařilo stručně nastínit, jak různé nástroje meta-ekosystému Ruby usnadňují vytváření knihoven a umožňují soustředit se na podstatné věci místo řešení podružností. Díky tomu je ekosystém Ruby bohatý a práce v tomto jazyce příjemná. A pokud máte zkušenosti z jiných prostředí a máte pocit, že některý z aspektů probraných v článku zvládá lépe než Ruby, rád se o tom dozvím.

Komentáře

Subscribe
Upozornit na
guest
21 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
retro

Co bundler? To je poslední dobou dost klíčová věc.

Tomáš Jukin

Bundler je jednoznačně must-have věc, ale souhlasím zcela s Davidem, že asi není way ho prezentovat jako killer-feature Ruby, ale jako workaround nedostatků rubygems – já prakticky vždy používám rubygems společně s bundlerem a už tak nějak jedno od druhého příliš neodděluji ani ve svých myšlenkových pochodech ;).

Jedna z věcí, které možná stojí za to poznamenat je velmi chabá (a.k.a. prakticky neexistující) podpora gitu ze strany rubygems, kterou přidává pořádně až právě bundler…

asfas

Dobry den, ja si dovolim mat na vec iny pohlad, mozno zaujaty pohlad programatora, ktory preferuje silne typove jazyky. V Ruby sa mi pracuje zle, pretoze:

1. nemam IDE a auto-completion (presnejsie, zakladne auto-completion tam je, ale z principu nemoze poskytovat tolko informacii ako pri silne typovych jazykov)
2. nie je mozne vytvorit portovatelnu aplikaciu, ktora po rozbaleni (bez bundle install) funguje na roznych linuxoch a na windows
3. zdrojaky vela kniznic maju jednoriadkove metody s poznamkou # native stub implementation (napriklad SSL).
4. Kniznice, pouzivajuce dynamicke techniky prepisovania kodu, sa mi citaju mimoriadne zle, a niekedy sa taketo kniznice zvyknu bit medzi sebou (mal som problem s dvoma kniznicami v Rails)
5. Nemoznost pisat silne API (nie je mozne specifikovat typy parametrov apod. Duck typing nie je dobry, umoznuje nekompatibilne zmeny, napr. uploading suborov v Rails 2 vs Rails 3)
6. Neexistuje specifikacia jazyka, napr. ak Ruby zacne pouzivat nativne thready, nastanu velke problemy kvoli absencii napr. happens-before relacie.

Neberte to, prosim, ako pokus o flame, len pohlad z druhej strany.

Tomáš Jukin

To jsou výborné poznámky!

A řada z nich je i zcela korektní a přesná, já bych to neviděl ani tak jako nevýhody ruby jako jeho featury, nebo rysy.

Zase tu je spousta lidí (me included), kterým velmi vyhovuuje způsob jakým ruby funguje a jak se v něm píše včetně jeho vlastností (dynamické typy, možnost přepisování tříd po jejich definici, DSL!, apod.).

Třeba bych to rozhodně nedoporučil jako jazyk pro tvorbu intranetových systémů např. elektronického bankovnictví, atd.

Featura, která se mě ale líbí úplně nejvíc je prostý fakt že jsem schopný během velmi málo času a s velmi malým množství vynaložného úsilí vytvořit komplexní webovou aplikaci (jako je např. e-shop, CMS, nebo customizovaný systém, nebo API). A to právě díky tomu že existuje neuvěřitelná množství proveřených a funkčních knihoven (v našem ekosystému právě gemů), které mohu do aplikace zaintegrovat během okamžiku, umím je používat během a okamžiku a just works. Dokonce je umím i upravovat během okamžiku. Což např. v případě JavyEE naprosto nefunguje…

Ale anyway skvělý názor „z druhé strany“, díky za něj!

omelkes

A jaké IDE pro ruby dooručujete?

A myslím, že v textu je chybka: na řádku 19 v testy by podle mě mělo být @full_stack.top­.should == „C“ (aktuálně je tam pop)

s pozdravem
Ondra Melkes

omelkes

Aha, tak to jsem špatně pochopil jak to v ruby fungují testy. Tedy, jestli to chápu správně tak IT je něco jako metoda test v PhpUnit a před ní se provede příkaz before each.

Zatím s ruby moc kamarád nejsem. Díky za odpověd.

Ad IDE – vim je poměrně šikovný nástroj, lze v něm nastavit autocomplete? Zobrazování doc komentářů?

Oldřich Vetešník

Ono těch testovacích frameworků je hodně, třeba standardně v Ruby 1.9 je Minitest (https://github.com/seattlerb/minitest), který je hodně podobný PHPUnit (ale lze psát i stylem, který je v článku).

Srigi

Co som si vsimol v Ruby komunite, su dva hlavne smery:
– VIM
– Rubymine (plnohodnotne IDE)

Na popularite taktiez nabera Sublime text.

Čelo
janminarik

Ahoj, dovolím si svojí trošku do mlýna…

Jak asi někteří víte, přecházím z Ruby na jiný jazyk. Hlavním důvodem je několik zásadních zjištění, které jsem udělal v poslední době:

1. Ruby má sice vyšší expresivitu než Java, C++ nebo C#, ale neplatí to obecně pro srovnání staticky x dynamicky typovaných jazyků. Druh typovosti jazyka s expresivitou nekoreluje.

2. Ruby umožňuje jen velmi základní úroveň abstrakce. Důvod neflexibility např. Javy není statická typovost jazyka, ale chybějící sémantické a syntaktické konstrukty, které Ruby nabízí. Jsou ale jiné jazyky, které naopak oproti Ruby nabízejí spoustu dalších konstruktů a možností abstrakce, které Ruby nezná.

3. Ruby je oslavováno pro možnost tvorby hezkých interních DSL. Ve skutečnosti ale při tvorbě takového DSL musí člověk při každém kroku provádět krkolomnou akrobacii s metatřídami a vůbec propojení objektů klade zásadní omezení tomu, jak může výsledné DSL vypadat. Jazyky, které umožňují spouštět část kódu při kompilaci (např. makra v Lispu), umějí ve skutečnosti mnohem snáz vytvářet mnohem silnější DSL a z principu sice mohou, ale vůbec nemusejí být dynamicky typované. O síle v podpoře externích DSL přímo v jazyce ani nemluvě…

4. Rychlost jazyka a pracnost paralelizovat výsledný kód sice není něco, co každý potřebuje, ale pokud ano, je to v případe Ruby show-stopper.

5. Množství chyb, které odhalí kompiler na základě statických typů je enormní. Pokud používáte automatické testovací nástroje, které samy generují testovací data na základě typových předpisů (např. QuickCheck), máte 10x bezpečnější kód bez jediné řádky ručně napsaných testů.

Pro zajímavost – šampiónem mého srdce se stal Haskell, který mi ve výše zmíněných ohledech vyhovuje mnohem víc.

vidya

ad 4. – jruby.

janminarik

Já jsem nemluvil o GIL. Problém paralelizace není v Ruby jako takovém, ale v imperativních jazycích obecně, tj. Ruby, Python, Java, všechny mají stejný problém. Stavovost jazyka znemožňuje standardní sekvenční algoritmus snadno paralelizovat. Pokud něco píšu, musím to od začátku psát buď sekvenčně, nebo paralelně.

Samozřejmě to neplatí vždy a všude, ale celkové paradigma, na kterém je jazyk postaven, podporuje hlavně sekvenční programování a pokud chci paralelizovat, obvykle skončím s dvojnásobně dlouhým kódem, plným race condition chyb.

K rychlosti asi tolik: V mnoha testech je Ruby pomalejší než kompilované jazyky třeba 10x, ale často i 100x. V takovém případě nehraje žádnou roli, že JRuby je např. 2x rychlejší (což navíc není).

Ale o rychlosti jsem se bavit nechtěl, je to jen jeden z mnoha důvodů.

lmb

U Haskellu zase bývá show-stopper IQ programátora, který ho chce efektivně využívat k řešení problémů ;-) IMHO jazyk pro horních 5% .

janminarik

Je pravda, že začít vyžaduje o něco víc práce než u jiných jazyků, které jsem zkusil. Ale jako někdo, komu se daří používat Haskell po většinu pracovního dne musím říct, že je to všechno jen o trpělivosti. Když už bych musel mluvit o IQ, spíš bych řekl, že je to jazyk pro horních 50% :)

Hlavně je to ale velká zábava. Kdo si chce udělat názor, existuje výborný tutoriál i v češtině: http://naucte-se.haskell.cz/

Oldřich Vetešník

Ahoj, chtěl bych poděkovat za pěkný příspěvek, po jiných jazycích pokukuju už delší dobu a právě zkouším Haskell (http://book.realworldhaskell.org/read/) a zatím se mi to líbí. Kdybyste měl nějaký super tutorial, tak sem s ním. Jinak Ruby mám rád, ale trochu mi vadí ten humbuk, co se kolem toho dělá; svět to rozhodně nespasí.

Tomáš Jukin

Perfektní shrnutí základů! Supr!

Jen má zkušenost – když nepíši zrovna knihovní funkci tak silně preferuji dokumentovat ruby (a hlavně rails) aplikace přímo kódem. Ale na knihovny je yard ideální…

andrej.k

yard v server mode vyzera luxusne, neviete niekto o podobnom produkte pre javadoc?

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.