Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Deny 08. 03. 2017, 12:02:01

Název: JS: composition over inheritance
Přispěvatel: Deny 08. 03. 2017, 12:02:01
Zdravim mam jednu otazku v JavaScripte ohladom best practice ako riesit "povod" objektu.
Chcem sa vyhnut OOP strukture a objekt vznika funkcionalne kompoziciou funkcionalit, ktore ma vediet.
Priklad: Chcem spravit Hikera a ten ma vediet sa predstavit a cestovat, pridelia sa mu teda metody introduce a travel s prislusnymi properties.
Kód: [Vybrat]
const introducer = (state) => ({
    name: state.name,
    introduce: () => console.log(`I am ${state.name}`)
})

const traveler = (state) => ({
    place: state.place,
    travel: (destination) => {
        state.place = destination
        console.log(`I have arrived at ${state.place}`)
    }
})

function hikerFactory(name, place) {
    let state = {name, place}
    return Object.assign(
        state,
        introducer(state),
        traveler(state)
    )
}

var johny = hikerFactory('Johny', 'Paris')

Vsetko funguje ale v chrome devtools nezistim co je zac, lebo je anonymny:
Kód: [Vybrat]
johny.introduce()
// I am Johny
johny.travel('Berlin')
// I have arrived at Berlin
johny
// Object {name: "Johny", place: "Berlin"}
// vidim len ze je Object

