JS: composition over inheritance

Deny

JS: composition over inheritance
« kdy: 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 ?


none_

Re:JS: composition over inheritance
« Odpověď #1 kdy: 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.

Deny

Re:JS: composition over inheritance
« Odpověď #2 kdy: 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.

abc

Re:JS: composition over inheritance
« Odpověď #3 kdy: 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.

Deny

Re:JS: composition over inheritance
« Odpověď #4 kdy: 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.


abc

Re:JS: composition over inheritance
« Odpověď #5 kdy: 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é.

Rapyd

Re:JS: composition over inheritance
« Odpověď #6 kdy: 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.

BoneFlute

  • *****
  • 1 600
    • Zobrazit profil
Re:JS: composition over inheritance
« Odpověď #7 kdy: 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.

balki

Re:JS: composition over inheritance
« Odpověď #8 kdy: 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.

BoneFlute

  • *****
  • 1 600
    • Zobrazit profil
Re:JS: composition over inheritance
« Odpověď #9 kdy: 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.

Rapyd

Re:JS: composition over inheritance
« Odpověď #10 kdy: 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

balki

Re:JS: composition over inheritance
« Odpověď #11 kdy: 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.

Immutable

Re:JS: composition over inheritance
« Odpověď #12 kdy: 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.

xxx

Re:JS: composition over inheritance
« Odpověď #13 kdy: 08. 03. 2017, 17:15:40 »
Jak se tomuhle matlání funkcionálního přístupu a OOP dohromady říká? Návrhový vzor Frankenstein?

oldschool

Re:JS: composition over inheritance
« Odpověď #14 kdy: 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/