Autor Téma: Ako na to?  (Přečteno 10312 krát)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Ako na to?
« kdy: 20-04-2014, 11:15:41 »
Mám aplikáciu, ktorú som prerábal. Teraz tam mám neskutočný bordel. Preto som sa rozhodol to prerobiť znova s použitím posledných verzií tried DB (= trieda pre prácu s DB). Rodiča pre triedy (priradzované do MyClass) musím komplet prerobiť s využitím tried DB.
Potrebujem k tomu základnú filozofiu - ako na to. Ide "len o ovládanie užívateľského prostredia".

Mám napríklad stav ako je na priloženom obrázku. Mám definovanú globálnu premennú MyClass, do ktorej priradzujem potrebnú inštanciu triedy. A to potrebujem metodicky vyriešiť.

Trieda sa priradzuje vždy podľa vybratého uzla v strome. To potrebujem aktualizovať v týchto prípadoch:
  - zmením záložku
  - kliknem na niektorý strom. Nemusí to byť na uzol! Ak strom nie je prázdny, tak tam mám vždy vybratý  nejaký uzol.
 
Nemám na to triedu. Využívam na to tieto udalosti:
  - TTabSheet -> onShow
  - VirtualStringTree -> onChange. Stromy majú 1 až 3 úrovne. V prípade komplikácii môžem ten jeden s 3 úrovňami vyhodiť. Je iba informačný.
  - onEnter kde volám onChange
 
Je tam toho podstatne viac. Lenže toto je základ správneho fungovania.
Beriem všetky návrhy čo vás napadnú.

Ak má niekto návrh na iný dizajn aplikácie typu všetko na jednom mieste, ktorý by to zjednodušil, tak sem s ním. Ten môj sa mi síce páči, ale je veľmi komplikovaný. Napríklad pri každej zmene musím vždy robiť aktualizáciu viacerých stromov.

Dávam ukážku onShow. Je z tých komplikovanejších.

Kód: Delphi [Vybrat]
  1. procedure TfrmMain.tsFSRoomShow(Sender: TObject);
  2. var
  3.   VST: TVirtualStringTree;
  4.   NodeLevel: Integer;
  5.   Node: PVirtualNode;
  6.   IsLeftTree: Boolean;
  7.   NodeData: PMyNodeData;
  8.   CurrClass: TDBEndAccessClass;
  9. begin
  10.   pnlFiSeEdit.Parent := sp_FS4;
  11.   pnlRoom.Parent := sp_Rom4;
  12.   IsLeftTree := (cRoom4.VST = cRoom4.LastFocusedVST);
  13.  
  14.   if not Assigned(cRoom4.LastFocusedVST) then
  15.   begin
  16.     if cRoom4.VST.RootNodeCount = 0 then
  17.     begin
  18.       VST := cFise4.VST;
  19.       IsLeftTree := False;
  20.     end
  21.     else
  22.     begin
  23.       VST := cRoom4.VST;
  24.       IsLeftTree := True;
  25.     end;
  26.   end
  27.   else
  28.     VST := cRoom4.LastFocusedVST;
  29.  
  30.   Node := VST.FocusedNode;
  31.   CurrClass := nil;
  32.  
  33.   if IsLeftTree then
  34.   begin
  35.     CurrClass := cRoom4;
  36.   end
  37.   else
  38.   begin
  39.     if Assigned(Node) then
  40.     begin
  41.       NodeData := VST.GetNodeData(Node);
  42.       NodeLevel := VST.GetNodeLevel(Node);
  43.  
  44.       case NodeLevel of
  45.         0:
  46.         begin
  47.           CurrClass := cFise4;
  48.           CurrClass.PrimaryKey := NodeData.PK;
  49.           lst_PozCharMiestnosti.ActivePageIndex := Succ(NodeLevel);
  50.           SetGroupbox(NodeData.KndPr);
  51.         end;
  52.         1:
  53.         begin
  54.           case  NodeData.KndPr of
  55.             1:
  56.             begin
  57.               CurrClass := cFSRoomAd;
  58.               CurrClass.PrimaryKey := NodeData.AdFK;
  59.             end;
  60.             2:
  61.             begin
  62.               CurrClass := cFSRoomIn;
  63.               CurrClass.PrimaryKey := NodeData.InFK;
  64.             end;
  65.             3:
  66.             begin
  67.               CurrClass := cFSRoomAg;
  68.               CurrClass.PrimaryKey := NodeData.AgFK;
  69.             end;
  70.             4:
  71.             begin
  72.               CurrClass := cFSRoomSt;
  73.               CurrClass.PrimaryKey := NodeData.StFK;
  74.             end;
  75.           end;
  76.         end;
  77.       end;
  78.     end;
  79.   end;
  80.  
  81.   CurrClass.VST.SetFocus;
  82.   cRoom4.LastFocusedVST := CurrClass.VST;
  83.   cFise4.LastFocusedVST := CurrClass.VST;
  84.   cFSRoomAd.LastFocusedVST := CurrClass.VST;
  85.   cFSRoomAg.LastFocusedVST := CurrClass.VST;
  86.   cFSRoomIn.LastFocusedVST := CurrClass.VST;
  87.   cFSRoomSt.LastFocusedVST := CurrClass.VST;
  88. end;
  89.  
   
