Co si myslíte o OOP?

paranoik

Re:Co si myslíte o OOP?
« Odpověď #480 kdy: 05. 01. 2019, 22:23:09 »
Toto není problém dynamicky typovaných jazyků, ale pouze tohoto příkladu.

Toto je problém dynamicky typovaných jazyků. Ve staticky typovaném jazyce můžeš napsat vypis jako generickou funkci a dostaneš naprosto stejnou funkcionalitu jaku v pythonu. Když tu funkci píšeš, nemusíš znát konkrétní typ. Jako bonus navíc máš typovou kontrolu během překladu, funce vypis nepujde zavolat s nečím, co není iterable a printable a v runtime to bude rychlejší než dynamicky typovaný jazyk, protože v runtime se už žádné typové kontroly dělat nemusí.


Kit

Re:Co si myslíte o OOP?
« Odpověď #481 kdy: 05. 01. 2019, 22:24:58 »
Tento příklad krásně ilustruje problém dynamicky typovaných jazyků. Procedura vypis() implicitně předpokládá, že parametr kolekce se dá iterovat a že iterací dostanu objekty, pro které má smysl volat print().
Toto není problém dynamicky typovaných jazyků, ale pouze tohoto příkladu. Navíc je to napsané spíš strukturovaně, než s OOP.
V OOP by pro výpis sloužila samostatná třída (nějaký Printer), s pomocí návrhového vzoru Visitor by si implementovala sama tu metodu print(), nebo by ji delegovala na ty prvky, u kterých to potřebuji. Navíc ve skutečnosti vůbec nemusí záležet na tom, zda chci vypsat kolekci, prvek, a nebo třeba rekurzivně nějaký Composite

Na příkladu jsem použil Occamovu břitvu, abych ukázal principy, které pochopí i propagátoři statického typování. Bylo by zbytečné ji obalovat nějakými plechy na bojlery.

V OOP vůbec není potřebné, aby se o výpis staraly nějaké další třídy. Stačí, když se budeme držet SOLID.

Kit

Re:Co si myslíte o OOP?
« Odpověď #482 kdy: 05. 01. 2019, 22:29:46 »
Toto není problém dynamicky typovaných jazyků, ale pouze tohoto příkladu.

Toto je problém dynamicky typovaných jazyků. Ve staticky typovaném jazyce můžeš napsat vypis jako generickou funkci a dostaneš naprosto stejnou funkcionalitu jaku v pythonu. Když tu funkci píšeš, nemusíš znát konkrétní typ. Jako bonus navíc máš typovou kontrolu během překladu, funce vypis nepujde zavolat s nečím, co není iterable a printable a v runtime to bude rychlejší než dynamicky typovaný jazyk, protože v runtime se už žádné typové kontroly dělat nemusí.

Generika jsou pouze berličkou, aby se ve staticky typovaných jazycích dalo dělat totéž co v dynamicky typovaných. Stále však budu chtít zavolat tu proceduru třeba se stringem.

Rychlost je dobrý důvod, proč používat staticky typované jazyky. Ovšem které? Java ani C# mezi ně nepatří.

paranoik

Re:Co si myslíte o OOP?
« Odpověď #483 kdy: 05. 01. 2019, 22:39:08 »
Generika jsou pouze berličkou, aby se ve staticky typovaných jazycích dalo dělat totéž co v dynamicky typovaných. Stále však budu chtít zavolat tu proceduru třeba se stringem.

Znovu opakuji, když to napíšeš jako generickou funkci ve staticky typovaném jazyce, získáš navíc typovou kontrolu během překladu a vyšší výkon. Se stringem to půjde zavolat taky.

Dynamické typování v tomto případě nemá žádnou výhodu. Bude to pomalejší a na chyby v programu se přijde až v runtime, kdy to celé spadne. Tvoje zásadní neznalosti vedou k tomu, že nedokážeš rozlišit, kdy a na co je kterou technologii vhodné použít.

Re:Co si myslíte o OOP?
« Odpověď #484 kdy: 05. 01. 2019, 22:42:55 »
Tento příklad krásně ilustruje problém dynamicky typovaných jazyků. Procedura vypis() implicitně předpokládá, že parametr kolekce se dá iterovat a že iterací dostanu objekty, pro které má smysl volat print().
Toto není problém dynamicky typovaných jazyků, ale pouze tohoto příkladu. Navíc je to napsané spíš strukturovaně, než s OOP.
V OOP by pro výpis sloužila samostatná třída (nějaký Printer), s pomocí návrhového vzoru Visitor by si implementovala sama tu metodu print(), nebo by ji delegovala na ty prvky, u kterých to potřebuji. Navíc ve skutečnosti vůbec nemusí záležet na tom, zda chci vypsat kolekci, prvek, a nebo třeba rekurzivně nějaký Composite

