it-swarm-eu.dev

Proč je OOP) obtížné?

Když jsem začal používat objektově orientovaný jazyk (Java), tak jsem prostě šel "Cool" a začal kódovat. Nikdy jsem o tom nepřemýšlel teprve nedávno poté, co jsem četl spoustu otázek o OOP. Celkový dojem, který mám, je, že lidé s tím bojují. Protože jsem o tom nepřemýšlel tak tvrdě a neřekl bych, že jsem žádný génius, myslím, že jsem něco musel nechat ujít, nebo to nepochopil.

Proč je obtížné rozumět OOP) Je obtížné porozumět?

93
gablin

Osobně jsem shledal mechaniku OOP docela snadno pochopitelný. Nejtěžší pro mě bylo „proč“. Když jsem byl poprvé vystaven, vypadalo to jako řešení při hledání problému. Zde je několik důvodů, proč si myslím, že pro většinu lidí je to těžké:

  1. Výuka IMHO OO od začátku je hrozný nápad. Procedurální kódování není „špatným zvykem“ a je správným nástrojem pro některé úlohy. Jednotlivé metody v programu OO mají tendenci vypadat docela procedurálně. Kromě toho, než se naučí procedurální programování dostatečně dobře, aby se jeho omezení zviditelnila, OO se studentovi nezdá příliš užitečný.

  2. Předtím, než opravdu dokážete pochopit OO, musíte znát základy datových struktur a funkce pozdní vazby/vyššího řádu. Je obtížné prohloubit polymorfismus (který v zásadě předává ukazatel na data a spoustu funkcí, které s daty pracují), pokud nerozumíte ani koncepcím strukturování dat namísto pouhého používání primitiv a předávání funkcí vyššího řádu/odkazy na funkce.

  3. Designové vzory by se měly učit jako něco zásadního pro OO, ne něco pokročilejšího. Designové vzory vám pomohou vidět les mezi stromy a dávají relativně konkrétní příklady toho, kde OO může zjednodušit skutečné problémy, a nakonec se je budete chtít naučit. Navíc, jakmile opravdu získáte OO, většina návrhových vzorů bude zřejmá při zpětném pohledu.

120
dsimcha

Myslím, že existuje několik faktorů, které ještě nebyly zmíněny.

Za prvé, alespoň v "čistém OOP" (např. Smalltalk), kde všechno je objekt, musíte otočit svou mysl do poněkud nepřirozené konfigurace, abyste vymysleli číslo (pouze pro jeden příklad) ) jako inteligentní objekt namísto pouhé hodnoty - protože ve skutečnosti 21 (například) opravdu is jen hodnota. To se stává obzvláště problematickým, když na jedné straně vám řekneme, že velkou výhodou OOP je modelování reality blíže, ale začnete tím, že se podíváte na to, co vypadá strašně hodně jako pohled inspirovaný LSD). i těch nejzákladnějších a nejzjevnějších částí reality.

Zadruhé, dědičnost v OOP velmi nenásleduje mentální modely většiny lidí. Pro většinu lidí má klasifikace věcí konkrétně ne kdekoli blízko absolutním pravidlům) nutné vytvořit hierarchii tříd, která funguje. Zejména vytvoření class D, které zdědí od jiného class B znamená, že objekty class D sdílejte absolutně, pozitivně všechny vlastnosti class B. class D může přidat své nové a odlišné vlastnosti, ale všechny charakteristiky class B musí zůstat nedotčeno.

Naopak, když lidé mentálně klasifikují věci, obvykle následují mnohem volnější model. Například, když člověk vytvoří některá pravidla o tom, co tvoří třídu objektů, je docela typické, že téměř každé jedno pravidlo může být porušeno, pokud bude dodrženo dost dalších pravidel. Dokonce i těch několik pravidel, která nemohou být skutečně porušena, je téměř vždy možné trochu „protáhnout“.