« Poslední změna: 20-04-2014, 11:50:50 od Stanislav Hruška »
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Ako na to?
« Odpověď #1 kdy: 23-04-2014, 12:21:35 »
Nikto žiadnu myšlienku? Čoho by som sa mal držať a naopak a čomu sa vyhýbať? Pri danom návrhu formulára.
Existuje nejaké iné riešenie "všetko na jednom mieste" okrem záložiek? Také, čo by zjednodušilo situáciu.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1127
  • Karma: 42
    • Verze Delphi: 7, 2010
Re:Ako na to?
« Odpověď #2 kdy: 23-04-2014, 13:10:43 »
Asi takhle ...
cist cizi kod je vzdy slozite. Cist tvuj kod je jeste slozitejsi :)

Nikdy neni jeden spravny zpusob, jak kod sestavit. Vzdy zalezi na autorovi.
Musis si s tim pohrat tak, aby funkce byly nejak logicky roztrideny a program
k nim pristupoval efektivne.
Zaroven musis zajistit urcitou univerzalnost, abys nemusel menit vsechno, kdyz
to menis.

A ukazka kodu toho moc neresi. S timhle si budes muset pohrat sam ;)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Ako na to?
« Odpověď #3 kdy: 23-04-2014, 14:35:45 »
Citace
A ukazka kodu toho moc neresi. S timhle si budes muset pohrat sam
Čo sa týka prvej vety, tak som si toho vedomý. Je to len ukážka ako zložito priradzujem triedu.

Druhá veta - to aj mienim. Len som si myslel, či mi niekto nedá všeobecné rady, alebo ako na to išiel, ak riešil podobnú situáciu. Nič viac. Teraz to mám zložito a neviem ako to zjednodušiť.

Skúsim to od prvej najzákladnejšej veci. Ako a kde správne priradzovať objekt s ktorým práve mám pracovať, alebo ako zmeniť návrh formulára/projektu. Teraz to robím na niekoľkých miestach

  - TabSheetShow -> 11 x
  - VST.Change -> 10 x Jeden TabSheet neobsahuje VST
  - VST.Enter -> 5 x volá onChange

a to je trochu veľa. A zakaždým to je ináč.
Tých záložiek mám 12 v 4 základných druhoch. Môžem to znížiť na 11 v 3. Teraz mám triedy definované podľa údajov/stromov.

Momentálne sú kritéria na určenie triedy:
  - VST -> Tag
  - úroveň uzla

Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2586
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Re:Ako na to?
« Odpověď #4 kdy: 23-04-2014, 14:57:51 »
Skúsim to od prvej najzákladnejšej veci. Ako a kde správne priradzovať objekt s ktorým práve mám pracovať, alebo ako zmeniť návrh formulára/projektu. Teraz to robím na niekoľkých miestach

  - TabSheetShow -> 11 x
  - VST.Change -> 10 x Jeden TabSheet neobsahuje VST
  - VST.Enter -> 5 x volá onChange

a to je trochu veľa. A zakaždým to je ináč.
Prvni co bys mel udelat, ze bys mel vyhazet skutecny kodu z handleru udalosti a presunout ho nekam do samostatnych metod. A pak bys mel v tom kodu identifikovat spolecne casti a vyclenit/zobecnit (parametrizovat) je  do samostatnych subrutin. Z jejich volani  to cele poskladat tak, abys vsechno psal prave jednou aneb jak se dnes rika  dusledne uplatnit DRY princip.

