Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Martin 16. 07. 2016, 09:34:48

Název: Copy & Paste vs. Špagety
Přispěvatel: Martin 16. 07. 2016, 09:34:48
Ahoj,

Zajímalo by mě, jak řešíte společnou funkcionalitu, která se téměř opakuje, až na nějaký malý rozdíl. Může to být funkce, kde pro jiné využití potřebujete změnit pár řádků. Nebo formulář, který ja nachlup podobný jinému, jen jsou tam nějaké položky navíc, nějaké chybí nebo se jinak jmenují.

Mě se osvědčily dva přístupy:
1. Copy & Paste: Výhoda je, že budoucí změny mají lokální dopad. V některých případech to je zároveň nevýhoda, protože je občas potřeba něco opravit hromadně.
2. Přidám rozšiřující parametry do funkce nebo skriptu stránky a dovnitř dám podmíněný specializující kód
2a. Nové funkce volající jednu univerzální, případně nové skripty inkludující jeden univerzální nebo v používající funkce/objekty.

Vím, že ideální je navrhnout modulárnějí architekturu, ale pokud se dvou formulářích opakuje 19 z 20 položek, tak opravdu nevím, jak na to.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 09:52:35
Specializující kód injektuji do funkce či metody se společným kódem. Podmínky tím nejsou potřebné a špagety nevzniknou.

V šablonách nevhodnou část prostě překryji jinou částí prostřednictvím importu.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: nechápe 16. 07. 2016, 11:08:20
Specializující kód injektuji do funkce či metody se společným kódem. Podmínky tím nejsou potřebné a špagety nevzniknou.

V šablonách nevhodnou část prostě překryji jinou částí prostřednictvím importu.

To máš zase svoje termíny a nebo jen neumím nějaký skriptovací bazmek? Jak jsi teda vyřešil problém?
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Filip Jirsák 16. 07. 2016, 11:47:49
Specializující kód injektuji do funkce či metody se společným kódem. Podmínky tím nejsou potřebné a špagety nevzniknou.

V šablonách nevhodnou část prostě překryji jinou částí prostřednictvím importu.

To máš zase svoje termíny a nebo jen neumím nějaký skriptovací bazmek? Jak jsi teda vyřešil problém?
Společná část je v kódu jenom jednou. Odlišnost se vyřeší podle povahy věci - pokud je to třeba posloupnost dílčích kroků, kde se jeden krok liší, bude každý z kroků samostatná funkce. V jednom případě se pak zavolají kroky 1, 2 a 3a, v druhém případě 1, 2 a 3b. Pokud ta odlišnost je v tom, že ten hlavní kód potřebuje provést nějakou specializovanou operaci, vytkne se ta specializovaná operace do samostatné funkce. Ve funkcionálním přístupu se pak ta specializovaná funkce předá hlavnímu kódu jako parametr, v objektovém přístupu  bude ten hlavní kód v nějaké třídě a bude volat specializovanou metodu, která bude v potomcích přetížená.

Pokud ty formuláře jsou nějaké šablony, obvykle šablonovací systém umožňuje používat nějaké importy nebo includy, které umožní znovupoužití kódu.

Zkrátka oba přístupy, jak kopírování tak zavlékání implementačních detailů do nějaké obecné funkce (z čehož vzniká špagetový kód), jsou špatně. Každé programovací paradigma, každý jazyk i spousta frameworků poskytuje nějaké nástroje, jako řešit znovupoužitelnost kódu. Pokud se tedy tazatel ptal, zda vůbec psát znovu použitelný kód, pak rozhodně ano. Pokud se ptá na to, jak ho psát, pak je potřeba znát alespoň konkrétní paradigma a jazyk, protože pokaždé jsou k dispozici trochu jiné nástroje.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Martin 16. 07. 2016, 12:26:12
Jo, virtuální metody jsem mohl dát jako třetí možnost. Akorát je pak problém, když potřebuju různé kombinace ano/ne. To jde řešit třeba v C++ vícenásobnou inheritancí, ale obecněji spíše funkčním pointerem, lambda funkcí, delegátorem nebo celým objektem. Akorát je možná jednodušší všechno nacpat do jedné rozvětvené funkce.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: dustin 16. 07. 2016, 12:34:08
Akorát je možná jednodušší všechno nacpat do jedné rozvětvené funkce.