V podstate mam dve moznosti ako ho odanonymnit.
Prva je pridat property co nieco o nom prezradi:
Kód: [Vybrat]
function hikerFactory(name, place) {
    let state = {name, place, type:'Hiker'}
    ...

johny
// Object {name: "Johny", place: "Berlin", type: "Hiker"}
// vidim ze je typu Hiker a teda ho zrejme vytvoril hikerFactory

Druha elegantnejsia je pomoct si triedou
Kód: [Vybrat]
class Hiker {
    constructor(name, place) {
        Object.assign(this, {name, place})
    }
}

function hikerFactory(name, place) {
    let state = new Hiker(name, place)
    ...

johny
// Hiker {name: "Johny", place: "Berlin"}
// vidim ze je z triedy Hiker a teda ho zrejme vytvoril hikerFactory

Otazka teda je: Co je zdravsie? Pridat si property na jeho identifikaciu alebo vytvorit jeho state z triedy ?
Název: Re:JS: composition over inheritance
Přispěvatel: none_ 08. 03. 2017, 12:50:44
Nechapu, jakou vyhodu by melo prinest pouziti pouheho Object bez tridy. Tohle neni inheritance. Teda samozrejme, ze dedi ten vas objekt z Object, ale to i v prvnim pripade.
Název: Re:JS: composition over inheritance
Přispěvatel: Deny 08. 03. 2017, 13:17:56
Tohle neni inheritance.

O tu sa nesnazim, moj objekt vyrvara factory co je obycajna funkcia. Nie nejaky new z 10x extendnutej triedy, ktore mi prihodi stado metod a properties, ktore nepotrebujem. Tu class som len "zneuzil" aby objekt nebol anonymny, to je vsetko.
Název: Re:JS: composition over inheritance
Přispěvatel: abc 08. 03. 2017, 13:33:26
Ano, dá se to samozřejmě i lepením objektů dohromady, ale musím ti říct, že je to neohrabané, nešikovné a přiděláš si tím hromadu práce. Je to ale asi dost subjektivní záležitost, takže to ber čistě jako osobní zkušenost.
Název: Re:JS: composition over inheritance
Přispěvatel: Deny 08. 03. 2017, 14:01:00
Ideme trochu offtopic. Kazdy z nas zazil par OOP projektov a aka je to pakaren refaktorovat objektovy model a polku apky, ked zakaznik vymysli dalsiu uzasnu feature, ked uz je vsetko hotove a feature nezapada do existujuceho modelu. Kompozicia tento problem nema, proste do objektu prihodim funkcie "novej uzasnej feature" a to je vsetko.
Název: Re:JS: composition over inheritance
Přispěvatel: abc 08. 03. 2017, 14:15:35
Tak proč ne, já s tím kódem pak pracovat nebudu. Ale podle mě si tam stejně časem různýma obezličkama budeš implementovat to, co bys měl v klasickém OOP zadarmo(což je vidět hned v prvním příspěvku) a nakonec z toho vznikne akorát takový škaredý prasopes. Ale dělej, jak uznáš za vhodné.
Název: Re:JS: composition over inheritance
Přispěvatel: Rapyd 08. 03. 2017, 14:17:39
aka je to pakaren refaktorovat objektovy model a polku apky
Presne tak

Mejme takovou dedicnost
Kód: [Vybrat]
clovek
  +- muz
     +- otec
A pak si zakaznik vymysli, ze otec muze byt i "kun". V inheritancnim svete OOP pak budete muset pridat neco jako "kun -> samec -> otec" a mate zdvojeni "otce" protoze z cloveka jej pro nejaky duvod nelze pouzit (napr. by podedil jen 2 nohy).
Ve funkcionalnim pristupu je to hubicka:
Kód: [Vybrat]
Franta <= clovek, muz, otec
Hatatitla <= otec
Pouzijete tou samou funkci otce jak pro Frantu tak pro Hatatitlu, a to ani nemusite uvest, ze je kun :-)

Nerikam, ze to v OOP nejde, ale musite tak nejak vice "predvidat" jak stavet model aby vyhovel i budoucim zmenam. Ve FP budoucnost moc neresite.
Název: Re:JS: composition over inheritance
Přispěvatel: BoneFlute 08. 03. 2017, 14:55:46
Tak proč ne, já s tím kódem pak pracovat nebudu. Ale podle mě si tam stejně časem různýma obezličkama budeš implementovat to, co bys měl v klasickém OOP zadarmo(což je vidět hned v prvním příspěvku) a nakonec z toho vznikne akorát takový škaredý prasopes. Ale dělej, jak uznáš za vhodné.
To nemusí být nutně pravda. Tazateli se možná jedná o práci s Typy. Zatímco ty hovoříš o OOP. Což nejsou synonyma přestože oboje umožňuje dědičnost.
Název: Re:JS: composition over inheritance
Přispěvatel: balki 08. 03. 2017, 14:57:41
Otazka teda je: Co je zdravsie? Pridat si property na jeho identifikaciu alebo vytvorit jeho state z triedy ?

Osobne by som sa vykaslal aj na classu aj na property a len by som zistoval, ci  ma objekt potrebne metody (funkcie). Tj, ci ma rozhranie s ktorym prave potrebujem pracovat.
Název: Re:JS: composition over inheritance
Přispěvatel: BoneFlute 08. 03. 2017, 15:03:00
Otazka teda je: Co je zdravsie? Pridat si property na jeho identifikaciu alebo vytvorit jeho state z triedy ?
Chceš jen, aby se ti v konzole zobrazoval co je zač? Nebo budeš ten typ nějak více řešit? Budeš řešit i složitější věci (typy, interface)?

Pokud budeš řešit složitější chování, třeba právě to interface, tak vzhledem k tomu, že to JS nepodporuje, tak se asi bez property neobejdeš.
Pokud ti jde hlavně o tu konzoli a budeš se u objektu zajímat jen o jeho typ, tak bych šáhl po vytváření z třídy.
Název: Re:JS: composition over inheritance
Přispěvatel: Rapyd 08. 03. 2017, 15:26:13
Klidne tou tridu. Poslouzi stejne jako property a navic je to jasnejsi v debuggeru.
Kód: [Vybrat]
johny.constructor.name
// ti da to same co by ti dal
johny.type
// nebo je mozny taky dostat bool pomoci
johny instanceof Hiker

V cistem FP ale sotva budes muset zjistovat co za objekt funkce prijala, nemelo by to byt nejak konditionalni. JS svet je ale plny knihoven tretich stran nebo mozna budes muset prepojit neco existujiciho co to bude potrebovat vedet.

A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D
Název: Re:JS: composition over inheritance
Přispěvatel: balki 08. 03. 2017, 15:47:42
A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D

Ding dong. Dobry den, tu svedkovia funkcionalni. Prisli sme vam porozpravat o funkcionalnom programovani.
Název: Re:JS: composition over inheritance
Přispěvatel: Immutable 08. 03. 2017, 16:27:41
Tak tenhle priklad neni moc FP. Objekt je mutabilni, funkce nejsou pure atd. Ale jako kompozice to by slo, porad lepsi nez inheritance hell.
(https://cdn-images-1.medium.com/max/800/1*AM83LP9sGGjIul3c5hIsWg.png)
Název: Re:JS: composition over inheritance
Přispěvatel: xxx 08. 03. 2017, 17:15:40
Jak se tomuhle matlání funkcionálního přístupu a OOP dohromady říká? Návrhový vzor Frankenstein?
Název: Re:JS: composition over inheritance
Přispěvatel: oldschool 08. 03. 2017, 18:40:43
Jak se tomuhle matlání funkcionálního přístupu a OOP dohromady říká?

Tomu se rika v JS svete normalka :-) Ale mne se to libi.

https://dayssincelastjavascriptframework.com/

(https://cdn.discourse.org/sitepoint/uploads/default/24163/5282c0e6babea783.png)
Název: Re:JS: composition over inheritance
Přispěvatel: čumil 08. 03. 2017, 19:06:53
Klidne tou tridu. Poslouzi stejne jako property a navic je to jasnejsi v debuggeru.
Kód: [Vybrat]
johny.constructor.name
// ti da to same co by ti dal
johny.type
// nebo je mozny taky dostat bool pomoci
johny instanceof Hiker

V cistem FP ale sotva budes muset zjistovat co za objekt funkce prijala, nemelo by to byt nejak konditionalni. JS svet je ale plny knihoven tretich stran nebo mozna budes muset prepojit neco existujiciho co to bude potrebovat vedet.

A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D
Třeba ja
Fp je zklamani
Je na něj moc brzo, respektive aktualni jazyky na jeho principi chčijou

Název: Re:JS: composition over inheritance
Přispěvatel: čumil 08. 03. 2017, 19:09:31
Zdravim mam jednu otazku v JavaScripte ohladom best practice ako riesit "povod" objektu.
Chcem sa vyhnut OOP strukture a objekt vznika funkcionalne kompoziciou funkcionalit, ktore ma vediet.
Priklad: Chcem spravit Hikera a ten ma vediet sa predstavit a cestovat, pridelia sa mu teda metody introduce a travel s prislusnymi properties.
Kód: [Vybrat]
const introducer = (state) => ({
    name: state.name,
    introduce: () => console.log(`I am ${state.name}`)
})

const traveler = (state) => ({
    place: state.place,
    travel: (destination) => {
        state.place = destination
        console.log(`I have arrived at ${state.place}`)
    }
})

function hikerFactory(name, place) {
    let state = {name, place}
    return Object.assign(
        state,
        introducer(state),
        traveler(state)
    )
}

var johny = hikerFactory('Johny', 'Paris')

Vsetko funguje ale v chrome devtools nezistim co je zac, lebo je anonymny:
Kód: [Vybrat]
johny.introduce()
// I am Johny
johny.travel('Berlin')
// I have arrived at Berlin
johny
// Object {name: "Johny", place: "Berlin"}
// vidim len ze je Object

V podstate mam dve moznosti ako ho odanonymnit.
Prva je pridat property co nieco o nom prezradi:
Kód: [Vybrat]
function hikerFactory(name, place) {
    let state = {name, place, type:'Hiker'}
    ...

johny
// Object {name: "Johny", place: "Berlin", type: "Hiker"}
// vidim ze je typu Hiker a teda ho zrejme vytvoril hikerFactory

Druha elegantnejsia je pomoct si triedou
Kód: [Vybrat]
class Hiker {
    constructor(name, place) {
        Object.assign(this, {name, place})
    }
}

function hikerFactory(name, place) {
    let state = new Hiker(name, place)
    ...

johny
// Hiker {name: "Johny", place: "Berlin"}
// vidim ze je z triedy Hiker a teda ho zrejme vytvoril hikerFactory

Otazka teda je: Co je zdravsie? Pridat si property na jeho identifikaciu alebo vytvorit jeho state z triedy ?
Použij class

Pokud se ptaš timhle stylem, nepokoušej se o nic novyho, zkurvil bys to, použij prostě es6 classu

Ex nihilo či klonovani jsou metody ktere vyzaduji znalost prototype oop systemu, v opacnem případě tvuj kod vyvola satana
Název: Re:JS: composition over inheritance
Přispěvatel: Deny 08. 03. 2017, 20:01:42
No vidim, ze je tu okolo toho aj trochu humoru. Ano nazvem to FrankensteinJS :)

Zatial pokracujem tak ako to je, nepridaval som ani type property ani state z classy, v podstate mi to este nechybalo a mozno ani nakoniec nebude treba. V pripade, ze ano tak pojdem cestou state z classy.

No a este par odpovedi:

Objekt je mutabilni, funkce nejsou pure atd.
To ci potrebujem immutable objekt uvidim, az ho budem prehanat streamom udalosti. Ale tam by som sa asi spolahol na immutable.js (pripadne mozno bude stacit Object.freeze) naco objavovat ameriku. S tou function purification by sa dalo daco robit, to beriem.

Ex nihilo či klonovani jsou metody ktere vyzaduji znalost prototype oop systemu
Hmm a ty si sa JS "naucil" vcera ci predvcerom, ked sa ti tak krasne podarilo popliest jablka z hruskami v jednej vete?
Pouzitie obycajneho flatcopy Object.assign v mojom pripade je praveze bezpecne. Pridavam ci menim len primitiva a funkcie, ziadne objekty. Takze nehrozia divne memleaky a nema to nic spolocne s prototypmi (ktore v ES6+ su aj tak syntakticky "skryte").
Název: Re:JS: composition over inheritance
Přispěvatel: Kit 08. 03. 2017, 20:41:28
A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D

<rejp>Zřejmě to bude tím, že OOP nikdy neuměli.</rejp>
Název: Re:JS: composition over inheritance
Přispěvatel: Kit 08. 03. 2017, 21:03:03
Zdravim mam jednu otazku v JavaScripte ohladom best practice ako riesit "povod" objektu.
V podstate mam dve moznosti ako ho odanonymnit.
Otazka teda je: Co je zdravsie? Pridat si property na jeho identifikaciu alebo vytvorit jeho state z triedy ?

Proč ten objekt potřebuješ "odanonymnit"? V Javascriptu se běžně používá Duck Typing, tak ho používej také a nějakou anonymitu neřeš.
Název: Re:JS: composition over inheritance
Přispěvatel: Polymath 09. 03. 2017, 10:58:20
A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D

Ding dong. Dobry den, tu svedkovia funkcionalni. Prisli sme vam porozpravat o funkcionalnom programovani.
Další jednodušší OOP fanatik?
Název: Re:JS: composition over inheritance
Přispěvatel: SB 09. 03. 2017, 14:11:55
K původní otázce:

1. Není zřejmé, proč modelujete objekt tak, jak to děláte, co s ním dělat budete, účel.
2. V objektu se mísí 2 entity - role stopaře (cestování + místo) a entita osoby (představování + jméno).
3. Pojmenování vstupu "state" nedává smysl, protože (stejně jako objekt) míchá "stav" stopaře a jeho jméno (což není stav), trvalo mi dlouho, než jsem vůbec zjistil, k čemu to slouží.
4. Proč při odděleném vytvoření funkcionalit představovače a cestovatele je definujete jako pracující s bastlem state, který obsahuje i informaci, která s danou funkcionalitou nesouvisí? Tím oddělení funkcionalit ztrácí smysl.
5. V HikerFactory máte "let state = {name, place}", to vytvoří pole (když se to rovnou nevysere), ne objekt, takže assign asi nezafunguje.
6. Chcete-li zatřídit objekt jako stopaře, je to možno udělat několika způsoby (do tříd v JS nejdu) - buďto oným prototypem reprezentujícím obecného stopaře (obdoba funkcionality a zařazení sdíleného třídou), nebo příznakem, ale pokud možno unikátním, třeba objektem nebo symbolem (jestli to JS má), ne nějakým řetězcem, ale nejčistší je (jak píše Kit) využít rovnou polymorfismu užitím správně pojmenované metody, která něco dělá, ne se nejdříve optat, zda je to Stopař a pak na něm podle toho spustit metodu.
Název: Re:JS: composition over inheritance
Přispěvatel: SB 09. 03. 2017, 14:13:43
Nechapu, jakou vyhodu by melo prinest pouziti pouheho Object bez tridy...

Realizace entity s jejími stavy a chováním. Na to zatřízení není třeba.
Název: Re:JS: composition over inheritance
Přispěvatel: SB 09. 03. 2017, 14:25:32
Mejme takovou dedicnost
Kód: [Vybrat]
clovek
  +- muz
     +- otec
...

Hned 2 chyby v hierarchii 3 tříd - smíchání kategorií druhu, pohlaví a role? To se hned tak nevidí. Pak je jasné, odkud se na Rootu berou ty příspěvky, že dědičnost je na hovno, když někdo zkouší dědit neděditelné.
Název: Re:JS: composition over inheritance
Přispěvatel: SB 09. 03. 2017, 14:27:35
A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D
<rejp>Zřejmě to bude tím, že OOP nikdy neuměli.</rejp>

...a za chvíli přejdou zase jinam.
Název: Re:JS: composition over inheritance
Přispěvatel: Deny 09. 03. 2017, 16:52:24
2. V objektu se mísí 2 entity - role stopaře (cestování + místo) a entita osoby (představování + jméno).
To je uplne v poriadku, vy myslite prilis objektovo a nie ucelovo. Vytvaram jediny objekt s jedinou rolou (ci entitou ked chcete). Vola sa introducer-traveler alebo kratsi alias hiker. Neexistuje entita osoby ani entita stopara. To su funkcionality. Kym si toto neuvedomite tak nepochopite zakladny rozdiel medzi composition a inheritance.

Citace
3. Pojmenování vstupu "state" nedává smysl, protože (stejně jako objekt) míchá "stav" stopaře a jeho jméno (což není stav), trvalo mi dlouho, než jsem vůbec zjistil, k čemu to slouží.
Opat ste zatazeny svojimi jednostrannymi navykmi. Naco by mi bol objekt bez stavu :) V podsate by som ho mohol aj schovat
Kód: [Vybrat]
Object.assign(
    {}, // state,
    introducer(state),
    traveler(state)
)
ale pocas vyvoja je dobre vidiet co drzi. State je proste mnozina properties, ktore mu tam prihodili jednotlive  funkcionality, ktore obsahuje. To, ze ich ma dobredu vymenovane je len pre pripadne default hodnoty, moze byt aj prazdny.

Kód: [Vybrat]
4. Proč při odděleném vytvoření funkcionalit představovače a cestovatele je definujete jako pracující s bastlem state, který obsahuje i informaci, která s danou funkcionalitou nesouvisí? Tím oddělení funkcionalit ztrácí smysl.
Presne nechapem ako to myslite. Ved to su obycajne funkcie a tie same o sebe ziadne "ulozisko" nemaju. Preto dostavaju argument s referenciou na state s ktorym mozu pracovat - resp. si v nom najdu properties s ktorymi vedia pracovat.
V realnom projekte samozrejme mam nejaku stabnu kulturu a pouziva sa jasna konvencia namespace aby sa nahodou nebili.

Kód: [Vybrat]
5. V HikerFactory máte "let state = {name, place}", to vytvoří pole (když se to rovnou nevysere), ne objekt, takže assign asi nezafunguje.
WTF, takze ste nakoniec predsa len troll. Precitajte si nejaky "ES6 for dummies" a prestante rozpravat nezmysly. Vytvori sa objekt a priklad je plne funkcny.

Citace
6. Chcete-li zatřídit objekt jako stopaře, je to možno udělat několika způsoby
Ano spravil som to kompozitnym sposobom.

Citace
...využít rovnou polymorfismu užitím správně pojmenované metody
No go. OOP detected :) Ziadne metody nebudu, zabudnite. Asi som tam tu class vobec nemal davat, lebo to OOPistov uplne zmiatlo :) Este raz zopakujem, ze zatial som sa na to vykaslal a nechavam objekt anonymny bez akejkolvek identifikacie, ci cez type property alebo classy pre state. Proste mi to este netrebalo ho identifikovat, funguje to samo.
Název: Re:JS: composition over inheritance
Přispěvatel: SB 10. 03. 2017, 09:27:52
No nic, vidím, že všechno vlastně víte a žádné rady nepotřebujete.
Název: Re:JS: composition over inheritance
Přispěvatel: balki 10. 03. 2017, 15:12:47
A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D