A zase to smeruje k MVC architekture -> logika pryc z ksichtu do modelu ;-)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Ako na to?
« Odpověď #5 kdy: 23-04-2014, 15:01:36 »
Citace
A zase to smeruje k MVC architekture
Tú necháme bokom  :)
Tú analýzu urobím a uvidím čo to dá.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Daniel_Andrascik

  • Hrdina
  • ****
  • Příspěvků: 459
  • Karma: 20
    • Verze Delphi: D2007, XE3
Re:Ako na to?
« Odpověď #6 kdy: 24-04-2014, 00:31:30 »
Stando. Nehovor mi ze nevies ako si to vylepsit. Ked som pred 15timi rokmi zacal programovat, bol som samouk. Vlastne dodnes som samouk. To ze si sam prisiel na to ze mas v aplikacii bordel a ze ju treba vylepsit je to najlepsie na co si mohol prist. Na to som prisiel i ja mnohokrat. No a ak si sa dostal do stavu ze si sa rozhodol ze to musis od zakladov prerobit pretoze je to neunosne, tak mi nehovor ze nevies prist aspon na 2 az 3 lepsie riesenia. Netvrdim ze prides uz teraz na idealne riesenia, ale musia ta napadnut aspon jedno dve riesenia ktore budu lepsie ako to ktore si pouzil teraz. Ja som sa presne takto ucil, urobil som proste x aplikacii, ktore neboli zrovna idealne vyriesene. X z nich som bol nuteny optimalizovat, tak som sa zamyslel ze co by bolo lepsie, prehladnejsie, spravovatelnejsie. Tak som to aplikoval. Niekedy som to prerabal i tretikrat, ale uz i po druhy krat bolo citit progres. Bohuzial mne nemal kto poradit, alebo vdaka bohu. Rozmyslal som a vylepsoval som sam. A dnes uz dopredu tusim akou cestou sa uberat, aby mnou vytvoreny kod, bol prehladny, spolahlivy, dobre udrziavatelny a pripraveny na buduce upravy a vylepsenia, ale to len vdaka tomu ze som necakal kto mi ako poradi, ale hladal som optimalnejsie riesenia sam. Ako som povedal, to ze si sam prisiel na to ze mas kod zle rieseny a ze potrebuje vylepsit je velmi dobre. Ved programovanie internych aplikacnych zalezitosti je lego, proste tu skaldacku rozober a poskladaj z inej strany. Variabilita je prevelka, a to ze vies kde ti to skripe, ta samo navadza na najdenie optimalnejsieho riesenia. Hodne zdaru  ;)

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 957
  • Karma: 27
    • Verze Delphi: XE8, Seattle
Re:Ako na to?
« Odpověď #7 kdy: 24-04-2014, 08:14:24 »
Podle mých dosavadních zkušeností je lepší založit novou aplikaci verze 2 a do ní, podle nějakého jednotného scénáře nebo konceptu, převzít to z předchozí verze, o čem si myslím, že je  udělané přinejmenším dobře a že to snese portraci do další, vyšší verze Delphi, čímž se docílí i jisté optimalizace příp. zobecnění, a zároveň to bude mít ambici stát se součástí většího celku nebo systému. Jak říká Daniel A. - jako skládačka lego - to hned poznáš, jesli máš něco správně a půjde to rozebrat a znovu seskládat. No a když ne, tak je tu prostor pro zlepšení, ne? Ale to je jen můj názor :)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Ako na to?
« Odpověď #8 kdy: 24-04-2014, 09:05:15 »
Daniel_Andrascik, JaroB
Najprv ďakujem za reakciu.
Na upresnenie. Nie som rodený programátor. Žiadne vzdelanie v tomto smere, jazykový antitalent a hlava ma prekvapuje čím ďalej tým viac >:( Mám určité danosti, o ktorých už viem*, a s tými musím vystačiť. Som totálny samouk a nemám tu nikoho s kým by som vôbec mohol o programovaní rozprávať.

Mám najmenej (principiálne) štvrtú verziu programu. V predchádzajúcej som mal pár "nezrovnalostí". V terajšej sa nestačím čudovať  ???

Problém je v tom, že neviem, kde by som to mohol zjednodušiť. Aby som sa v tom sám vyznal! A OOP mi robí značné problémy. Ale veľa pomohlo.

Preto som položil otázku. (Ináč rozmýšľate, máte vedomosti a rôzne skúsenosti.) Nechcem algoritmy ani nijaké hotové riešenie. Všetky čiastkové mám. Len ich dať poriadne dokopy. Ja neviem prísť na to ako na to.

  - vykašľať sa na zásadu "všetko na jednom mieste"?
Mám to kvôli užívateľskému komfortu. Ale komplikuje to život.

  - riešiť to novými triedami?
Nenapadá ma vytvorenie iných tried, ktoré by mi pomohli. Analýza kódu a opakované časti zabaliť do tried toho veľa neprinesie. Toho opakovaného kódu tam (predpokladám) veľa nenájdem. Metodika je síce rovnaká, ale vždy sú tam rozdiely. Druh, počet tried a pod.
Existujúce triedy chcem tak či tak prerobiť podľa nových znalostí. To bude dosť roboty - dvakrát sa mi do toho nechce ;). Neviem čo všetko mi to prinesie.

