Co si myslíte o OOP?

M

Re:Co si myslíte o OOP?
« Odpověď #630 kdy: 07. 01. 2019, 11:44:38 »
Tak to máte docela nízké požadavky na kvalitu. Python je sice syntakticky přehledný a má dost knihoven, takže se v něm rychle dělá, ale ZCELA ZBYTEČNĚ obsahuje neobjektové konstrukce (len(řetězec), ...), na zapouzdření dlabe (přestože implementace by pravděpodobně ani nebyla složitá), definice třídních metod je řešena nekoncepčně přes jakési anotace... To mě napadá jen tak z hlavy, na co jsem stihnul zběžně narazit.
Neobjektové konstrukce nejsou zbytečné, python není oop jazyk, ale hybridní. Jestli mu neco vycist, tak to, ze by default krome len(list) neumi i list.len(). Zapouzdreni ma. Proc povazujete dekoratory za nekoncepcni? Python nepouziva modifikujici klicova slova, ale obecneji fungujici a uzivatelsky nastavitelne dekorarory, coz je koncept.

A jaký má smysl zavádět imperativní konstrukce s objekty, jestliže je to bez přínosu a komplikuje to jazyk i jeho implementaci?
Opravdu se tu nehodlám dohadovat s někým, co je to zapouzdření a zda jej má Python, OPRAVDU NE!
Proč tedy není i u instanční metody anotace "@instancemethod"?

@ není anotace, ale dekorátor. Takovou classmethod si můžete zjednodušeně představit jako wrapper který implementuje interface deskriptoru (__get__). Když python na třídě nebo objektu narazí na deskriptor, tak přenechá implementaci chování toho, co se má vrátit, tomu deskriptoru. A classmethod udělá to, že tu funkci nabinduje ne na objekt, ale na jeho třídu. Jakákoliv funkce sama o sobě má taky metodu __get__, takže pokud je ta funkce položená na třídě, tak při přístupu z instance objektu se vrátí nabindovaná na instanci toho objektu a při volání dostane jako první argument objekt. S deskriptory a __getattribute__/__setattribute__ protokolem se dá hodně vyhrát, myslím si, že i řízení přístupu by se s určitým performance hitem dalo vyrobit, ale proč bych to dělal ...

Ty "neobjektové" funkce si představte jako implementaci určitého protokolu. Díky duck typingu nemusí mít objekt miliardy metod pro všechny možné situace. Proto také můžou existovat věci jako len(), iter(), next(), ... které ho využívají. Pokud vím, že něco je kolekce, len() na to bude fungovat a určitým postupem zjistí, kolik je v ní prvků. Taky můžu udělat např. max(map(len, iterable)). max(map(lambda i: i.len(), iterable)) by bylo krkolomnější. Rubysta by namítl, že iterable.collect(&:len) je lepší, ale každý jazyk má své vlastnosti :)

Dokonce se v pythonu dá udělat isinstance({}, Mapping), kde mapping není rodič třídy dict a přesto to vrátí True. Mapping je totiž ABC třída, která definuje jaké metody má mít něco, co se dá považovat za Mapping. A pokud je objekt má, není nejmenší pochyb o tom, jestli se chová jako Mapping nebo ne.


SB

Re:Co si myslíte o OOP?
« Odpověď #631 kdy: 07. 01. 2019, 12:38:27 »
Funkce get_peer_address() je buď metoda třídy network_socket bez parametrů, nebo je to samostatná funkce (nebo klidně metoda třídy address_extractor) s jedním parametrem typu network_socket.

Jak dostane ta "samostatná funkce", nebo třída address_extractor z toho socketu tu adresu???

Návratová hodnota je typu socket_address, což je polymorfní typ zahrnující IPv4, IPv6 i řetězce (používané jako jména UNIX domain socketů).

Co je to "polymorfní typ"?

Testy už píšu jen na ověření chování této funkce se smysluplnými typy parametrů.

Jasně, když je to jen pro smysluplné typy parametrů, tak to vlastně testy ani nejsou.

SB

Re:Co si myslíte o OOP?
« Odpověď #632 kdy: 07. 01. 2019, 12:49:21 »
K tomu mě napadá akademická otázka: Dá se pro libovolný program napsat testovací sada, která nalezne všechny chyby, jež by nalezla statická typová kontrola, a přitom nebude zahrnovat (jakkoliv zakamuflovanou) statickou typovou kontrolu?