Zrovna print() není úplně dobrý příklad, protože "nějak smysluplně vypsat" se dají vypsat hodnoty libovolného typu. Ale třeba get_peer_address() má jistě smysl pro třídu network_socket. Hůř se ale bude hledat význam takové funkce pro string nebo int a s tím mi nepomůže, když tu funkci přesunu do samostatné třídy address_extractor. Jde mi o to, že některé operace nemají pro nějaké typy smysl, buď obecně nebo v kontextu konkrétního řešeného problému. Jakákoliv runtime reakce na volání takové operace s nevhodným typem argumentu je špatně, protože v prvé řadě nemělo dojít k tomu zavolání. Tedy jedná se o chybu v programu, kterou je nutno řešit úpravou kódu. Statické typování mi takovou chybu odhalí včas a bez toho, abych musel kvůli diagnostice psát víc, než jméno typu.


Kit

Re:Co si myslíte o OOP?
« Odpověď #485 kdy: 05. 01. 2019, 22:46:17 »
Dynamické typování v tomto případě nemá žádnou výhodu. Bude to pomalejší a na chyby v programu se přijde až v runtime, kdy to celé spadne.

Při chybě v programu to spadne už v testech - stejně jako při statickém typování.

paranoik

Re:Co si myslíte o OOP?
« Odpověď #486 kdy: 05. 01. 2019, 22:50:41 »
Při chybě v programu to spadne už v testech - stejně jako při statickém typování.

Při statickém typování to nepůjde vůbec přeložit, chybu zjistíš ještě dřív, než napíšeš jedinou řádku testů.

Re:Co si myslíte o OOP?
« Odpověď #487 kdy: 05. 01. 2019, 22:53:46 »
Dynamické typování v tomto případě nemá žádnou výhodu. Bude to pomalejší a na chyby v programu se přijde až v runtime, kdy to celé spadne.

Při chybě v programu to spadne už v testech - stejně jako při statickém typování.

Pokud máš plné pokrytí. Za předpokladu jedné unity.

Pokud píšeš libku nebo nedejte bozi framework, tak se ti tohle ještě dál komplikuje...

BaldSlattery

Re:Co si myslíte o OOP?
« Odpověď #488 kdy: 05. 01. 2019, 22:55:58 »
Teoreticky. Prakticky treba kdyz mas getXs(), tak podle typu vis, zda mohou byt xka duplicitni (list vs. set).
K čemu potřebuješ rozlišovat list vs. text? Dostaneš kolekci a budeš s ní tak i pracovat.
On je tam trochu sémantický rozdíl, víme? A z toho typu vysloveně svítí.
Sémantický rozdíl nevidím. Seznam autorů nebo množina autorů? Pro mne je to kolekce autorů a budu s ní pracovat tak, aby když někdo vymění list za set, mi to mohlo být jedno.
Pokud ti není jasný rozdíl mezi sémantikou listu a setu, tak je asi problém na tvém přijímači.

(Btw zrovna tady máš ještě o problém navíc, protože se rozlišuje první autor, korespondující autor...)

Kód: [Vybrat]
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def vypis(kolekce):
    print(type(kolekce))
    for i in kolekce:
        print(i)
    print()

seznam = ["Alfa", 42, 42, ("Beta", "Gamma")]
mnozina = {"Alfa", 42, 42, ("Beta", "Gamma")}
vypis(seznam)
vypis(mnozina)
Jak vidíš, tak proceduře vypis() je v daném případě jedno, zda jí předhodíš seznam nebo množinu. Vypíše obojí. Pokud je budu potřebovat rozlišit, stále ještě mohu použít reflexi.
Jde-li jen o (úsporný) zápis, tak v C++ to jde stejně jednoduše (bez explicitních typů):
Kód: [Vybrat]
auto printElements(auto coll) {
  for (auto el : coll) {
    std::cout << el << std::endl;
  }
}

int main() {
  std::vector<int> v{1, 2, 3};
  printElements(v);
  std::set<int> s{4, 5, 6};
  printElements(s);
  printElements("abc"s);
}
Ještě nějaký jiný problém s typy?

Honza

Re:Co si myslíte o OOP?
« Odpověď #489 kdy: 05. 01. 2019, 22:56:56 »
Při chybě v programu to spadne už v testech - stejně jako při statickém typování.

Při statickém typování to nepůjde vůbec přeložit, chybu zjistíš ještě dřív, než napíšeš jedinou řádku testů.

Tohle je tady mylně považováno za výhodu statických jazyků, ale ten program nepůjde přeložit vůbec úplně celý.
Přitom v dynamickém jazyce mi ta hotová část programu může už dávno běžet...

Re:Co si myslíte o OOP?
« Odpověď #490 kdy: 05. 01. 2019, 23:01:10 »
Generika jsou pouze berličkou, aby se ve staticky typovaných jazycích dalo dělat totéž co v dynamicky typovaných.

