Jak programovat OOP rubrika: Programování: Jiné

4 jednabedna
položil/-a 19.11.2013

Docela jsme se v práci pohádali ohledně toho jak programovat v OOP. Zajímalo by mě jak to dělají jinde, respektive jaký na to máte názor vy, jak vypadá to co tady řešíme v očích nezaujatého člověka. Řešíme to v PHP, ale to je asi jedno.
První názor
Převládající názor je, že by měly v programu existovat pouze dva typy tříd. Jednak třídy, kterým se říká service. Ta může v konstruktoru dostat jako závislosti nějaké jiné servisy a bude mít jednu public metodu. Ideálně nebude mít, žádné private metody, ty by se měly refaktorovat (kvůli znovupoužitelnosti i testovatelnosti) do jiných servisních tříd. Tato třída tedy nikdy nebude nést žádná data.
Druhý druh tříd jsou tak zvané entity. Ty, kromě getterů a setterů nemají žádné metody a pouze přenáší data.
Servisa může jako parametr metod a návratovou hodnotu (kromě primitivních typů) použít pouze entitu nebo pole entit.
Kromě tříd typu service a entity není povolena v programu žádná jiná třída.
Druhý názor
Minoritní názor je, že můžou existovat i jiné typy tříd. Třídy, které ponesou nějaká data a navíc mohou mít i nějaké metody.

Co si o tom myslíte vy?

Komentáře

  • Anonym : http://blog.ircmaxell.com/2013/11/beyond-object-oriented-programming.html http://sourcemaking.com/ 19.11.2013
  • Anonym : to první jsou třídní špagety. dobrou chuť 19.11.2013
  • jednabedna : Aleš Roubíček: Nějaké argumenty? Takový výkřik mi nic nepřinese, chtěl bych se o tom ve firmě pobavit, s tímhle nikam nedojdeme. 19.11.2013
  • Anonym : Jak jinak označit něco, co má na každou metodu samostatnou třídu? Jedna funkce per jeden soubor... Command pattern je pěknej, ale své místo má trochu někde jinde. Pokud to chete konzultovat víc do hloubky, prosím, jsem vám k dispozici za normální tržní konzultantský ceny. ;) 19.11.2013
  • arron : Dobře je to vysvětlené v prvním odkazu od @o5 :-) 19.11.2013
  • Anonym : @jednabedna: Vymýšľat nejaké vlastné striktné rámce v OOP (viď prvý názor) je čistý nezmysel. Treba romzmýšlať, čo je vhodné použiť práve pre daný spôsob užitia (čítaj use-case). Odporúčam kompletne naštudovať http://sourcemaking.com/refactoring 19.11.2013
  • dzejkob : to je zase flame topic 20.11.2013
  • Vašek Ch. : @jednabedna: A ty jsi ze kterého tábora? 20.11.2013
  • jednabedna : Já jsem z druhého tábora. 20.11.2013
  • ic : "Docela jsme se v práci pohádali ohledně toho jak programovat v OOP. Zajímalo by mě jak to dělají jinde" jinde se hádají taky XD 20.11.2013
  • siq : Suhlasim s @Aleš Roubíček, triedne spagety, s takym modelom by som teda pracovat rozhodne nechcel. 20.11.2013
  • Taco : To prvé mi připomíná v hrubých obrysech funkcionální programování. Jen jsem nepochopil, proč by tam neměli být privátní metody? To jako veškerou logiku nacpeš do té hlavní metody? Ano, všiml jsem si, toho refaktorování do jiných servisních tříd. A co volitelné parametry? A co multiple parametry? Objekt samozřejmě může držet data, v tom případě slouží settery jako validace; a nebo může držet stav, v tom případě settery a addery slouží jako konfigurace chování třídy. Myslím si, že ten první názor je příliš rigidní a ten druhý názor je příliš obecný. Představa, že by třída měla mýt nějaké metody, a taky by měla držet data - to je snad jasné, ne? To je i ten první případ. 23.11.2013
  • xxar3s : Nie su to ziadne spagety, ked programator potrebuje objekt, ktory ma jednu metodu tak si vytvori triedu s jednou metodou. Najradsej mam ked si nejaki wannabe mudrlanti vymyslaju obmedzenia a hadzu si polienka pod nohy vymyslaju zlozite systemy, ktore by sa dali nahradit jednou elegantnou funkcoiou (btw funkcia je tiez objekt s jednou metodou Invoke). Howgh - nebudem sa k tejto teme vracat, flamovanie ma obera o cas. 26.11.2013