Jednodušší to možná je, teď pro tebe. Až přijde další požadavek na změny, budeš sám sebe nebo někdo jiný tebe proklínat. Mnohokrát ověřeno v praxi, bohužel...

Napiš to čistě přehledně hned od začátku, dobrý kód je takový, ze kterého máš radost a můžeš sám sebe pochválit.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 12:37:31
Ha! Konečně jsi prozradil, že se jedná o C++!

I booleovské vlastnosti se dají injektovat. Samozřejmě je nejlepší se psychické závislosti na typu boolean co nejdříve zbavit.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Filip Jirsák 16. 07. 2016, 12:58:33
Akorát je možná jednodušší všechno nacpat do jedné rozvětvené funkce.
Je to jednodušší to tak jednou napsat. Jenže pak pro ten kód budete psát test, budete jej mnohokrát číst a mnohokrát upravovat, a ve všech těch případech už je to komplikace.

Na to, že je špagetový kód zlo, nepřišel nějaký teoretik, který by nenapsal ani čárku. Na to přišli a přicházejí programátoři opakovaně v reálném kódu, se kterým musí pracovat.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 15:37:23
Je to jedno. Hlavně, že to bude fungovat.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Ondra Satai Nekola 16. 07. 2016, 15:43:26
Je to jedno. Hlavně, že to bude fungovat.

Jen si musis dat pozor, aby ti, kdo po tobe ten kod zdedi, nemeli sanci najit tvou adresu...
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 15:45:40
Souhlasím s Kitem. Není možné předat jako parametr funkci nebo blok kódu, který dělá tu specifickou část?
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 15:46:52
Je to jedno. Hlavně, že to bude fungovat.

Jen si musis dat pozor, aby ti, kdo po tobe ten kod zdedi, nemeli sanci najit tvou adresu...

Nejjednodušší možné řešení bývá nejčitelnější.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: hawran diskuse 16. 07. 2016, 15:55:04
Je to jedno. Hlavně, že to bude fungovat.

Jen si musis dat pozor, aby ti, kdo po tobe ten kod zdedi, nemeli sanci najit tvou adresu...
;D
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: hawran diskuse 16. 07. 2016, 15:55:29
Je to jedno. Hlavně, že to bude fungovat.

Jen si musis dat pozor, aby ti, kdo po tobe ten kod zdedi, nemeli sanci najit tvou adresu...

Nejjednodušší možné řešení bývá nejčitelnější.

OMG
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Ondra Satai Nekola 16. 07. 2016, 16:35:23
Je to jedno. Hlavně, že to bude fungovat.

Jen si musis dat pozor, aby ti, kdo po tobe ten kod zdedi, nemeli sanci najit tvou adresu...

Nejjednodušší možné řešení bývá nejčitelnější.

Jenomze to skutecne nejjednodussi reseni da obrovske mnozstvi prace...
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 16:44:18
Nejjednodušší možné řešení bývá nejčitelnější.

Jenomze to skutecne nejjednodussi reseni da obrovske mnozstvi prace...

Pokud beru v potaz standardní postup řešení
primitivní -> složité -> jednoduché
tak to nejjednodušší je skutečně nejpracnější.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Filip Jirsák 16. 07. 2016, 17:10:02
Je to jedno. Hlavně, že to bude fungovat.
Což se u kopírovaného nebo špagetového kódu těžko zajišťuje, protože se těžko testuje, těžko čte a těžko opravuje.