Tahle věta platí pro třídu Object v Javě, nebo void* a makra v C. Naopak generika v Javě nebo šablony v C++ přidávají něco navíc - možnost definovat chování nějaké třídy, jejíž objekty se nějakým způsobem starají o objekty jiných tříd (typický příklad jsou kolekce nebo chytré ukazatele), bez znalosti typu vnitřních objektů, ale zároveň při použití takové generické třídy mít možnost omezit, co může obsahovat. Je to přesně jako v tom příkladu s Iterable<Printable> versus Iterable<Object>, mám kolekci objektů, jejíž implementace procházení obsažených objektů nezávisí na typu obsažených objektů, ale chci vynutit (staticky v době překladu), že při konkrétním použití budou ty obsažené objekty něco umět.

Re:Co si myslíte o OOP?
« Odpověď #491 kdy: 05. 01. 2019, 23:03:14 »
Při chybě v programu to spadne už v testech - stejně jako při statickém typování.

Při statickém typování to nepůjde vůbec přeložit, chybu zjistíš ještě dřív, než napíšeš jedinou řádku testů.

Tohle je tady mylně považováno za výhodu statických jazyků, ale ten program nepůjde přeložit vůbec úplně celý.
Přitom v dynamickém jazyce mi ta hotová část programu může už dávno běžet...

A na to jsi přišel jak?

DotNetGuy

Re:Co si myslíte o OOP?
« Odpověď #492 kdy: 05. 01. 2019, 23:03:42 »
Kite, už nikdy nezmiňuj Javu, ale místo ní C#. Vytlučem jí Linuxákum z hlavy a všichni budou používat C#.

Jinak, nechápu proč se tu furt dokola omílá statický vs dynamický typování.

Dynamické typování v tomto případě nemá žádnou výhodu. Bude to pomalejší a na chyby v programu se přijde až v runtime, kdy to celé spadne.

Přesně to jsem chtěl napsat. Statickym typovánim nic nezkazíš a nechápu, proč se mu někteří tak brání. Dynamický tě může (ale nemusí) rychle přivést do problémů a navíc žere výkon.

Honza

Re:Co si myslíte o OOP?
« Odpověď #493 kdy: 05. 01. 2019, 23:05:09 »
Tento příklad krásně ilustruje problém dynamicky typovaných jazyků. Procedura vypis() implicitně předpokládá, že parametr kolekce se dá iterovat a že iterací dostanu objekty, pro které má smysl volat print().
Toto není problém dynamicky typovaných jazyků, ale pouze tohoto příkladu. Navíc je to napsané spíš strukturovaně, než s OOP.
V OOP by pro výpis sloužila samostatná třída (nějaký Printer), s pomocí návrhového vzoru Visitor by si implementovala sama tu metodu print(), nebo by ji delegovala na ty prvky, u kterých to potřebuji. Navíc ve skutečnosti vůbec nemusí záležet na tom, zda chci vypsat kolekci, prvek, a nebo třeba rekurzivně nějaký Composite

Zrovna print() není úplně dobrý příklad, protože "nějak smysluplně vypsat" se dají vypsat hodnoty libovolného typu. Ale třeba get_peer_address() má jistě smysl pro třídu network_socket. Hůř se ale bude hledat význam takové funkce pro string nebo int a s tím mi nepomůže, když tu funkci přesunu do samostatné třídy address_extractor.

Tak částečně souhlas, ale ta samostatná třída pomůže v jiné věci. Můžu chtít vypsat totéž několika způsoby. K tomu ale nebudu mít metody print1, print2, print3...

Ale šlo mi o trochu něco jiného. Dávají se sem nějaké příklady, a na jejich základě se pak hodnotí obecně celá rodina programovacích jazyků... V takovém případě by ty příklady musely vypadat hodně jinak!

Kit

Re:Co si myslíte o OOP?
« Odpověď #494 kdy: 05. 01. 2019, 23:11:04 »
... Ale třeba get_peer_address() má jistě smysl pro třídu network_socket. Hůř se ale bude hledat význam takové funkce pro string nebo int a s tím mi nepomůže, když tu funkci přesunu do samostatné třídy address_extractor. Jde mi o to, že některé operace nemají pro nějaké typy smysl, buď obecně nebo v kontextu konkrétního řešeného problému. Jakákoliv runtime reakce na volání takové operace s nevhodným typem argumentu je špatně, protože v prvé řadě nemělo dojít k tomu zavolání. Tedy jedná se o chybu v programu, kterou je nutno řešit úpravou kódu. Statické typování mi takovou chybu odhalí včas a bez toho, abych musel kvůli diagnostice psát víc, než jméno typu.

get_peer_address() má jako parametr int32, string nebo je to jedno? Návratová hodnota je big endian nebo little endian? Pro diagnostiku musíš psát i testy. Co když dostaneš 0.0.0.0 nebo 255.255.255.255? Bude to v pořádku?