* Čisto technický údaj. Beriem si vzor z tohto webu.  pf1950  >:( :-X
Okrem správ je to tu jediný web kde chodím. Som neskutočne rád, že vás tu mám. Počnúc Semim, Fialom... a končiac pf1957, pepak - nebudem vypisovať všetkých :) Vysoko si cením každú reakciu.

Preto sále "ĎAKUJEM".
« Poslední změna: 24-04-2014, 09:09:48 od Stanislav Hruška »
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2586
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Re:Ako na to?
« Odpověď #9 kdy: 24-04-2014, 10:44:40 »
Mám napríklad stav ako je na priloženom obrázku. Mám definovanú globálnu premennú MyClass, do ktorej priradzujem potrebnú inštanciu triedy. A to potrebujem metodicky vyriešiť. Trieda sa priradzuje vždy podľa vybratého uzla v strome. To potrebujem aktualizovať v týchto prípadoch:
Ja to pro jistotu shrnu, jestli ti rozumim, o co se snazis:

Uz jsme tu rozebirali, ze  potrebujes spojit kazdy uzel v kazdem stromu s nejakymi daty a operacemi, ktere mas soustredene v nejake tride, odpovidajici typu uzlu. V zasade to ma asi 3 ruzna reseni:
1) uplne zapouzdreni, kdy kazdy uzel bude predstavovan instanci vhodne polymorfni tridy (z pohledu OOP idealni reseni, ale vzhledem k tomu, ze VTV je navrzen pro praci se zmolkem pameti a ze Delphi prilis nepodporuje persistenci, takze  by ses mohl zejmena  u D&D operaci s uzly dostavat do svizelnych situaci)
2) explicitni binding, kdyz bys kazdemu uzlu priradil odkaz na vhodnou instanci tridy a tu instanci predaval jako argument do vsech operaci, pokud bys ty operace neprovadel primo s tou instanci
3) a pak neco, co tam mas: hlidas zmeny kontextu uzlu v ksichtu pres nejaka pomocna kriteria a prirazujes do globalni promenne. V tomto pripade samozrejme neexistuje nejaky obecny postup, jak definovat, kde vsude musis hlidat zmenu kontextu a prirazovat globalni promennou. Tam pak IMHO muzes udelat jedine: dat ty operace prepinajici promennou do samostanych metod a ty z tech udalosti volat. A abys to mohl volat z ruznych urovni, je treba tu logiku fyzicky dale rozlecnit.

Osobne bych reseni 3) nikdy nepouzil, 1) by pro tebe mohl byt tvrdy orisek, takze pokud chces neco predelavat znovu, doporucoval bych 2), pokud to chces jen nejak ucesat, tak si udelej poradek v operacich, prepinajicich ten kontext. A pak ti bude jedno, ze pri ladeni treba prijdes na to, ze v nejakem stavu se ti kontext neprepina: jednoduse odchytis udalost a zavolast prepnuti kontextu.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Ako na to?
« Odpověď #10 kdy: 24-04-2014, 11:25:21 »
Vystihol si to dobre. Trocha mi to potrvá, než si to preložím. Už mi tu niečo také bolo navrhované, ale nemal som na to nárok. Teraz už je šanca. Ak budem mať nejaký návrh, tak ho tu dám na posúdenie.

D&D = Drag & Drop? Akého typu by boli dané problémy?
Vďaka.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2586
  • Karma: 133
    • Verze Delphi: D2007, XE3, DX10