Například považujte „auto“ za třídu. Je docela snadné vidět, že obrovská většina toho, co většina lidí považuje za „auta“, má čtyři kola. Většina lidí však viděla (alespoň obrázek) auto s pouze třemi koly. Několik z nás ve správném věku si také pamatuje závodní auto nebo dvě z počátku 80. let (nebo tak), která měla šest kol - a tak dále. To nám dává v podstatě tři možnosti:

  1. Nepřiměřujte nic o tom, kolik kol má auto - ale to vede k implicitnímu předpokladu, že to bude vždy 4, a kód, který se pravděpodobně zlomí pro jiné číslo.
  2. Tvrdit, že všechna auta mají čtyři kola, a ty ostatní klasifikovat jako „ne auta“, i když víme, že skutečně jsou.
  3. Navrhněte třídu, aby umožňovala kolísání počtu kol, jen pro případ, i když existuje dobrá šance, že tato schopnost nebude nikdy potřebována, používána ani řádně testována.

Výuka o OOP) se často zaměřuje na budování obrovských taxonomií - např. Kousky toho, co by byla obrovská hierarchie veškerého známého života na Zemi nebo něco v tomto pořadí. To vyvolává dva problémy: v první řadě to má tendenci vést mnoho lidí k zaměření na obrovské množství informací, které jsou naprosto irelevantní pro danou otázku. V jednom bodě jsem viděl poměrně zdlouhavou diskuzi o tom, jak modelovat plemena psů, a zda (například) “ miniaturní pudl "by měl zdědit" pudl plné velikosti ", nebo naopak, nebo zda by měla existovat abstraktní základní třída" pudl ", z níž by zděděly" pudl plné velikosti "a" miniaturní pudl ". ignorovat bylo, že aplikace se měla zabývat sledováním licencí pro psy, a za tímto účelem bylo zcela postačující mít jedno pole nazvané „plemeno“ (nebo něco v tomto pořadí) bez modelování vztahu mezi plemeny vůbec.

Zadruhé a téměř důležitě to vede k zaměření na vlastnosti položek, namísto na zaměření na vlastnosti, které jsou důležité pro daný úkol. Vede to k modelování věcí tak, jak jsou, kde (po většinu času) to, co je skutečně potřeba, je vytvoření nejjednoduššího modelu, který naplní naše potřeby, a pomocí abstrakce přizpůsobí nezbytné podtřídy, aby vyhovovaly abstrakce jsme vytvořili.

Nakonec ještě jednou řeknu: Jsme pomal po stejné cestě, jakou se ubírají databáze v průběhu let. Časné databáze následovaly hierarchický model. Toto je jediné dědictví kromě soustředění se výhradně na data. Po krátkou dobu následovalo několik databází síťový model - v podstatě identický s vícenásobnou dědičností (a při pohledu z tohoto úhlu se více rozhraní neliší od několika základních tříd, aby si toho všimly nebo se o ně staralo).

Už dávno však databáze do značné míry konvergovaly na relačním modelu (ačkoli nejedná o SQL, jsou na této úrovni abstrakce také relační i současné databáze "NoSQL"). Výhody relačního modelu jsou dostatečně dobře známy, že se jim nebudu obtěžovat opakovat. Budu jen poznamenat, že nejbližším analogem relačního modelu, který máme v programování, je generické programování (a omlouvám se, ale i přes jméno, Java generika, pro jeden příklad, ve skutečnosti se nekvalifikují) , i když jsou malým krokem správným směrem).

57
Jerry Coffin

OOP vyžaduje schopnost abstraktního myšlení; dárek/kletba, kterou má opravdu málo lidí, dokonce i profesionálních programátorů.

26
John Kraft

Jakákoli paradigma vyžaduje, aby většina lidí pochopila určitý tlak „přes okraj“. Podle definice je to nový způsob myšlení, a proto vyžaduje určité množství propuštění starých pojmů a určité množství plného pochopení, proč jsou nové pojmy užitečné.

