Doplňující informace k objektu rubrika: Programování: Jiné

9 Taco
položil/-a 27.9.2017

Mějme objekt Item a skupinu těchto objektů: ItemGroup. Případně můžeme mět ještě třetí úroveň ať je to pěkný strom. Objekt ItemGroup obsahuje nějaké atributy, plus teda pole těch Item. A Item obsahuje taky nějaké atributy.

Dále mějme šablonu/renderer který ten kořenový ItemGroup předám a ona ho nějakým způsobem vykreslí.

Teď ale nastává situace, kdy z nějakého jiného zdroje získám ke každému tomu itemu nějakou doplňující informaci. Třeba že je ten který Item enabled. A on ten typ Item tuto vlastnost nemá. Jak tyto dvě informace skloubit?

  • Tak samozřejmě bych mohl do té šablony předat dvě hodnoty. ItemGroup, a potom pole těch dodatečných vlastností klíčovaných pomocí nějakého id toho Item. Ale to se mi moc nelíbí.

  • Nebo bych mohl udělat Proxy of Item, a celej ten ItemGroup přemapovat. Což je teda jako krapet dost pracný.

  • Případně ten ItemGroup včetně Item rozpustit na obyčejné beztypové struktury. Což zase, tak k čemu ty typy používám, že?

Jak byste to řešili vy? Díky za odpovědi.

Komentáře

  • arron : Je nějaký fundamentální rozdíl mezi Item, ItemGroup a nějakým ItemTree? Tedy je ItemGroup taky Item (může s ním být tak zacházeno) a pozná to program? 28.9.2017
  • Taco : Mno, to nemůžu říct, může i nemusí. Pokud by to něco znamenalo, tak ItemGroup může být typu Item, tudíž, jako položka ItemGroup může být jak Item tak ItemGroup. Program to pozná (pokud myslíš typové omezení). Takže buď použiju proxy, nebo se vzdám typů. 28.9.2017
  • Jakub Macek : No a jak by vypadala ta šablona pro Item? Pokud tam má být taky explicitní typování, tak se musí někde vyskytnout nějaké if item.enabled then ... end. Jenomže pokud Item žádné enabled nezná, tak mi to nepasuje k sobě. Tedy první otázku bych viděl v tom, jak vypadá šablona, která renderuje Item bez ohledu na to, zda zná či nezná enabled. 29.9.2017
  • Taco : @Jakub Macek: Sorry, konkrétní šablonu neukážu, asi by to nemělo moc velkej smysl. --- Ta šablona ví, že tam to item.enabled je, nebo minimálně, že tam může být. Ta část modelu, která připravuje data pro view, tak ví, že tam někde musí přidt k item enabled. Ta část modelu, která poskytuje originální Item a ItemGroup o enabled nic neví. Součástí Item na této úrovni enabled není. A moc se mi nezdá mu tuto vlastnost přidávat. 29.9.2017
  • rmaslo : Věta: "Ta část modelu, která připravuje data pro view, tak ví, že tam někde musí přidt k item enabled." se mi vůbec nelíbí. A trochu by mě zajímalo co je vlastně zdrojem toho jestli je item enabled nebo ne. Protože pokud je zdrojem nějaký "stav stránky" (ve smyslu uživatel si naklikal co zobrazit/rozbalit/skrýt) tak by o tom Model vůbec neměl vědět. Pokud je naopak zdrojem "enabled" jen jiné datové úložiště modelu (třeba ve smyslu, v interní db mám seznam firem a ARESu se ptám jestli jsou plátci DPH) tak samozřejmě tuto informaci model poskytuje, ale rozhodně ne jako "enabled", ale jako nějakou standardní vlastnost item. Prostě model vůbec nemá co rozkazovat View jak zobrazovat, to není v jeho pravomoci, to jen a pouze v pravomoci View. Pokud to tak máš tak je to podle mě špatně. A pak je možnost, že to máš dobře a jenom jsi to chybně napsal - měl jsi na mysli: "Ta část View, která připravuje data pro Renderer, tak ví, že tam někde musí přidat ..." 29.9.2017
  • Taco : @rmaslo: "Protože pokud je zdrojem nějaký "stav stránky" (ve smyslu uživatel si naklikal co zobrazit/rozbalit/skrýt) tak by o tom Model vůbec neměl vědět." - s tímto tvrzením nesouhlasím. Možná, když by to naklikání byl stav requestu... A i v takovém případě bych měl tendenci z toho udělat jeden model. Tak aby model (nebo něco jako model, pravděpodobně uvažuju o ModelView vzoru) opravdu rozkazoval View jak má co zobrazovat. --- Každopádně v rámci tohoto dotazu je zdrojem "enabled" jiné "datové úložiště". Takže tuto ideologickou bitku můžeme nechat na jindy :-) 29.9.2017
  • rmaslo : Aha to trochu mění situaci. Pokud je zdrojem "enabled" jen jiné datové úložiště, tak by podle mě už model měl sjednotit data ze všech úložišť do jednoho objektu a ten předat. View by o tom co je z kterého úložiště nemělo vůbec vědět. Ono se to totiž může i někdy změnit (třeba se rozhodneš jedno úložiště cachovat v jiném). 1.10.2017
  • Taco : @rmaslo: :D a o co myslíš, že mi celou dobu jde? (Zdůrazňuji, že nemám v plánu Item obohatit o vlastnost enabled.) 2.10.2017
  • rmaslo : No myslel jsem, že jiným zdrojem myslíš URL (SESSION, COOKIES či jinak uložený stav). Pokud jde o "skutečná" data (z datového úložiště), tak se už jen nabízí otázka: Proč Model nemá obohatit item o vlastnost enabled? 2.10.2017
  • Kit : @Taco: K čemu je vlastnost "enabled"? Takový predikát bych jen stěží upotřebil. 2.10.2017
  • Taco : @rmaslo: Proč nechci enabled dát do Item není podstatné. Když bych toto chtěl udělat, tak nějak už nemám problém, že jo :-) 2.10.2017
  • rmaslo : @Taco: jj pak by žádný problém nebyl, protože tam to patří. Ale ono se trochu blbě radí, když neprozradíš, proč to nechceš dát tam kam to patří. 2.10.2017
  • Taco : @rmaslo: Protože to tam nepatří. Neřešíme, proč jsem blbej. Řešíme, co kdybych měl pravdu. 2.10.2017
  • Kit : @Taco: Item přece nemusí mít vlastnost "enabled", ale Model ji mít může. 2.10.2017