Přeloženo: Dá se mechanismus statické kontroly nahradit jiným mechanismem statické kontroly, aniž by byl tomu prvnímu podobný? (Jestli jsem to správně pochopil, předpokládá se formální kontrola zdrojáku, ne běhová.)

Jaký má daná snaha smysl?

Kit

Re:Co si myslíte o OOP?
« Odpověď #633 kdy: 07. 01. 2019, 13:16:39 »
Fakt nechápu, co tu řešíte. Když vemu ten úžasný Python, tak pokud mám methodu:
Kód: [Vybrat]
def get_record(self, data):
Tak co ta metoda vrací? A co jí mám poslat? Fakt někdo chce takový jazyk používat na víc než na hraní a skriptíky?

Tak především jste v uvedeném případě udělal jednu z nejzákladnějších a nejhorších chyb v psaní kódu (standard většiny "vývojářů"), to je, že jste špatně pojmenoval jak metodu, tak její druhý parametr nicneříkajícím označením. A jestli si myslíte, že typovaně

Propocet get_record(Object self, Integer data)

to bude lepší, tak se mýlíte.

Velmi výstižné. Hlavně však nepoužívat v těch názvech maďarskou notaci. Když pak někdo změní typ dat, vypadá to fakt blbě a metoda se musí zbytečně přejmenovávat.

Kit

Re:Co si myslíte o OOP?
« Odpověď #634 kdy: 07. 01. 2019, 13:24:18 »
K tomu mě napadá akademická otázka: Dá se pro libovolný program napsat testovací sada, která nalezne všechny chyby, jež by nalezla statická typová kontrola, a přitom nebude zahrnovat (jakkoliv zakamuflovanou) statickou typovou kontrolu?

Přeloženo: Dá se mechanismus statické kontroly nahradit jiným mechanismem statické kontroly, aniž by byl tomu prvnímu podobný? (Jestli jsem to správně pochopil, předpokládá se formální kontrola zdrojáku, ne běhová.)

Jaký má daná snaha smysl?

O něco podobného se snaží například PHPStan. Smyslem je udělat zdrojáky čitelnější, s menším množstvím záludností. Ovšem pojmenování věcí, které je pro OOP zásadní, neřeší. Nemá ani jak.


SB

Re:Co si myslíte o OOP?
« Odpověď #635 kdy: 07. 01. 2019, 15:06:35 »
(dle pravidla Liskovové).
A ještě lepší by bylo tam podtypový polymorfismus vůbec nemít, ušetřili bysme si spoustu bolehlavů ;)

Do důsledku vzato pak ale rovnou můžu říct, že typované zprávy jsou na hovno, a pořeším si ověření parametrů na začátku metody jak chci, do jaké hloubky chci a podle čeho chci, čímž se opět vracíme k tomu, že samotná typová kontrola nemusí stačit.

SB

Re:Co si myslíte o OOP?
« Odpověď #636 kdy: 07. 01. 2019, 15:29:31 »
Příklad: Mám batoh s danou nosností a objemem a (netypový) seznam blíže neurčených předmětů (= nezajímá mě, co to je), jejichž jediným společným prvkem (a to ještě ne nutně) je, že odpovídají na zprávu "hmotnost" a "velikost", a chci zjistit, zda se mi do toho batohu vlezou. Jak se to řeší typovaným seznamem???
Proč je tam to "ne nutně"? Pokud chci zjistit, jestli se mi tam vlezou, pak musí na ty zprávu odpovídat nutně, jinak nemůžu rozhodnout, jestli se mi tam vlezou.

Je to tam schválně, protože se dokonce v krajním případě můžu rozhodnout, že co neodpoví na zprávu (ověřením odpovídatelnosti objektu, nebo zachycením chyby), buďto do batohu nepůjde, nebo celá metoda vrátí chybu, nebo odpověď False, nebo já nevím co. Prostě se můžu rozhodnout, aniž bych věděl, co za bordel v tom seznamu je.

Pak taky není pravda to "netypový" a "nezajímá mě, co to je". "Netypový" by znamenalo, že o těch objektech nemám vůbec žádnou informaci. Já ale nějakou mám: odpovídají na zprávu "hmotnost" a "velikost". To je typ.  (Odbočka: ) Přesvědčení, že to typ není, vychází imho z internalizace zparchantělého OOP založeného jenom na dědičnosti.