Myslím, že velkým problémem je, že metody používané k výuce počítačového programování jsou obecně obecně velmi špatné. OOP je nyní tak běžné, že to není tak patrné, ale ve funkčním programování to stále vidíte:

  • důležité pojmy jsou schovány za lichými jmény (FP: Co je monad? OOP: Proč jim někdy říkají funkce a jindy metody?)

  • liché pojmy jsou vysvětleny metaforou namísto toho, co ve skutečnosti dělají, nebo proč byste je použili, nebo proč je někdo kdy myslel použít (FP: Monad je skafandr, zalomí nějaký kód. OOP: An objekt je jako kachna, může vydávat zvuk, chodit a zdědit od zvířete)

  • dobré věci se liší od člověka k člověku, takže není zcela jasné, jaký bude bod zvratu pro každého studenta, a často si učitel ani nevzpomene. (FP: Oh, monadé vám umožňují skrýt něco v samotném typu a pokračovat v tom, aniž byste museli explicitně psát, co se děje pokaždé. OOP: Oh, objekty vám umožňují zachovat funkce pro určitý druh dat s těmito daty.)

Nejhorší z toho je, že, jak ukazuje otázka, někteří lidé se okamžitě uchopí, aby pochopili, proč je koncept dobrý, a jiní ne. To opravdu záleží na tom, co je bodem zlomu. Klíčem pro mě bylo pochopení toho, že objekty ukládají data a metody pro tato data, poté se všechno ostatní hodilo jako přirozené rozšíření. Pak jsem později skočil, jako kdybych si uvědomil, že volání metody z objektu je velmi podobné tomu, jak provést statické volání s tímto objektem jako prvním parametrem.

Malý skok později pomůže vylepšit porozumění, ale je to ten první, který vezme člověka z "OOP nedává smysl, proč to lidé dělají?" „OOP je nejlepší, proč lidé dělají něco jiného?“

21
CodexArcanum

Myslím, že můžete shrnout základní potíže tímto způsobem:

// The way most people think.
Operation - object - parameters
// Example:
Turn the car left.

// The way OOP works conceptually
Object - operation - parameters
// Example:
Car.Turn(270);

Jistě, lidé si mohou zvyknout na mapování „vlevo“ jako 270, a ano, říkat „Car.Turn“ namísto „otočit auto“ není tak velký skok. VUT v Brně, ale aby bylo možné s těmito objekty dobře pracovat a vytvářet je, musíte převrátit to, jak si obvykle myslíte.

Místo manipulace s objektem říkáme objektu, aby skutečně dělal věci sám. Už to nemusí být obtížné, ale říkat oknu, aby se otevřelo, zní zvláštně. Lidé, kteří se k tomuto způsobu myšlení nevyužívají, musí s tou podivností bojovat znovu a znovu, až se konečně nějak stane přirozeným.

21
John Fisher

Protože základní vysvětlení OOP) má velmi, velmi málo společného s tím, jak se používá v terénu. Většina programů pro výuku se snaží použít fyzický model, například „Myslete na auto jako objekt a kola jako objekty, dveře a přenos ... “, ale mimo některé nejasné případy simulačního programování se objekty mnohem častěji používají k reprezentaci nefyzických konceptů nebo k zavedení přesměrování. že to lidi nutí pochopit intuitivně špatným způsobem.

Výuka z návrhových vzorů je mnohem lepší způsob, jak popsat OOP, protože ukazuje programátorům, jak mohou být některé skutečné problémy modelování účinně napadeny objekty, než je popisovat abstraktně.

15
Dan Monego