Nejjednodušší možné řešení bývá nejčitelnější.
Ano, ale bývá těžké ho vymyslet a naprogramovat.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 17:42:40
Ještě k formulářům. Záleží jak moc se liší a kolik jich je. Pokud jsou 2 nebo 3, klidně bych copy pastoval. Pokud se liší málo, dá se použít společná šablona s nějakou podmínkou. Pokud se liší hodně, asi bych je skládal z malých šablon pro jednotlivé položky. Na takové věci používám Jinja2 makra. Podobná funkcionalita existuje i jinde. Validaci bych se snažil řešit pomocí kódu navázaným na modely do kterých se ukládá, ale mělo by jít ověřit validitu bez uložení. Záleží na konkrétním formuláři, někdy je nutné validovat formulář jako celek. Tam bych se snažil oddělit kód společný pro všechny formuláře a kód specifický pro jednotlivé typy. Možná bych si někam do databáze ukládal raw post data z toho formuláře pro pozdější kontrolu. Při opravě chyby se použijí uložená post data v testech, aby se chyba neopakovala. Je dobré do jednotlivých formulářů přidat skryté pole s typem formuláře.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 17:58:30
Ty části šablony, které potřebuji jinak, jednoduše překryji specializovanou částí šablony, která importuje tu obecnou část šablony. Na to ty importy jsou.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 18:14:06
Ty části šablony, které potřebuji jinak, jednoduše překryji specializovanou částí šablony, která importuje tu obecnou část šablony. Na to ty importy jsou.

Souhlas. Pokud těch opakujících se částí není moc, je to asi lepší než makra. Některé šablonovací systémy ani makra nemají. V Djangu se dají používat widgety a jednotlivé formy z nich poskládat, ale to mi přijde zbytečně komplikované.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 18:38:28
Ty části šablony, které potřebuji jinak, jednoduše překryji specializovanou částí šablony, která importuje tu obecnou část šablony. Na to ty importy jsou.

Souhlas. Pokud těch opakujících se částí není moc, je to asi lepší než makra. Některé šablonovací systémy ani makra nemají. V Djangu se dají používat widgety a jednotlivé formy z nich poskládat, ale to mi přijde zbytečně komplikované.

Ty šablony se dají normálně vrstvit na sebe, podobně jako v OOP při použití dědičnosti. Přednost má vždy speciální komponenta šablony před obecnou. V podstatě není důvod, aby se něco opakovalo.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: jinjanoob 16. 07. 2016, 18:53:43
Jak se dělá import v Jinja?
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 19:02:51
Jak se dělá import v Jinja?

importem jsem myslel include.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 19:10:44
importem jsem myslel include.

Některé šablonovací systémy dělají rozdíl mezi import a include. Rozdíl je právě v tom, co je čím překryto.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 19:20:03
Ty části šablony, které potřebuji jinak, jednoduše překryji specializovanou částí šablony, která importuje tu obecnou část šablony. Na to ty importy jsou.

Souhlas. Pokud těch opakujících se částí není moc, je to asi lepší než makra. Některé šablonovací systémy ani makra nemají. V Djangu se dají používat widgety a jednotlivé formy z nich poskládat, ale to mi přijde zbytečně komplikované.

Ty šablony se dají normálně vrstvit na sebe, podobně jako v OOP při použití dědičnosti. Přednost má vždy speciální komponenta šablony před obecnou. V podstatě není důvod, aby se něco opakovalo.

mám 3 formuláře složené z částí:

část1
část2
část4
část5

část2
část3
část4
část6

část1
část3
část5
část6

Některé části mohou mít stejnou šablonu jen s jinými parametry. Jak se tohle řeší pomocí vrstvení?
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 19:38:51
mám 3 formuláře složené z částí:
...
Některé části mohou mít stejnou šablonu jen s jinými parametry. Jak se tohle řeší pomocí vrstvení?

Z příkladu není patrné, která část šablony je do které zanořena. Sekvenci různých šablon by mi to odmítlo, protože v každé komponentě podšablony musí být uzavřeny párové závorky - <div> musí být ve stejné komponentě jako příslušný </div> - parser to kontroluje a nepárové či překřížené tagy vyhodnotí jako fatální chybu.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 21:28:58
mám 3 formuláře složené z částí:
...
Některé části mohou mít stejnou šablonu jen s jinými parametry. Jak se tohle řeší pomocí vrstvení?

Z příkladu není patrné, která část šablony je do které zanořena. Sekvenci různých šablon by mi to odmítlo, protože v každé komponentě podšablony musí být uzavřeny párové závorky - <div> musí být ve stejné komponentě jako příslušný </div> - parser to kontroluje a nepárové či překřížené tagy vyhodnotí jako fatální chybu.

Jaký používáš šablonovací systém? Ty části mohou být jednotlivé položky formuláře. Třeba

Kód: [Vybrat]
<div class="form-group">
    <label for="{{id}}">{{label}}</label>
    <input type="{{type}}" class="form-control" id="{{id}}" name="{{name}}">
  </div>