Jak by se to vyřešilo? Snadno. Už víme, že ty objekty mají nějaký typ. Stačí ho pojmenovat (např. HasWeightAndDimension) a pak už snadno můžu říct, že pracuju s polem HasWeightAndDimension[].

Přesně!
Nezajímá mě ve smyslu statických typů. Píšete to správně, za typ "weight" můžeme považovat i schopnost odpovídat na zprávu "weight", pak tyto "vícetypové" objekty se vzájemně různě prolínají v některých typech. Lepší by bylo ale označovat je za "vzájemně polymorfní v metodách", či "vzájemně polymorfní v nějaké jejich společné části protokolu". Neboli v Kayově (zprávovém) OOP nejde o polymorfismus typový/třídní (nekteré objekty typ ani mít nemusejí, třeba ad-hoc), ale polymorfismus zprávový/protokolový (třeba i jen částečný).
Je to tak?

Jak to přesně technicky udělat, na to asi bude víc způsobů. Jeden konkrétní je třeba ten, který ma Go: struktury implementují rozhraní implicitně - tj. jakmile jsou pro strukturu definované všechny potřebné metody, je interface implementovaný, není potřeba to explicitně prohlašovat.

To je ale opět onen protokol objektu.

Re:Co si myslíte o OOP?
« Odpověď #637 kdy: 07. 01. 2019, 15:32:54 »
Funkce get_peer_address() je buď metoda třídy network_socket bez parametrů, nebo je to samostatná funkce (nebo klidně metoda třídy address_extractor) s jedním parametrem typu network_socket.

Jak dostane ta "samostatná funkce", nebo třída address_extractor z toho socketu tu adresu???

Původně jsem reagoval na návrh, že výpis informací o objektu nemá dělat metoda print(), ale samostatná třída Printer. Ta se taky musí nějak dostat k informacím, které má vypsat. Třída address_extractor funguje v principu stejně.

Návratová hodnota je typu socket_address, což je polymorfní typ zahrnující IPv4, IPv6 i řetězce (používané jako jména UNIX domain socketů).

Co je to "polymorfní typ"?

https://en.cppreference.com/w/cpp/language/object#Polymorphic_objects

Testy už píšu jen na ověření chování této funkce se smysluplnými typy parametrů.

Jasně, když je to jen pro smysluplné typy parametrů, tak to vlastně testy ani nejsou.

I když vím, že get_peer_address dostane socket, musím otestovat, že ze socketu extrahuje a vrátí správnou adresu a ne nějaká náhodná data. Jenom se nemusím zabývat testováním reakce na situaci, kdy dostane něco jiného než socket, protože statická typová kontrola zajistí, že to nemůže nastat.

Re:Co si myslíte o OOP?
« Odpověď #638 kdy: 07. 01. 2019, 15:41:42 »
K tomu mě napadá akademická otázka: Dá se pro libovolný program napsat testovací sada, která nalezne všechny chyby, jež by nalezla statická typová kontrola, a přitom nebude zahrnovat (jakkoliv zakamuflovanou) statickou typovou kontrolu?

Přeloženo: Dá se mechanismus statické kontroly nahradit jiným mechanismem statické kontroly, aniž by byl tomu prvnímu podobný? (Jestli jsem to správně pochopil, předpokládá se formální kontrola zdrojáku, ne běhová.)

Jaký má daná snaha smysl?

Reagoval jsem na tvrzení, že místo statické typové kontroly mohu použít dynamickou typovou kontrolu a testy. Statická typová kontrola zabrání určité třídě chyb v programu, protože nepovolí použití neočekávaných typů. Pokud mají být testy plnohodnotnou náhradou, měly by všechny tyto chyby odchytit taky (nepřu se o to, že testy mohou zachytit i spoustu jiných chyb, na které naopak nestačí typová kontrola). Je mi celkem jedno, jak budou testy vypadat, ale aby odpověď nebyla triviální, neměly by zahrnovat nic, co je jen převlečená statická typová kontrola přesunutá z kompilátoru do testovacího prostředí (tedy žádná statická analýza zdrojáků s použitím typových anotací).

SB

Re:Co si myslíte o OOP?
« Odpověď #639 kdy: 07. 01. 2019, 15:58:07 »
@ není anotace, ale dekorátor. Takovou classmethod si můžete zjednodušeně představit...