odkaz
6 arron
odpověděl/-a 19.11.2013

Už z definice objektově orientovaného programování (http://cs.wikipedia.org/wiki/Objektov%C4%9B_orientovan%C3%A9_programov%C...) vyplývá, že objekt si drží svůj stav (čili data ve formě svých atributů) a poskytuje nějaké metody pro práci s nimi.

Už jenom z této věty imho vyplývá, že ten první přístup, který popisuješ je nesmyslný. Ano, své využítí najdou jak servisy, které nemají data (ale rozhodně nesouhlasím s tím, že mají mít jenom jednu metodu, proc?), tak objekty určené jenom pro uložení dat. Ale omezovat se jenom a tyto typy, to by ses ochudil o spoustu prostředků, které Ti OOP poskytuje.

Samozřejmě je potřeba ve správnou chvíli umět použít ty správné prostředky :-)

Private metody mají v OOP jasně vymezené místo a jejich použítí je naprosto v pořádku stejně jako protected a public metod. Private metody obecně testovatelnost neovlivňují, správné použití neovlivňuje ani znovupoužitelnost.

Komentáře

  • Stefano : Kto dal tejto odpovedi minus nech napise aj svoj nazor preco. Ja s odpovedou suhlasim. 19.11.2013
  • Taco : Pomiňme settery, které použijeme pro nastavení volitelných parametrů. Můžeš prosím uvést nějaký příklad objektu, u kterého by bylo užitečné, aby měl výce jak jednu, nebo dejme tomu dvě "výkonné" metody? (Pod pojmem výkonné si představuji metody často nazívané jako fetch*()) A samozřejmě se bavíme o objektu, který architektonicky "netrpí". Také prosím pomiňme gettery u přepravek. 23.11.2013
  • Kit : U přepravek se gettery stejně nedělají. Běžně dělám objekty, které nemají gettery ani settery, ale mají víc metod v rozhraní s okolím. Například servisní vrstva k databázi víc metod potřebuje. 23.11.2013
  • Taco : @Kit: Asi si to nedokážu představit. O přepravkách se nebavím, tam je to jinej případ. Jaké množství metod potřebuje servisní třída do databáze? Co tím vlastně myslíš? Vrstva není objekt, ale spíš soustava objektů. 23.11.2013
  • Kit : Mám na mysli rozhraní mezi modelem a databází. Většinou si vystačím s jednou třídou, která má kolem 60 řádek a je v ní 4-6 metod pro čtení a modifikaci dat v DB. Metody se liší počtem parametrů a typem návratových hodnot. Je snad jasné, že pro insert použiji jinou metodu než pro select. Insert mi vrací pouze stavový kód, select volitelně seznam nebo iterátor. V určitých případech mohu třeba chtít jen skalár. 23.11.2013
  • Taco : @Kit: Ano, chápu. A akademicky vzato, co mají ty metody společného, že jsou v jednom objektu? Jak spolu souvisejí? 23.11.2013
  • Kit : Mají společnou v podstatě jen tu databázi (je to jediná instanční proměnná) a ano, je možné je umístit do samostatných tříd. U složitějších projektů to tak dělám, ale když dělám nějakou prkotinu, tak to nacpu do jedné třídy. 23.11.2013
  • Taco : @Kit: V tom případě bych tento příklad zařadil do skupiny "architektonicky trpí". Takže zpět k otázce: nějaký příklad, kde by to bylo užitečné? (A ne "jen" praktické.) 23.11.2013
  • Murděj Ukrutný : Třeba já mám svou DB třídu udělanou takto: Database má metody který "vyrobí" objekty pro select, insert, ... takže nějakých 5 výkonných metod Select má metody pro skladbu dotazu a tyto pro provedení SQL: ExecuteNonQuery, FetchRow, FetchObject, FetchValue, FetchObjects, FetchRows. I kdybych si pro výsledek sql selectu udělal další třídu tak pořád tam mám těch 5 Fetch*. Dělal něco takto: ent = new Entity(); result = SelectExecutor.Exec(database, select); ObjectFetcher.Fetch(result, ent); místo ent = select.FetchObject(new Entity); To už je jednodušší to psát procedurálně. 25.11.2013
  • Taco : @Murděj Ukrutný: Objekt, který ti vyrobí jiné objekty jsme tu už měli. Ty metody imho nemají nic společného. Takže jediný benefit, který v tom vidím, je, že se na to dá udělat rozhraní, a pak měnit implementaci. Jenže ta třída mi nepřijde ani tak jako objekt, jako spíše modul. Ale to už slovíčkařím. Mě by prostě zajímal nějaký příklad opravdového objektového objektu s více výkonnýma metodama. A zatím jsem narazil jen na rozhraní Iterator v php, což je ale hnus. Ten tvůj příklad bych napsal jinak, a s jednou výkonnou metodou. 28.11.2013
  • Murděj Ukrutný : @Taco: Tak jo, hodím příklad už z aplikační logiky, je to aplikace pro výběrová řízení db tabulky mají své třídy v aplikaci. Všechny mají základní CRUD metody (3. R může mít víc variant ale je statická takže se nepočítá) A teď třeba trída Tender (třída vlastního VŘ) Má metody determineScope - nalezení financí kategorie podle částky, getUsableMethods - zjištení postupů řízení podle finanční kategorie a typu řízení, allDataCollected - zjištení jestli jsou zadána všechna potřebná data pro vybraný postup a caa desítka dalších metod. Všechny pracují s daty konkrétního VŘ takže je blbost je mít jinde. 6.12.2013
  • Taco : @Murděj Ukrutný: Schází ti tam argument, proč to je blbost. Neboli: Ty metody nemají nic společnýho, takže je blbost je mět pohromadě. 6.12.2013
  • rmaslo : @Taco: Ať si vynyslím jakýkoliv objekt s jakýmikoliv metodami tak vždy jde argumentovat tím, že mají společného málo a nemají být v jednom objektu a nebo že mají společného moc a má to být jedna metoda. Vezmu třeba obyčejný objekt obdélník a netody Plocha() a Obvod(). Lze argumentovat: Výpočet plochy a výpočet obvodu spolu nemaji nic společnýho a mohou být v různých objektech. A nebo lze naopak argumentovat: Na to stačí jedna metoda Spocti(parametr) kde parametr je buď 'plocha' nebo 'obvod'. Pokud se Ti realita modeluje snadněji stylem "více objektů" nebo stylem "parametr metody" já proti tomu nic nemám ... ale stejně dobře je možný si zavést více metod - což bych udělal i já a to se zrovna za nějakýho velkýho nadšence do OOP nepovažuji. 7.12.2013
  • Taco : @rmaslo: Co z toho vyplývá? 7.12.2013
  • Martin Mystik Jonáš : Objekty jsou nástroj pro seskupování souvisejícího chování a dat. Jde v zásadě organizační jednotku, která nám umožňuje se v kódu vyznat tím, že budu pracovat s menším počtem pojmů. Pokud seskupím všechno do jednoho objektu neplní svoji funkci - vše je na jedné kupě v tom objektu. Pokud ale neseskupím nic taky neplní svoji funkci - mám jen kupu objektů pro každý kousek dat a metodu. Jde o to najít tu správnou míru seskupení. Na to, jaká ta správná míra a být není jasná odpověď. Jen principy, kterýma by se to mělo řídit. Psal sem o tom na zdrojáku http://www.zdrojak.cz/clanky/grasp-2-high-cohesion/ http://www.zdrojak.cz/clanky/grasp-3-low-coupling/ 7.12.2013
  • rmaslo : @Taco: No z toho vyplývá, že Tvoůj požadavek "Najděte mi objekt který má víc než dvě výkoné metody" je značně subjektivní a vždy můžeš daný objekt vyloučit! 7.12.2013
  • Taco : @rmaslo: Jenže na rozdíl od kolegy, jsem alespoň uvedl nějaké argumenty. A všichni ví, co mi na tom vadí. Z mé strany je to zajímavost, zda existuje, při splnění určitých podmínek, takový objekt. Protože mám podezření, že objekt, který má více jak dvě výkonné metody je blbě napsanej. Ale je to jen mé podezření, netvrdím nic. A protože já sám jsem si to mé podezření nebyl schopen vyvrátit, tak zkouším, zda se to nepovede zkušenějším. Rozumíme si? 7.12.2013
  • Taco : @Martin: Znám, rozumím, četl jsem, je to moc dobré. Podsouvám tu kritice už konkrétní pravidlo, které navíc patří právě do té správné míry. 7.12.2013
  • rmaslo : @Taco: ok - podle mě objekt "Okno na ploše". Metody: Minimalizovat do lišty, Maximalizovat na celou plochu, Dát na střední velikost. PS: Jako zkušenější než ty si teda rozhodně nepřipadám, a navíc radši argumentuju proti klasickému třídnímu OOP (ve prospěch trigerů, eventů, callbacků, prototypů, deklarativního programování atd...), ale jsou vyjímečné případy :-) kdy i mě přijde jako nejlepší programovací technika "klasické třídní OOP" a správa oken je jedním z těchto případů. 7.12.2013
  • Taco : @rmaslo: Argument je stejnej. Já mám třeba u oken nadefinované akce, Na půlku do prava, Na půlku doleva, Maximalizovat vertikálně, Maximalizovat horizontálně, a další. To znamená, že do té samé třídy okna budu muset vytvořit dalších šest metod. To je dohromady devět, a nemáme jistotu že jsme skončili. Myslíš, že je to správně? 7.12.2013
  • rmaslo : @Taco: To záleží na tom co to "Na půlku doleva" atd... znamená. Pokud to znamená "na střední stav" a pak "nastav rozměry na x=100% a y=50%" tak bych to asi jako zvláštní metody nedělal, ale použil bych parametry metody NaStredniStav(). Pokud, ale okno na "Na půlku doleva" má jiné vlastnosti než okno "ve středním stavu" (třeba "je roztahovatelné" jen doprava) tak bych se nebál udělat další metodu. Prostě podle toho jestli stav "na půlku doleva" je plnohodnotný stav nebo jen podstav stavu "střední velist". Samozřejmě, že kdybych těch plnohodnotných stavů měl třeba 50 tak bych asi nedělal 50 metod, ale udělal bych jednu - NastavTvarOkna(parametr) kde ten parametr by byl "Maximalizované", "Minimalizované" a dalších 48. Když se vyjádřim trochu obecně - je to design pattern stav. V tomto DP si samozřejmě musím dát pozor a pořádně analyticky rozlišit stavy a podstavy (A konkrétně u "oken na ploše" mě 9 plnohodntých stavů přijde jako fakt hóóóódně přehnaný - to budou spíš podstavy). Pokud je stavů relativně málo a předpokládám, že nebudou přibývat tak si myslím, že realizovat přepnutí do stavu pomocí metody je naprosto ok. Pokud jsem původně čekal, že stavy budou tři a pak se zjistilo, že jich je 9 tak se prostě změnilo zadání (chyba v analýze) a reagovat na změnu zadání jiným návrhem třídy není nic špatného. A zpětnou kompatibilitu lze zachovat poměrně snadno - metoda Maximalizovat() nově bude volat metodu NastavTvarOkna('Maximalizovane') 8.12.2013
  • Murděj Ukrutný : @Taco: "Schází ti tam argument, proč to je blbost." argument tam mám ">>Všechny pracují s daty konkrétního VŘ<< takže je blbost je mít jinde". Zeptám se jinak jak teda metody nacpat do oodělených tříd tak aby to neporušovaly zásady dobrého programovní (přehlednost, zapouzdřenost, dry, ...) 8.12.2013
  • Taco : @Murděj Ukrutný: Mám objekt reprezentující okno. To okno má nějaké vlastnosti. 1/ Můžu mět logiku na úpravu těchto vlastností objektu okna vně okna. Třeba nějakou funkci maximize(), minimize(), ... apodobně. Nebo 2/ můžu mět logiku úpravy těchto vlastností uvnitř objektu, takže vytvořím rozhraní s funkcí resize(width, height), a budu ho předávat instanci okna w.resize(IResize cmd). Obávám se, že nejsem tak zkušený, abych hned dal dobrý návrh. To první by mi asi vyhovovalo víc. To druhé zase do určité míry zachovává zapouzdření. Každopádně mi to furt přijde lepší, než vytvářet modul a říkat tomu objekt. 27.12.2013

Pro zobrazení všech 14 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.