Ding dong. Dobry den, tu svedkovia funkcionalni. Prisli sme vam porozpravat o funkcionalnom programovani.
Další jednodušší OOP fanatik?

Zrovna vedla. Som inteligentny privrzenec multiparadigmoveho pristupu.
Název: Re:JS: composition over inheritance
Přispěvatel: Polymath 10. 03. 2017, 16:39:53
A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D

Ding dong. Dobry den, tu svedkovia funkcionalni. Prisli sme vam porozpravat o funkcionalnom programovani.
Další jednodušší OOP fanatik?

Zrovna vedla. Som inteligentny privrzenec multiparadigmoveho pristupu.
Tak to jo. Ten primitivní útok na FP se mi asi jenom zdál...
Název: Re:JS: composition over inheritance
Přispěvatel: balki 11. 03. 2017, 09:13:09
A kousek off topic. Znam dost koderu co presli z OOP -> FP ale neumim si spomenout jestli znam nekoho co presel z FP zpet do OOP :-D

Ding dong. Dobry den, tu svedkovia funkcionalni. Prisli sme vam porozpravat o funkcionalnom programovani.
Další jednodušší OOP fanatik?

Zrovna vedla. Som inteligentny privrzenec multiparadigmoveho pristupu.
Tak to jo. Ten primitivní útok na FP se mi asi jenom zdál...

Presne tak, lebo nic take sa nestalo.