Každopádně všechny divy jsou vždy otevřené a uzavřené ve stejné části.  Určitě je mnoho způsobů jak tohle řešit. Makra se mi osvědčila asi nejvíc. Jsem v téhle oblasti samouk, rád dovím jiná řešení.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: javaman 16. 07. 2016, 21:33:21

Jaký používáš šablonovací systém?

Že se vůbec ptáš :D
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 16. 07. 2016, 21:39:17

Jaký používáš šablonovací systém?

Že se vůbec ptáš :D

Tebe jsem se neptal, ale můžeš odpovědět za něj pokud to víš.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Ivan Nový 16. 07. 2016, 21:52:12
Na složité logické vazby se už před mnoha lety používaly rozhodovací tabulky. Viz zde http://www.ibm.com/support/knowledgecenter/cs/SSFTDH_8.0.0/com.ibm.wbpm.main.doc/topics/cbrm_dectbl.html
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 16. 07. 2016, 22:31:41
Jaký používáš šablonovací systém? Ty části mohou být jednotlivé položky formuláře. Třeba

Kód: [Vybrat]
<div class="form-group">
    <label for="{{id}}">{{label}}</label>
    <input type="{{type}}" class="form-control" id="{{id}}" name="{{name}}">
  </div>

Každopádně všechny divy jsou vždy otevřené a uzavřené ve stejné části.  Určitě je mnoho způsobů jak tohle řešit. Makra se mi osvědčila asi nejvíc. Jsem v téhle oblasti samouk, rád dovím jiná řešení.

Aha, tak na tohle bych měl jen jednu šablonu, kterou bych řídil tokem dat. Používám XSLT. V té šabloně by bylo 6 komponent část1..část6 a volaly by se podle pořadí vstupních dat, např.
Kód: [Vybrat]
<post>
<username id="username" label="část1" name="jmeno"/>
<password label="část2" name="heslo"/>
<password label="část4" name="heslo2"/>
<captcha label="část5"/>
</post>
Napsal jsem to pro přehlednost ve formátu XML. Ve skutečnosti té šabloně předávám datový strom.
Ve výstupu se pak vygeneruje i potřebná bižuterie pro výstupní HTML.

Těch 6 komponent šablony tady nebudu rozepisovat, ale je to v jednom souboru na cca 25 řádek. Při zpracování se vezme se první node, tedy <username> a na něj se použije komponenta s atributem select="username", která vygeneruje výstup viz výše. Jen místo {{id}} se napíše @id apod. Vezme se další node, a aplikuje se šablona select="password" a tak dále. To všechno však samostatně dělá datový procesor, který zvládá i rekurzi ve vstupních datech. To vše je zabaleno v elementu <form method="POST"> a pokud chceš, tak i v <div class="form-group">
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Petr M 18. 07. 2016, 21:37:09
Jenom dodám, že v klasickým kódu (C apod.) se to řeší pomocí dependency injection. Ta je základem efektivního řešení třeba pro takový věci, jako jednoduchý operační systém (předání vykonávané funkce do context switche), hierarchický stavový automat (řeší to dynamicky hierarchie), u univerzálníchtřídících algoritmů se tak dá měnit za běhu porovnávací funkce, v objektovce je na tom principu postavená VMT a dá se s tím užít ještě další obrovský kopec srandy. A pěkně učesat kód, samožřejmě.

Řekněme, že máme dvě čísla, který mají být ořezány na rozsah -9999 až +9999, má s nimi být udělána nějaká neznámá operace a výsledek ořezán na na stejný rozsah. Takže to ořezání si vytkneme do funkce
Kód: [Vybrat]
int orez(int a) {
if(a < -9999) return -9999;
if(a > 9999) return 9999
else return a
}
V příkladu je to jenom jako společná část kódu, která se nemění, s DI zatím nemá co do činění, ale opakující se část ve funkci by měla být samozřejmost.

Vlastní operace bude asi nejaká funkce, která si vezme dva inty a vrátí int. Takže ukazatel na ni bude jednoduše
Kód: [Vybrat]
int(*funkce)(int a, int b);