Je mi buřt, jak se to jmenuje (dekorátor je pro mě návrhový vzor), vnitřní implementace je nepodstatná. Představoval bych si, že vedle klíčového slova def tu bude např. classdef, aby bylo jasné, co je definováno na třídní a co na instanční straně. Tyto anotace/dekorátory na mě dělají dojem dobastlovaného jazyku.

Ty "neobjektové" funkce si představte jako implementaci určitého protokolu. Díky duck typingu nemusí mít objekt miliardy metod pro všechny možné situace. Proto také můžou existovat věci jako len(), iter(), next(), ... které ho využívají. Pokud vím, že něco je kolekce, len() na to bude fungovat a určitým postupem zjistí, kolik je v ní prvků. Taky můžu udělat např. max(map(len, iterable)). max(map(lambda i: i.len(), iterable)) by bylo krkolomnější. Rubysta by namítl, že iterable.collect(&:len) je lepší, ale každý jazyk má své vlastnosti :)

Nechápu. Proč budu "určitým postupem" zjišťovat, kolik je v kolekci prvků, když se jí můžu rovnou zeptat? Oč jsou uvedené funkce jednodušší, koncepčnější a přehlednější než seznam.len(), seznam.forEach(), seznam.max(), ... Tohle se mi jeví jako zbytečný bastl za účelem lezení do zadku uživatelům zvyklým na imperativní jazyky.

Kit

Re:Co si myslíte o OOP?
« Odpověď #640 kdy: 07. 01. 2019, 16:07:49 »
Statická typová kontrola zabrání určité třídě chyb v programu, protože nepovolí použití neočekávaných typů. Pokud mají být testy plnohodnotnou náhradou, měly by všechny tyto chyby odchytit taky (nepřu se o to, že testy mohou zachytit i spoustu jiných chyb, na které naopak nestačí typová kontrola). Je mi celkem jedno, jak budou testy vypadat, ale aby odpověď nebyla triviální, neměly by zahrnovat nic, co je jen převlečená statická typová kontrola přesunutá z kompilátoru do testovacího prostředí (tedy žádná statická analýza zdrojáků s použitím typových anotací).

Při statickém typování se neobejdeš bez testů, používáš tedy dva kontrolní mechanismy. Cílem tvůrců Smalltalku bylo tyto dva mechanismy sloučit do jednoho, tedy do testů. U dynamicky typovaných jazyků jsou tedy v testech i kontroly typů.

Naproti tomu se mi typové anotace nelíbí, to už raději v hlavičce metody ten typ použiji. Problém však nastane, pokud jsou přípustné paranetry různých typů. U statického typování se to řeší přetěžováním, což může pro různé kombinace typů parametrů znamenat značné množství metod. U dynamického se to může vyřešit v jedné metodě.

BaldSlattery

Re:Co si myslíte o OOP?
« Odpověď #641 kdy: 07. 01. 2019, 16:12:35 »
Viděl jsi často, že by hostinský točil pivo do papírové krabice, přestože mu v tom nic nebrání? Jistě by šlo zařídit, aby se pípa odjistila jen v případě, že pod sebou detekuje konkrétně určený značkový půllitr. Mě by popadl rapl a ta pípa by letěla na smetiště hned v okamžiku, kdy by mi odmítala pustit pivo do džbánku.
Smysl statických typů je zajistit, aby se něco takového nestalo. Když zůstaneme u přirovnání, tak ty budeš muset hostinského zaškolit, a ještě nainstalovat kameru, aby si ho sledoval, zda nečepuje pivo přímo do pusy. A stejně ho neuhlídáš. Zatímco já tam budu moct dát cedulku "samoobslužná pípa".


Nemá smysl řešit, že použijete např. typový seznam, když to potřebujete. Problémem u statických jazyků je použití seznamu v případě, kdy v něm potřebujete různé prvky.

Příklad: Mám batoh s danou nosností a objemem a (netypový) seznam blíže neurčených předmětů (= nezajímá mě, co to je), jejichž jediným společným prvkem (a to ještě ne nutně) je, že odpovídají na zprávu "hmotnost" a "velikost", a chci zjistit, zda se mi do toho batohu vlezou. Jak se to řeší typovaným seznamem???
Rozhraním, ne? V ObjC se to jmenuje protokol, řekne se, jakou metodu má implementovat, a zbytek už je triviální.

operator

