Tak jsem to pročetl... Je-li pan Armstrong spoluautorem Erlangu, je zarážející, že podstatu OOP naprosto, ale NAPROSTO nepochopil:
Ve tvrzeních o Armstrongovi bych byl opatrnější. Když člověk trochu zná výsledky jeho práce, vidí na vlastní oči, jak velice dobře různé problémy Erlangovský tým vyřešil. Člověk občas až žasne, jak u spousty problému zvolili řešení, které prozíravě
předchází problémům, které se (ne)projeví až o několik tahů později. Působí to na mě jako přesný opak třeba javascriptového světa, kde každý krok typicky jeden problém vyřeší a deset nových způsobí
Objection 1: OOP oproti FP "data" a "funkce" spojuje z jednoduchého důvodu, a to, že data bez funkcí jsou k ničemu stejně tak jako funkce bez dat, přičemž funkce jsou vytvořeny pro daná data (to nevylučuje práci s obecnými daty jako v FP!). Myšlenka nutnosti nespojovat funkce a data jen z důvodu, že se jedná o jiné kategorie, je neopodstatněná (to ale neznamená, že to nejde).
Tam jde myslím spíš o to, že OOP svazuje
konkrétní fce s
konkrétními ("svými") daty a tím komplikuje (záměrně - a podle některých chybně) přístup k datům jinými fcemi.
Stupidní příklad: fce List.reverse(list) může fungovat nad listem čehokoli, protože o položkách nic nepředpokládá. Vesele teda jednou jedinou funkcí otáčím listy zákazníků, faktur i planet sluneční soustavy. Když chci totéž udělat u OOP, tak mi tenhle jeden problém exploduje do tisíce dalších: asi teda chci nějaké rozhraní IReversable, nebo chci nějak data zpřístupnit? Nebo pro každý objekt úplně nezávisle napíšu tutéž fci o.reverse()? Co je správně? Co je antipattern? Co porušuje zapouzdření? Neměl by objekt PlanetList dědit z List? No jo, ale já potřebuju, aby dědil z PlanetsOfSolarSystem. Co s tím? Vícenásobná dědičnost? Ale ne, to je fuj. atd.atd.atd. Armstrong tvrdí (nemusíš s ním souhlasit, ale myslím, že to nemůžeš jenom tak šmahem odbýt), že kdybys ty data nesvázal s konkrétními, předem danými funkcemi, měl bys míň problémů.
Objection 2: Různé třídy (typy; či prototypy) pro různé časové údaje se používají v implementacích OOP naprosto běžně - tento bod je nadbytečný.
Ten bod je spíš špatně vysvětlený. Nejde tam imho o to, že máš víc typů, ale že ty typy jsou "ubiquitous and data structures representing times can be manipulated by any function in the system" a že "There are no associated methods.". Čili to souvisí s předchozím a následujícím bodem. Např. na některé typy zachycující čas můžu v FP aplikovat List.reverse, když mi to bude dávat smysl. V OOP by nikdo nepředpokládal, že to budu chtít udělat, takže by neimplementoval IReversable, takže bych musel z Time dědit do svého MyReversableTime, který o IReversable rozšířím, jenže pak ho nemůžu serializovat stejně jako Time, protože na druhé straně MyReversableTime nemám a navíc ... (opět exploze pseudoproblémů)
Objection 3: Všudypřítomné "typy" se realizují třídami či prototypy. Poslední věta fabuluje cosi o nutnosti dědění.
Opět je tam klíčové to "ubiquitous". Prostě na jednom místě mám definováno, jakou strukturu mají data pojmenovaná "List" a používám to všude. Nepotřebuju řešit pseudoproblémy typu "Všechny objekty musí dědit z Object".
Objection 4: Objekty mají skryté stavy, ale nedávno mi tu pan Prýmek vysvětlil na Elixíru, že FP je má taky, akorát je jinak ukládá. Kde je potom rozdíl?
Říká tam, že stav nechceme, protože je s ním opruz, ale nějakým způsobem potřebujeme řešit, protože práce se stavem je cílem programování v reálném světě. Takže stav nějak ošetřit potřebujeme, máme na to několik možností. A Armstrong říká (opět s ním nemusíš souhlasit), že způsob práce se stavem, který zvolilo OOP, je nejhorší možný z dostupných.
---
Btw, velmi doporučuji se kouknout na video, kde Armstrong s Kayem diskutují. Neřekl bych, že by si nějak zvlášť vjížděli do vlasů. Spíš naopak - vypadá to, že oba dva se shodují na tom, že to, co se z OOP stalo, stojí za starou belu
[EDIT: sorry, nějak jsem si spletl Kaye s Johnsonem
]
https://www.infoq.com/interviews/johnson-armstrong-oopJeště je na YT jedno video s nima oběma, to jsem ale zatím neviděl.