Blog | Pohled na OOP po 2 letech funkcionálního programování

Pohled na OOP po 2 letech funkcionálního programování

Už jsou to víc než 2 roky, co jsem začal většinu zdrojových kódů psát funkcionálně. Pohledem zvenčí se mi spíš pochopení OOP prohloubilo.

Na co jsem přišel?

Objekt vypadá nějak takhle:

[tady začíná černá skříňka
        tady je skrytý stav
        tady jsou metody pracující s tím stavem
        ty metody lze volat zvenčí nebo zevnitř
tady končí černá skříňka]

Zevnitř je "věc" samotný objekt, atributy i metody. Zvenčí je "věc" objekt a veřejné metody. Pokud máte "věc", tak se na ni můžete odkázat, poslat ji jako parametr další metody.

A protože ikdyž vás zajímá jen pár atributů, stejně dopadnete tak, že budete všude možně šoupat tyto černé skříňky.

A když si uděláte svou funkci, která bude umět s těmi atributy něco užitečného a bude použitelná ve více objektech, máte několik možností, jak tuto funkci používat.

  1. použijete dědičnost a dáte funkci do společného předka - což funguje dobře, pokud daná funkce dává perfektní smysl v rodiči a i ve všech potomcích, což nemusí být pravda
  2. použijete kompozici a budete atributy předávat z objektů, což znamená rozkopírovat spoustu kódu
  3. budete používat mixiny, což se snadno může zvrhnout v takovouhle šílenost, kdy bude mít váš objekt stovky metod
  4. budete používat věci jako bind, call jako znáte z JS (a brzy i z PHP 7), což je fajn, dokud tohle nebudete používat uvnitř objektů a začnete mít problém pamatovat si, this je objekt A, this aktuální objektu jste si přiřadili do self atd.
  5. prostě to rozkopírujete a máte v projektu stejně pojmenované metody

Zapouzdření, které je považované za dobrou věc, nakonec vede k tomu, že na 10 objektech s 10 datovými strukturami máte vždy 10 metod místo toho, abyste měli 1 datovou strukturu, nad ni třeba 30 funkcí a ušetřili jste si 80 % zdrojového kódu.

Někdy se zapouzdření samozřejmě hodí, ale na to nepotřebujete objekt. Můžete si napsat funkce, kterou budete používat jen v určitém kontextu a jen s danou datovou strukturou. Funkcionální jazyky obvykle umí nabídnout zapouzření tak, že zároveň nabídne polymorfismus.

Další zjištění, na které jsem přišel, je v tom, že ikdyž desítky procent vývojářů objekty používají, nikdy se OOP vlastně ani pořádně nenaučili. Buď z objektů dělají jen skladiště na funkce, objekt potom nereprezentuje zodpovědnost, ale namespace. Nebo si projekt plní singletony a statickými metodami, protože je pro ně nutnost předávat objekt nepohodlná a v podstatě se snaží napodobit neobjektové programování uvnitř objektů. Dál neumí rozlišovat mezi objektem a typem. Pravda, někdy za to může jazyk. Pak se místo předávání PSČ jako typového aliasu obyčejného stringu předává objekt PSČ který má string atribut a getter, který ten string vrátí. Toto jsem na školeních pod výrazem "Obscese primitivy" sám pomáhal šířit, za což se omlouvám. Další používají objekty jen jako přepravky na data, ideálně tam, kde potřebují entitu vzít a poslat někam jako JSON. Takže z databáze přijde pole, vývojář z něj vytvoří entitu, kterou o pár instrukcí znovu převádí na pole, z kterého je JSON. Je tohle něco jiného, než obyčejné plýtvání?

Tam, kde zase OOP funguje velmi dobře, je globálnější úroveň. Při budování paralelně běžících a distribuovaných aplikací jsem přišel na chuť actor-based modelu. Mnohdy s ním lze napsat multhreadovou aplikaci, kde spolu jednotlivé části komunikují a přesto není peklo takovou aplikaci vyvinout. Když se OOP dělá tak, že jednotlivé thready vůbec nesdílejí stav a objekty jsou naprosto izolované (tak, jako je to v actorech), je tento přístup praktický. Je dobré, že je dané rozhraní. Je dobré, že můžu měnit vnitřek bez toho, abych musel přepisovat celý systém. Ale uvnitř této služby nemusí být žádné objekty, stačí thready, kterým přichází zprávy, ony si předávají vnitřní stav v parametrech funkcí a když někdo data potřebuje, tak si je thready navzájem pošlou.

Ve výsledku se pak ukazuje, že na nízké úrovni je velmi praktické používat funkce a datové struktury, zatímco na architekturální úrovni je dobré používat konstrukce podobné OOP (a identické actor based modelu).

Proto když teď školím OOP, ukazuju ty konstrukce, návrhové vzory a principy na komunikujících microslužbách. Na takovém školení nemusím vytvořit jedinou třídu ani instancializovat jediný objekt a přesto se může jednat o objektovou aplikaci.

Jak vypadá Factory u samostatných miniaplikací? Jak adapter? Jak chain of responsibility? Jak observer? Když se podíváte na ZeroMQ, přijdete na to, že všechny tyto věci se dají napsat na pár řádek a dají vám možnost brutálně paralelizovat, distribuovat aplikaci na mnoho serverů, měnit části bez restartu celku, zvládat pád částí atd.

Po té době jsem se s OOP nějak smířil. Objektové koncepty používám, ale nejspíš úplně jinak, než vy. Mám tu simulaci napsanou v Pythonu. Knihovny mě nutí používat objekty, ale vnitřní komunikaci řeším celou pomocí pykka (asi bych přežil i s threading.Eventy, ale nebylo by to vůbec pohodlné). V jednom threadu pak běží simulace, v dalším se hromadí eventy (používám event sourcing), v dalším se hromadí stav generovaný z přicházejících eventů, v dalším běží webová aplikace ve Flasku, která má actora, který buď stáhne stav při 1. načtení, nebo průběžně stahuje eventy a posílá je do SPA, která si pravideln eventy stahuje a aplikuje je ve view.

Tento přístup mi vyhovuje a mám pocit, že takto získávám výhody objektů i funkcionálního programování naráz.

Programování

Předejte zkušenosti i dalším a sdílejte tento článek!

Předchozí článek
Následující článek


Jiří Knesl
Business & IT konzultant

Jiří Knesl poprvé začal programovat v roce 1993. Od té doby, díky skvělým učitelům a později zákazníkům, měl možnost neustále růst v oboru vývoje webových aplikací a informačních systémů. v roce 2002 se přidal zájem o ekonomii a v roce 2006 o organizaci práce. Vším tím se konstantně profesně zabývá jak ve svém podnikání, tak i u zákazníků. Za posledních 5 let vydal na tato témata přes 400 článků.

Prohlédněte si moje reference

Mám zkušenosti z rozsáhlých projektů pro korporace, velké podniky, střední i malé firmy, ale i pro startupy v cloudu. Zvyšoval jsem jejich know-how, pomáhal nastavovat jejich organizační strukturu, byl lektorem a mentorem v náročných situacích. Podívejte se, jak vidí můj přínos samotní klienti.

Sledujte mé postřehy na sociálních sítích