Nesouhlasím s odpovědí dsimchy z velké části:

  1. Výuka OO od začátku není ve skutečnosti špatný nápad, ani výuka procedurálních jazyků. Důležité je, že učíme lidi psát jasný, výstižný, soudržný kód, bez ohledu na OO nebo procedurální.

  2. Jednotlivé metody v dobrých OO programech NEJSOU inklinující k procedurálnímu pohledu vůbec. To se stává stále více pravdivější s vývojem OO jazyků (čtení C # protože jiný než C++, který je jediný jiný OO jazyk, který znám) a jejich syntaxe, která je každým dnem složitější (lambda, LINQ k objektům atd.). Jediná podobnost mezi OO metody a postupy v procedurálních jazycích je lineární povahou každého, o kterém pochybuji, že se brzy změní.

  3. Nemůžete ovládat procedurální jazyk, aniž byste pochopili datové struktury. Koncept ukazatele je stejně důležitý pro procedurální jazyky jako pro OO jazyky. Předávání parametrů odkazem, které je například běžné v procedurálních jazycích), vyžaduje, abyste porozuměli ukazatelům, jak je to nutné naučit se jakýkoli OO jazyk).

  4. Nemyslím si, že by se návrhové vzory měly učit brzy v OO programování vůbec, protože nejsou zásadní pro programování OO programování vůbec). být dobrým programátorem OO=), aniž by něco věděl o vzorcích vzorů. Ve skutečnosti může člověk dokonce používat dobře známé vzory vzorů, aniž by věděl, že jsou dokumentovány jako takové se správnými jmény a že knihy jsou o nich by se mělo zásadně učit principy designu, jako je Single Responsibility, Open Close a Interface Segregation. Mnoho lidí, kteří se sami považují za programátory OO programátoři v dnešní době), s tím ani nejsou obeznámeni základní koncept, nebo si to prostě nevšímejte, a proto máme tolik odpadků OO kód tam venku). Teprve po důkladném pochopení těchto a dalších principů by měly být zavedeny vzory designu.

Abychom odpověděli na původní otázku autora, ano, OO je těžší pochopení pojmu než procedurální programování. Je to proto, že nemyslíme na vlastnosti a metody objektů skutečného života. Například lidské mozek snadno nepovažuje „TurnOn“ za metodu televize, ale vidí ji jako funkci lidského zapnutí televizoru. Podobně je polymorfismus cizím konceptem lidského mozku, který obecně vidí každý objekt skutečného života pouze jedním “ face ". Dědičnost pro naše mozky není přirozená. Jen proto, že jsem vývojář, neznamená, že by mým synem byl jeden. Obecně řečeno, lidský mozek musí být vyškolen, aby se učil OO) procedurální jazyky jsou pro něj přirozenější.

13
SoftwareRockstar

Myslím, že mnoho programátorů má potíže s prvotním návrhem a plánováním, které má začít. I když pro vás někdo udělá veškerý design, je stále možné se odtrhnout od principů OOP=). Pokud vezmu spoustu špagetového kódu a vyhodím ho do třídy, je to opravdu OOP? Někdo, kdo nerozumí OOP) může stále programovat v Javě. Nezaměňujte však potíže s porozuměním s tím, že nechcete dodržovat určitou metodologii nebo s ním nesouhlasíte.

6
JeffO

Měli byste si přečíst Objekty nikdy? No, stěží někdy. (vyžaduje členství ACM) od Mordechai Ben-Ariho, který navrhuje, že OOP je tak obtížné, protože to není paradigma) to je vlastně přirozené pro modelování čehokoli. (Přestože mám k článku výhrady, protože není jasné, jaká kritéria se cítí, musí program splnit, aby řekl, že je napsán na paradigmatu OOP) na rozdíl od procedurální paradigma používající OO jazyk.)

5
Ken Bloom

Samotné objektově orientované programování není těžké.

Tvrdá část přichází v tom dobře. Kam vložit řez mezi kód, abyste mohli snadno přesunout věci do společného základního objektu a rozšířit je později? Jak učinit váš kód použitelným pro ostatní (rozšířit třídy, zabalit do proxy serverů, přepsat metodu), aniž byste to museli přeskočit přes obruče.

To je těžká část, a pokud se to udělá správně, může být velmi elegantní a pokud se to udělá špatně, může být velmi nemotorný. Moje osobní zkušenost je taková, že vyžaduje hodně praxe, abych byl ve všech situacích, kdy byste si přáli, abyste to udělali jinak, abyste to udělali dost dobře tentokrát čas.

5
user1249

Než jsem byl představen OO, udělal jsem programování GW-Basic a Turbo Pascal docela slušně, takže zpočátku to UDĚLAL udělal mi hlavu.

Nemám ponětí, jestli se to stane ostatním, ale pro mě to bylo takto: můj proces přemýšlení o programování byl čistě procedurální. Jako v: „takové a takové se stane, pak takové a takové se stane dále“ atd. Nikdy jsem nepovažoval proměnné a data za nic víc než prchavé subjekty v průběhu programu. Programování bylo „tokem akcí“.