Re:Co si myslíte o OOP?
« Odpověď #642 kdy: 07. 01. 2019, 16:12:45 »
Tak to máte docela nízké požadavky na kvalitu. Python je sice syntakticky přehledný a má dost knihoven, takže se v něm rychle dělá, ale ZCELA ZBYTEČNĚ obsahuje neobjektové konstrukce (len(řetězec), ...), na zapouzdření dlabe (přestože implementace by pravděpodobně ani nebyla složitá), definice třídních metod je řešena nekoncepčně přes jakési anotace... To mě napadá jen tak z hlavy, na co jsem stihnul zběžně narazit.
Neobjektové konstrukce nejsou zbytečné, python není oop jazyk, ale hybridní. Jestli mu neco vycist, tak to, ze by default krome len(list) neumi i list.len(). Zapouzdreni ma. Proc povazujete dekoratory za nekoncepcni? Python nepouziva modifikujici klicova slova, ale obecneji fungujici a uzivatelsky nastavitelne dekorarory, coz je koncept.
A jaký má smysl zavádět imperativní konstrukce s objekty, jestliže je to bez přínosu a komplikuje to jazyk i jeho implementaci?
Opravdu se tu nehodlám dohadovat s někým, co je to zapouzdření a zda jej má Python, OPRAVDU NE!
Proč tedy není i u instanční metody anotace "@instancemethod"?
Smysl je ve flexibilite. Zadne paradigma neni objektivne lepsi nez jine a pro ruzne situace muze byt jednou vhodnejsi to a podruhe ono, v Pythonu si je lze podle potřeby vybrat a kombinovat je, zlepsuje to vyjadrovaci prostredky jazyka. To je bez pochyby prinosne a obliba Pythonu prokazuje, ze to za pripadne komplikace stoji.

Nedohadujte se, Python zapouzdreni ma, at se vam to libi nebo ne. Zapouzdreni je abstrakce, ktera progranatorum umoznuje urcity pristup k programovani a Python tento pristup umoznuje.

@instancemethod neni anotace, ale dekorator a tento tam neni, protoze je to vychozi chovani. Stejne byste se mohl ptat, proc se v matematice nepise + pred kladnymi cisly, kdyz u zapornych se pise -.

operator

Re:Co si myslíte o OOP?
« Odpověď #643 kdy: 07. 01. 2019, 16:16:04 »
Statická typová kontrola zabrání určité třídě chyb v programu, protože nepovolí použití neočekávaných typů. Pokud mají být testy plnohodnotnou náhradou, měly by všechny tyto chyby odchytit taky (nepřu se o to, že testy mohou zachytit i spoustu jiných chyb, na které naopak nestačí typová kontrola). Je mi celkem jedno, jak budou testy vypadat, ale aby odpověď nebyla triviální, neměly by zahrnovat nic, co je jen převlečená statická typová kontrola přesunutá z kompilátoru do testovacího prostředí (tedy žádná statická analýza zdrojáků s použitím typových anotací).

Při statickém typování se neobejdeš bez testů, používáš tedy dva kontrolní mechanismy. Cílem tvůrců Smalltalku bylo tyto dva mechanismy sloučit do jednoho, tedy do testů. U dynamicky typovaných jazyků jsou tedy v testech i kontroly typů.

Naproti tomu se mi typové anotace nelíbí, to už raději v hlavičce metody ten typ použiji. Problém však nastane, pokud jsou přípustné paranetry různých typů. U statického typování se to řeší přetěžováním, což může pro různé kombinace typů parametrů znamenat značné množství metod. U dynamického se to může vyřešit v jedné metodě.

Typove anotace jsou dobra pomucka, svuj smysl maji treba u verejneho rozhrani. Vyhodou u nich je, ze nejsou povinne, takze je programator je nemusi otrocky pouzivat tam, kde nemaji smysl nebo dokonce program zbytecne komplikuji.

Kit

Re:Co si myslíte o OOP?
« Odpověď #644 kdy: 07. 01. 2019, 16:17:15 »
Proč budu "určitým postupem" zjišťovat, kolik je v kolekci prvků, když se jí můžu rovnou zeptat? Oč jsou uvedené funkce jednodušší, koncepčnější a přehlednější než seznam.len(), seznam.forEach(), seznam.max(), ... Tohle se mi jeví jako zbytečný bastl za účelem lezení do zadku uživatelům zvyklým na imperativní jazyky.

Vývojář by se především měl zeptat sám sebe, zda ten počet prvků potřebuje k dosažení cíle. Například zmíněné metody seznam.forEach(), seznam.max() tuto potřebu zpravidla eliminují.