Re:Ako na to?
« Odpověď #11 kdy: 24-04-2014, 11:37:48 »
D&D = Drag & Drop? Akého typu by boli dané problémy?
Kopirovani uzlu - problematika melke vs. hluboke kopie. Mam dojem, ze i  Lischke u nekterych operaci uvnitr stromu kopiruje uzly tak, ze se si je uklada do a cte ze streamu. Ale HOSIP, protoze s VTV jsem neco vetsiho delal pred 6+ lety.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Ako na to?
« Odpověď #12 kdy: 24-04-2014, 13:39:50 »
Kopírovanie mi nikdy nefungovalo. :)

Používam postup:
  - vytvor uzol
  - priraď mu údaje
  -  opakuj v cykle podľa potreby
  - zopakuj pre všetky dotknuté stromy
  - vymaž vybraté uzly
« Poslední změna: 24-04-2014, 13:41:47 od Stanislav Hruška »
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4393
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Ako na to?
« Odpověď #13 kdy: 25-04-2014, 11:11:55 »
Model riešenia je v poslednom zozname.
Idem postupnými krokmi. Možno bude len jeden.

Používam
TJvPageControl + TTabSheet + TJvPageList + TJvStandardPage

Predpoklad/podmienka
Na ľavej strane mám vždy dva stromy. Ľavý ma jednu úroveň a môže byť prázdny. Pravý má dve úrovne a nemôže byť prázdny.
Vždy je vybratý nejaký strom a uzol. Prázdny strom ignorujem

Globálne premenné
Budú definované v triede CurrentClass
CurrentClass
  - priradím mu instanciu požadovanej triedy (do MyClass)
  - tu budem riešiť spoločné metódy pre instancie tried
LastFocusedVST - v poli pre každý TabSheet

Predstava modelu
  - každý uzol má odkaz na triedu + samotné údaje
 
Hlavný problém. Správne priradiť patričnú triedu zobraziť na pravej strane zodpovedajúce komponenty. Malo by sa to udiať iba raz.

Kedy sa to musí udiať. Popisujem súčasný stav
  - TabSheet.Show Nastavujem tu
    * panelxy.Parent := StandardPagezz
    * CurrentClass
    * LastFocusedVST.SetFocus
  - VST. Tu sa dosť zamotávam
    * Enter - nastavím LastFocusedVST, volám VST.onChange
    * Change - nastavím CurrentClass, JvPageList.ActivePge 
     
Model riešenia
Ako tak na to pozerám, tak mi vychádza
  - TabSheet.Show
    * CurrentClass.SetMyClass
    * CurrentClass.SetParentPanel
    * CurrentClass.LastFocusedVST.SetFocus 
  - VST
    * CurrentClass.LastFocusedVST. Len ak došlo k zmene
    * CurrentClass.SetMyClass
      1 pri zmene LastFocusedVST ináč
      2 pri zmene NodeLevel     

Kde mi to škrípe? Nejaké iné návrhy a pod.
Keď si to takto hodím na papier, tak tomu začínam aj rozumieť  :)   
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline starous

  • Mladík
  • **
  • Příspěvků: 59
  • Karma: 2
Re:Ako na to?
« Odpověď #14 kdy: 25-04-2014, 12:36:43 »
Hlavný problém. Správne priradiť patričnú triedu zobraziť na pravej strane zodpovedajúce komponenty. Malo by sa to udiať iba raz.

Optimalizace se dělá jako poslední. Určitě není nezbytné, aby se to dělalo jenom jednou.

Co takhle použít návrhový vzor Factory nebo něco podobného? Do uzlu si vložit jen identifikaci třídy. Až budeš třídu potřebovat, tak si jen z uzlu přečteš identifikaci a podle toho zvolíš třídu.

Čtu si ten tvůj úvodní příspěvek a vůbec se mi nelíbí, že máš nějakou globální proměnnou MyClass, kterou neustále měníš.

pf1957 ti radil tři způsoby řešení, ze kterých se i mě zamlouvá varianta 2.

Návodný příklad: Mám 10 dětí a řeknu jim "namaluj domeček". Každý ten domeček namaluje jinak. Když budu chtít, aby domeček namalovalo konkrétní dítě, tak si je očísluju a vytvořím si funkci NamulujDomeček a jako parametr jí předám číslo dítěte (nebo místo čísla použiju k identifikaci jméno).

Protože tam těch operací může být víc, tak si je třeba uložím do třídy, kterou vytvořím podle návrhového vzoru Singleton.