a vlastní implementace funkcí pro jednotlivý operace budou třeba
Kód: [Vybrat]
int soucet(int a, int b) {return a+b;}
int rozdil(int a, int b) {return a-b;}
Těch může být, kolik je potřeba. Rozhoduje jenom počet a typ parametrů a typ návratové hodnoty.

Pak se to všechno bude volat z programu nějak slepený a zapouzdřený, dáme to tedy do funkce. Ta si vezme tři parametry, operaci a dva operandy. Vrací zase int.
Kód: [Vybrat]
int mojeOperace(funkce typ, int a, int b) {
  int a1 = orez(a);
  int b1 = orez(b);
  int x = funkce(a1, b1);
  return orez(x);
}

No a nakonec jak to celý použít. Prostě, jako volání funkce.
Kód: [Vybrat]
int main() {
  int a = 100; int b = 200;
  printf("Soucet je %d", mojeOperace(&soucet, a, b);
  printf("Rozdil je %d", mojeOperace(&rozdil, a, b); 
  return 0;
}

Zkus vymyslet, jak s pomocí mojeOperace() uděláš x=a^2/b bez toho, že bys v ní samotné změnil jediný řádek kódu  ;)
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: gl 19. 07. 2016, 22:47:09
Jaký používáš šablonovací systém? Ty části mohou být jednotlivé položky formuláře. Třeba

Kód: [Vybrat]
<div class="form-group">
    <label for="{{id}}">{{label}}</label>
    <input type="{{type}}" class="form-control" id="{{id}}" name="{{name}}">
  </div>

Každopádně všechny divy jsou vždy otevřené a uzavřené ve stejné části.  Určitě je mnoho způsobů jak tohle řešit. Makra se mi osvědčila asi nejvíc. Jsem v téhle oblasti samouk, rád dovím jiná řešení.

Aha, tak na tohle bych měl jen jednu šablonu, kterou bych řídil tokem dat. Používám XSLT. V té šabloně by bylo 6 komponent část1..část6 a volaly by se podle pořadí vstupních dat, např.
Kód: [Vybrat]
<post>
<username id="username" label="část1" name="jmeno"/>
<password label="část2" name="heslo"/>
<password label="část4" name="heslo2"/>
<captcha label="část5"/>
</post>
Napsal jsem to pro přehlednost ve formátu XML. Ve skutečnosti té šabloně předávám datový strom.
Ve výstupu se pak vygeneruje i potřebná bižuterie pro výstupní HTML.

Těch 6 komponent šablony tady nebudu rozepisovat, ale je to v jednom souboru na cca 25 řádek. Při zpracování se vezme se první node, tedy <username> a na něj se použije komponenta s atributem select="username", která vygeneruje výstup viz výše. Jen místo {{id}} se napíše @id apod. Vezme se další node, a aplikuje se šablona select="password" a tak dále. To všechno však samostatně dělá datový procesor, který zvládá i rekurzi ve vstupních datech. To vše je zabaleno v elementu <form method="POST"> a pokud chceš, tak i v <div class="form-group">

Dík za odpověď. Docela se mi to líbí. Možnou nevýhodu vidím v tom, že není na první pohled tak dobře odlišitelné co je html a co šablonovací jazyk. Ale jde asi o zvyk.
Název: Re:Copy & Paste vs. Špagety
Přispěvatel: Kit 19. 07. 2016, 23:42:01
Dík za odpověď. Docela se mi to líbí. Možnou nevýhodu vidím v tom, že není na první pohled tak dobře odlišitelné co je html a co šablonovací jazyk. Ale jde asi o zvyk.

Je to odlišeno prefixem u XML značek. Každá komponenta šablony začíná například <xsl:template ... Právě tohle je vytýkáno XSLT, vypadá to totiž hrozně ukecaně. S kvalitním editorem je to však pohodička. HTML značky jsou bez prefixu. Jsou povinně párové, jinak se šablona nezkompiluje.

Teoreticky je možné v tom udělat celou aplikaci, ale odporovalo by to zvyklostem rozdělení do vrstev. Zkusil jsem v tom například generování SQL dotazů (struktura DB byla v XML) a fungovalo to docela hezky. Na založení DB při instalaci aplikace je to perfektní. Je to vlastně virtuální procesor, do kterého z jedné strany sypeš DOM a z druhé strany lezou serializovaná data.