odkaz
6 arron
odpověděl/-a 29.9.2017

Já bych asi udělal dva základní kroky.

Jednak bych sjednotil Item a ItemGroup, alespoň přes nějakého předka nebo interface (a možná přes oboje), protože ItemGroup je IMHO proste taky obyčejný Item (bude mít metodu render či něco podobného) a prostě jenom vykreslí skupinu itemů. Programu by to pak mohlo být tak trochu jedno s čím pracuje, prostě zavolá render, ostatní operace mohou být zapouzdřené (proto ta dědičnost).

A druhá věc jsou ty atributy. Implementoval bych tam (asi nejprve do předka) nějaké "skladiště atributů" tedy nějaké pole, kam se budou ukládat atributy. Na to nějaký getter (s trochou snahy do toho dostaneš i typovou kontrolu, byť to asi nebude úplně přímočaré) a setter (buď se to bude předávat přímo přes konstruktor, pokud ty atributy máš už při vzniku objektu nebo klasický setter, pokud je máš až později). Co získáš? Ke každému objektu si budeš moc dát kolik chceš atributů, budeš k nim přistupovat poměrně hezky objektově, budeš k nim přistupovat úplně stejně bez ohledu na přesný typ objektu (čili klidně přes rozhraní) a můžeš si k tomu přídělat jakoukoliv logiku, kterou chceš.

A dál? Dál si s tím můžeš hrát jak budeš chtít. Když zjistíš (a to dost možná zjistíš), že něco takového potřebuješ i někde jinde, tak si to vyrefaktoruješ do nějaké samostatné třídy a pak to budeš předávat jako závislost (nějaký AttributeStorage), nebo zjistíš, že by to bylo lepší udělat fakt přes nějakou proxy, tak si to vyrefaktoruješ do proxy atd. atp. to už pak záleží na konkrétní potřebě :-)

No snad jsem správně zachytil podstatu problému :-)

Komentáře

  • harrison314 : Neporusuje to SRP, respektyve nie je to miesanie vrstiev? (aj ked to zalezi od konkretheho kotextu) 29.9.2017
  • Kit : @harrison314: SRP to neporušuje. Kolekce atributů je do Item jen zakomponována. Renderování můžeš injektovat, pokud by se ti to zdálo málo SRP. 29.9.2017
  • Taco : @arron: Moc pěkný přístup, díky! Zatím to vypadá jako favorit. Měl bych ještě dotaz k té proxy: Proxy v typových jazycích má ten význam, že má stejný typ, jako proxovaný objekt. Tudíž bych nemohl vytvořit obecnou proxy pro cokoliv (alespoň v jazycích jako Java, PHP,...). Leda tak nějaký trait. Měl jsi nějakou konkrétní představu? 29.9.2017
  • arron : @Taco: No ono hodně záleží, co tou proxy budeš chtít přesně řešit. Ideálně se Ti ta proxy bude dělat na nějakým interface a pak, pokud budeš mít jednotný interface, tak jí budeš mít stejnou pro Item i pro ItemGroup i pro nějaké třeba ItemTree (což je stejně spíš jenom další ItemGroup, že jo). Případně použít dekorátor. A nebo mít nějakou továrnu, která ty objekty vytvoří i s těmi atributy a pak nic takového možná nebudeš potřebovat :-) Ale to už záleží fakt na tom konkrétním použití, do kterého nevidím ;-) 1.10.2017
  • Anonym : Tady bych nesouhlasil, že "ItemGroup je IMHO proste taky obyčejný Item" a že by měli mít společného předka. To, že někde potřebuju stejné metody, není vůbec důvod, abych používal dědění. Tady v tom případě by se hodily interface (např. Renderable, ad.). Dědění je dobré např. ve smyslu Animal -> Dog, Cat ..., ale ne Animal -> AnimalGroup. 2.10.2017
  • arron : @Honza B.: jasně, záleží na konkrétní situaci, někdy se to hodit může, někdy ne :-) Interface je jasný, dědičnost jak kdy, s tím musím souhlasit :-) Neznám konkrétní problém, takže spíš spekuluju. 2.10.2017
  • Taco : @Honza B: Né, že by na tom záleželo, ale zrovna v tomto případě ItemGroup je prostě taky obyčejný Item, protože se s ním jako s obyčejným Itemem narába. Strká se do ItemGroup například. Je to speciální verze Itemu. Takže zrovna toto by mohl být krásný příklad dědění. Korektního. 2.10.2017
  • Anonym : @Taco: Ok, už jsem to pochopil :-) On totiž ItemGroup není skupina Itemů, ale je to Item, který *navíc* obsahuje ještě skupinu Itemů. 2.10.2017
  • Kit : @Honza B: Tuto vlastnost může mít každý Item, jen některé budou mít tu skupinu prázdnou. Tím lze docílit polymorfismu a jednotného ovládání. 2.10.2017
  • Taco : @Honza B.: Tak. Sorry, pokud jsem se nevyjádřil úplně výstižně. 2.10.2017

Pro zobrazení všech 6 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.