Předpokládám, že to, co nebylo snadné pochopit (jak hloupé, jak to vypadá teď), byla myšlenka, že data/proměnné skutečně skutečně záleží , v hlubším smyslu, než jen být prchavými herci v programu „flow“. Nebo jinými slovy: Snažil jsem se to pochopit prostřednictvím toho, co se děje , spíše než prostřednictvím toho, co je , což je skutečný klíč k jeho uchopení.

4
Bobby Tables

Právě jsem sledoval video Richarda Feynmana, kde diskutoval o tom, jak mohou lidé ve své hlavě myslet na úplně jiné metodiky - myslím úplně jinak.

Když dělám design na vysoké úrovni, stalo se mi, že vizualizuji objekty, vidím je, vidím jejich rozhraní a vidím, jaké cesty musí informace procházet.

Mám také potíže si vzpomenout na podrobnosti a zjistil jsem, že OO) je skvělá organizační pomoc - mnohem snazší je najít funkčnost než skenování prostřednictvím volně organizovaného seznamu podprogramů.

Pro mě OO byla velká výhoda, ale pokud si vizualizujete stejným způsobem nebo neděláte architekturu na vysoké úrovni, je to pravděpodobně zbytečné a nepříjemné.

4
Bill K

Nemyslím si, že je obtížné to pochopit, ale je možné, že spousta programátorských dotazů je pro tento koncept nová a vychází z procedurálních jazyků.

Z toho, co jsem viděl/přečetl, hodně lidí (alespoň na fórech) hledá „výsledek“ od OOP. Pokud jste procedurální programátor, který se nevrací a neupravuje rozšíření svého kódu, může být obtížné pochopit výhody.

Také tam je spousta špatných OOP===================================================================================.

IMO, musíte počkat, až to „zaklikne“ nebo vás naučí někdo, kdo má skutečné znalosti, nemyslím si, že můžete Rush.

3
DBlackborough

Myslím, že důvod OOP je pro mnohé obtížný) je ten, že to nástroje opravdu neusnadňují.

Počítačové jazyky dnes představují abstrakci toho, co se v počítači děje.

OOP je abstrahovaný způsob, jak reprezentovat abstrakce.

Takže pomocí abstrakce vytváříme abstrakce pomocí abstrakce. K tomu přidejte, že to, co abstraktujeme, jsou obvykle velmi složité fyzické/sociální interakce a není divu.

3
ElGringoGrande

Vlastně mám blog s názvem „Zápasy v objektově orientovaném programování“, který se zrodil z mých zápasů s jeho učením. Myslím, že to bylo pro mě obzvláště obtížné pochopit, protože jsem trávil tolik času procedurálním programováním, a měl jsem těžký čas, abych si pomyslel, že objekt může být reprezentován souborem atributů a chování (byl jsem zvyklý jednoduše soubor proměnných a metod).

Existuje také spousta konceptů, které dělají jazykový objekt orientovaný - dědičnost, rozhraní, polymorfismus, kompozice atd. O jeho teorii se opravdu musí hodně dozvědět, než budete moci skutečně psát kód efektivně a v objektově orientovaném způsobem, zatímco u procedurálního programování je to prostě záležitost pochopení věcí, jako je přidělování paměti pro proměnné, a volání vstupních bodů k jiným metodám.

2
Tim Claason

Motivace. Je těžší se něco naučit, když nevidíte proč a také když se nemůžete podívat na to, co jste udělali, a zjistit, zda jste to udělali správně nebo ne.

Potřebujeme malé projekty, které využívají OO) k tomu, aby dělaly užitečné věci. Navrhl bych prohlédnout si knihu o vzorcích a přijít s tím, který je očividně užitečný a dobře funguje s OO. (I použil strategii jednou, když jsem to zkusil. Něco jako Flyweight nebo Singleton by bylo špatnou volbou, protože jsou to způsoby, jak používat objekty obecně, nepoužívat objekty k dosažení něčeho.)

2
David Thornley