Arutelu: DTO või mitte DTO

by melborp 18. oktoober 2007 11:35

Eile õhtul oli arutelu Silver Sepaga, kes on Vita Group OÜ tarkvara arhitekt ning tal oli mure teemal, et kas kasutada DTO -d või mitte oma lahenduses (kus kohas täpsemalt seda loe alt poolt). Kuna olen DTO -de kasutamise temaatikaga varem tegelenud, siis andsin nõu, et vältida temal samade vigade tegemist, mis mina olen teinud.
Antud teema on juba aastaid arutluse all DomainDrivenDesign -i foorumis ja pole siiamaani ühest vastust - eks kõik sõltub kontekstist nagu ikka tarkvara arhitektuuri puhul. Igatahes, pika arutelu käigus jõudsime huvitava lahenduseni, mida sooviksin jagada ja arutelu üles utsitada, et mida kaasarhitektid ja tarkvara disainijad eestis mõtlevad. Aga enne veel kui asuks lahenduse kirjeldamiseni, tuleks lugejale anda tausta ja viia konteksti.

Taust

Selleks, et paremini mõista allolevat konteksti on soovituslik tutvuda mõningate terminite ja materjalidega.

Mis on DDD?
Domain Driven Design -i (DDD) raamat (lühikokkuvõte kuskil 100 lk)

Mis on DTO (Data Transfer Objekt)?
Tegu on Java kommuni poolt välja töötatud mustriga. Antud mustri kirjeldusele sooviks lisada omapoolsed kommentaarid. DTO objekte kasutatakse tegelikult ka laiemalt ja need ei pruugi alati tähendada mitmete objektide üle viimist ühest kihist teise. Pigem võib see tähendada huvi, teisele kihile näidata piiratud vaadet objektist ja võimaldada piiratud tegevusi objektil (kõlab nagu interface?).

Küsimus, kasutada DTO -d või mitte, kerkib tavaliselt kahel juhul.

Veebiteenus ja DTO

Sul on lahendus, mis suures pildis koosneb kahest osast - veebiteenus ja klient. Veebiteenus peab publitseerima teenuse meetodeid, mille sisendid ja tulemused on mõistliku suurusega andmehulgad. Need ei tohi liiga ühendust liiga koormata ning suhtlus teenusega peab olema kiire. Kui sinu domeeni objekt on rikas objekt - väärtuslik ning paljude omaduste ja tegevustega (meetoditega), siis võib juhtuda, et paljuds omadused ei pruugi üldsegi olla vajalikud kliendi poolele. Selleks, et kliendi pool saaks minimaalseima objekti kasutatakse antud juhul DTO -d.
DTO kasutamine atnud juhul, aga toob lisa halduskulusid (on rohkem koodi mida hallata), kuna nüüd peate looma domeeni objektist DTO -ks ja DTO -st tagasi Domeeni objektiks muutmise koodi. Kusjuures antud koodi loomine on suht tülikas ja igav tegevus.

Domeeni teenus ja DTO

Sarnane vajadus on domeeni teenuste (DDD mõistes) ja kliendi kihtide vahelises suhtlemises. Sa soovid kliendi kihile (kihtidele) näidata piiratud võimalustega objekti.

Kontekst

Antud arhitektuuri konteksti viimiseks olen loonud lihtsustatud näidisarhitektuuri, mida mina olen tihti oma lahendustes kasutanud ja mis sarnane natukene ka Silveri poolt kasutatud arhitektuurile. Igatahes kasutab see Model-View-Presenter mustrit, millele on teil ka tark silm peale visata (kusjuures ma olen plaaninud antud mustrist blogida, aga pole kahjuks selleni veel jõudnud, väga väärtuslik muster. Sellest kirjutab ka Martin Fowler UI arhitektuuri mustrite all). Hetke seisuga on aga MVP jagatud kaheks. Lisaks järgitakse Domain Driven Designi disanipõhimõtteid (üleval on link raamatule, mis neid tutvustab).

Arhitektuur ise näeb välja nagu all oleval UML -i mudelil (kusjuures siin on kirjas ainult antud kontekstile tähtsad osad, muidu on veel näiteks DataAccess -i osa jne).

MVP_ddd_näide

Domeen (Domain) kujutab endast lahenduse äriloogikat (äriobjektid ja nende omadused). Kui domeen on korralikult disainitud ja arenduse käigus hallatud, siis peaks see kiht olema täiesti taaskasutatav. Domeeni teenus (service) on domeeni objekte ja loogikat kontrolliv ning haldav kiht. See võib olla peenike (kõigest suunab edasi domeeni objektidele tegevust) või paksem, kus ta haldab näiteks andmebaasi ühendust jm ressursse ning ka ligipääsu ja domeeni objektide kasutamist. Tavaliselt Service -i kihis on n-ö use case -i põhised teenused ning ühe teenuse sees võib olla mitme domeeni objektiga tegevusi.
Presenterid on kontrollerid, mis täidavad view -d andmetega ja haldavad sündmusi, mis View -s toimuvad. Ka suhtleb Presenter domeeni teenusega, et domeeni vajalikke muudatusi (tegevusi) teha. Kusjuures Presenter näeb View -d läbi interface -i ainult. View on puhtalt visuaalne pool - kasutaja kontrollid (usercontrol) ja lehed. Nad sisaldavad endas kujunduselemnte, paigutust jne. ja suunavad kõik sündmused edasi Presenterile.

Probleem

Täisinformatsioon (omadused ja meetodid) domeeni objektide kohta on vajalik ainult domeeni teenustel, kes haldavad domeeni objekte. Presenter ja View ei vaja muud, kui informatsiooni mida kuvada (mis juhuslikult on ka domeeni objektis hetkel). Nad ei käivita meetodeid domeeni objektidel, sest me soovime et õiged kihid teeksid õigeid tegevusi ja kõik oleks korralikult enkapsuleeritud.
Probleemi sõnastuseks oleks seega: "Kuidas piirata ligipääsu domeeni objektidele nii, et domeeni teenus saaks kõikke teha aga Presenter ja View näeksid limiteeritud versiooni samast objektist (saaksid ainult lugeda omadusi näiteks)? Otsime kõige lihtsamat viisi, mis ei põhjusta suuri lisa koodihaldustööd."

Lahenduse variandid

Minule tulevad lahendustena kohe pähe kolm varianti:

  • Interface -i kasutamine (kolm erinevat realiseerimist)
  • DTO objektid
  • Domeeni objektid (kui ükski ülemistest ei aita)

Alustame seletamisega alt poolt ülesse.

Domeeni objektid

Siin kohal võib mõelda, miks ma selle variandi üldse kirja panin. See ei täida ju tingimusi ja lahenda probleemi. Kahjuks aga on see lahendusvariant, mis tihti peale valitakse, kuna see ei nõua üldse lisa koodi loomist ja haldamist. Antud lahenduse puhul eeldatakse, et Presenter ja View on alati hallatud sama meeskonna poolt, mitte kunagi keegi domeeni objekte valesti ei kasutaks ja üldse jälgitakse aktiivselt arhitektuuri reeglite järgimist ning tagatakse nii, et antud lahendus on sobiv.

DTO objektid

DTO objektid on muidu tore lahendus ja tagab kindlasti, et kuidagi domeeni objektile ligi ei saada. DTO objekti kasutamine tähendab seda, et Domeeni teenus saab sisse ja väljastab alati DTO objekti ning see saadakse domeeni objekti transleerimisel DTO objektiks. DTO objektid on eraldi klassid, mis on 1:1 seoses domeeni objektiga ja, mis sisaldavad neid domeeni omadusi, mida siis view (kliendi) pool vajab kindlasti.
Muidu on lahendus suhteliselt elegantne ja kindlasti korrektne ning üheselt mõistetav. Kahjuks, aga ei vasta lahendus nõudele - me ei soovi hallata veel sama palju klasse, kui on domeeni klassid ning luua transleerimise koodi (ja iga kord uuendada seda, kui uueneb domeeni objekt).

Interface

Liides ehk interafce on variant, mis mulle kõige rohkem meeldib ja kui mõelda, et me soovime piirata, mis funktsionaalsusi domeen välja näitab, siis liides saab selle ülesandega kindlasti hakkama. Originaalselt muidugi on liides mõeldud selleks, et ühendada kõikki sarnaste omadustega objekte ja nõuda objektilt, et ta teatud omadusi/tegevusi võimaldaks. Hetkel vaatame me asja veidi teise nurga alt :)

C#.Net -st on võimalik implementeerida liidest kahte moodi - explicitly (välja toodud, mis interfce -i omadus on) või implicitly (vaikimisi).

Antud lahendus hõlmab mõlemat lähenemist. Pakun välja, et domeeni objektid peaksid implementeerima IDtoObjekt -i, milles on kõik omadused kirjas, mis Presenterile ja View -le on tähtsad.
See nõuab osalist lisatööd, aga mitte nii palju kui DTO -de puhul ja transleerimist ei ole vaja ise realiseerida.

Domeeni objekt implementeeriks tavalised propertid, mis ei ole domeeni objekti või domeeni objekti listi tüüpi implicitly (ehk vaikimisi) ja muud omadused explicitly. Põhjuseks on probleem, et te soovite kasutada domeeni teenuse kihis täisfunktsionaalsust domeeni objektidelt ja samas võimaldada Presenter ja View kihis ainult IDtoObjekti interface -de läbi objektide kasutamist. Kõige lihtsam viis näidata, mida sellega mõtlen on koodi abil. All olev kood illustreeribki lahendust, mida kirjeldasin.

Oletame, et me soovime niisugust DTO objekti näidata Presenterile ja View -le:

public interface IDtoEntity
{
    /// <summary>
    /// Liides võimaldab ainult Get -da Teksti.
    /// </summary>
    string Tekst { get; }

    /// <summary>
    /// See tuleb siis explicitly implementeerida 
    /// ja võib nõuda lisaarendus natukene :(
    /// </summary>
    IDtoEntity2[] Entitid { get; }
}

Selle implementatsioon näeks siis välja niisugune:

/// <summary>
/// Entity on tüüpiline domeeni objekt.
/// </summary>
public class Entity : IDtoEntity
{
    private Entity2[] _massiiv;
    private string _muutuja;

    /// <summary>
    /// Domeeni objekti tüüpi massiv.
    /// Seda ei saa IDtoObjekt liideses avalikustada, 
    /// kuna võimaldab ligipääsu päris domeeni objektile.
    /// </summary>
    public Entity2[] Entitid
    {
        get { return _massiiv; }
        set { _massiiv = value; }
    }

    /// <summary>
    /// Tavalist string tüüpi property.
    /// Implicitly implementeeritud (piirame liideses!).
    /// </summary>
    public string Tekst
    {
        get { return _muutuja; }
        set { _muutuja = value; }
    }

    /// <summary>
    /// Explicitly implementeeritud IDtoEntity2 tüüpi massiiv.
    /// Antud juhul ta castib/konverteerib teist tüüpi loeteluks/massiiviks.
    /// </summary>
    IDtoEntity2[] IDtoEntity.Entitid
    {
        get { return Entitid; }
    }
}

Kusjuures toetav klass Entity2 ja liides IDtoEntity2 on täiesti tühjad

/// <summary>
/// Tühi domeeni objekt 2.
/// </summary>
public class Entity2 : IDtoEntity2 { }

/// <summary>
/// Tühi IDtoObjekt interface 2.
/// </summary>
public interface IDtoEntity2 { }

Meil on olemas nüüd funktsionaalsus ja jääb üle vaid proovida seda kasutada ja vaadata, kas kõik toimib nii nagu soovime:

public Runner()
{
    //Service -i seest kasutamine
    Entity entity = new Entity();
    entity.Tekst = "Vaartus";
    string m = entity.Tekst;
    Entity2[] s6brad = entity.Entitid;

    //Presenterist ja View -st kasutamine
    IDtoEntity entityDto = entity;
    m = entityDto.Tekst;
    //entity.GetString = "Vaartus"; // EI saa omistada :( Ainult get on.
    //Saame kätte IDtoEntity2 massiivi:
IDtoEntity2[] s6brad2 = entityDto.Entitid; }

Mulle tundub, et antud lahendus toimis, nii nagu me soovisime ja erikoodi tuli ka luua vähe ning transleerimist ei pidanud eraldi tegema? OK, interface -e tuleb hallata (neil puudub realisatsioon, on ainult kirjeldus).

Muidugi leidub antud lahendusel ka kitsaskohti.
Kõigepealt, kui soovite tagastada domeeni objekti, siis View -le ja Presenterile soovite te tagastada IDtoObjekt -i ning peate selle explicitly implementeerima (samas säilitate samad nimetused propertitel). Lisaks, juhul kui te kasutate generic liste (näiteks IList<Entity>), siis peate explicitly implementeeritud elemendi sees ka manuaalselt konverteerima oma uude tüüpi listiks (ehk käima läbi kõik IList<Entity> elemendid ja lisama nad uude listi IList<IDtoEntity>. Saaks teha generic helperi, mis teeb seda lihtsalt IList -de jaoks. See probleem on generic tüüpidel (tüüp on sisse kirjutatud)).

Üleskutse

Mul oleks ülimalt heameel kuulda teiste arendajate arvamusi! Diskuteeriks veidi kommenteerides antud postitusele.

  • Mis kitsaskohti teie näete?
  • Mis arvate üldiselt?

Tags:

.Net | Arhitektuur | Disainivõtted | DDD | C#

Kommentaarid


oktoober 17. 2007 02:30
Toon reaalelulise näite, kus DTO on kasutusel ja väga omal kohal. On üks suur objekt, mille küljes päris hea patakas küllaltki keerukaid kollektsioone. Selle objekti pidev liigutamine serveri ja kliendi vahel oleks paras overkill. Kliendis on vaja objektide hierarhias kuskil keskel asuvast kollektsioonist teha list, mida näidata kasutajale. DTO-st paremat lahendust pole ma antud juhul siiani leidnud.

Ma usun, et arhitektuurilises mõttes võib tekitada igasugu vahvaid vaidlusi, kuid kui midagi on vaja päriselt ära teha ja toimima saada, siis on kindlasti mõttekas kaaluda DTO kasutamist, et vähendada koormust nii serverile kui ka kliendile (serialiseerimine ja deserialiseerimine) ning mitte ummistada võrku.

DTO kasutuselevõtt lahendas minu juhul päris paljud probleemid, sest XML-ine 5 megast jurakat on ikka päris piin kokku ja lahti lappida ning mööda võrku liigutada.

Seega praktiline pool minust räägib igati DTO kasuks.


oktoober 17. 2007 07:36
Veel üks märkus. Lugesin kuskilt targast raamatust, mida meil kontoris natuke tekkinud on, ja ühtlasi sain kinnitust meie arhitekti käest, et domeeni objektid ei tohiks laiendada DTO objekte või nende interface-e implementeerida.

Soovitus oli selline, et DTO objekt initsialiseerib ennast talle tuntud objekti põhjal ennast ära. See tähendab seda, et domeeni objektid säilitavad sõltumatuse vahekihist, kus DTO-d kasutatakse.

Point on lihtne - DTO pole osa core objektmudelist, vaid lihtsalt vahend, mida kasutatakse liidestamisel. Seega pole korrektne arhitektuuri mõttes, et domeeni objektid tunnevad DTO teemat.

Aga nüüd asun kasse tuvastama. Tong


oktoober 17. 2007 16:23
Paneks samuti mõned tekkinud mõtted kirja.

DTO-d veebiteenustes.

Nagu Gunnar eespool juba kirjutas, on hea domeen ja DTO kiht hoida teineteisest sõltumatud. See sõltumatus hea kahtepidi, nii DTO-sid pakkuva süsteemi poolt kui ka neid kasutava süsteemi poolt, eriti juhul kui mõlemal süsteem on ehitatud domeenimudelipõhises arhitektuuristiilis. DTO-del on siinjuures veel oluline roll olla (koos teenusemeetodite kirjeldustega) andmesuhtlusprotokolli (või teenuste kokkuleppe) oluliseks osaks.

Teenuseid tarbival süsteemil on mõistlik hoida oma domeen sõltumatu DTO-dest, sest see ei lase suhtlusprotokollis toimunud muudatustel levida domeenimudelisse. Muudatus lõhuks ainult suhtluskihi või -komponendid. Sellest on pikemalt juttu Evansi DDD raamatus mustri “Anticorruption Layer” juures.

Teenust pakkuvale süsteemile on hea eristada domeeni ja DTO-sid seetõttu, et nende granulaarsus on erinev. Erinevalt Gunnari näitest (kus suur domeenimudeli objekt ei mahu DTO-ks), tuleb pigem kokku puutuda vastupidise olukorraga, kus domeenimudel on oma olemuselt liiga peenekoeline ning mingi osa eksponeermiseks väljaspoole on mõistlik domeenimudeli klasse nö flat-imaks lüüa. Samas Gunnari näitest säilib mõte, et kõike domeenimudelis pakutavat ei tarvitse mõne teenuse kontekstis vaja olla väljaspoole näidata. Samuti on DTO-de ja domeenimudeli klasside ülesanne erinev, DTO-d on andmestruktuurid protsesside vahel loksutamiseks (ehk siis andmed on eraldatud funktsioonist), domeenimudelis on andmed ja funktsioon grupeeritud klassideks. Seetõttu on domeenimudelit ennast üsna tülikas andmevahetuskihti otse tõsta, sest see pole sobilik andmevahetuseks. Lisaks säilib klientsüsteemis DTO-sid kasutades võimalus domeenimudelit korrastada selliselt, et selle muutused ei mõjuta andmevahetusprotokolli (ehk siis jällegi omamoodi Reverse-Anticorruption Smile.

Aga nagu alati, on erandeidSmile On tulnud ette selliseid süsteeme, kus teenust teenust pakkuva süsteemi DTO objektid on teadlikult viidud ka teenust kasutava süsteemi “domeenimudeliks”. See on mõistlik sellistes olukordades, kus teenust tarbiv süsteem on väga tihedasti seotud teenust pakkuva süsteemiga ning teenust tarbiv süsteem ei oma ise väga tõsist sisemist loogikat. See oleks siis omamoodi UI rakendus teenuste ees. Sellises süsteemis pole see DTO ja domeenivahelise tõlkimise töö väärt seda vaeva, sest need on oma olemuselt suhteliselt identsed, mis viib järgmise teemani:

DTO ja domeenimudeli omavaheline tõlkimine on üsna töömahukas ja nüri hallata. Siinkohal on oluline hoiatada ühest viimastes projektides ilmenenud anti-mustrist, kus DTO-d üritatakse kujundada sellised, mis oleksid universaalselt sobivad kõikide teenuset andmevahetuseks. Sellise võtte tulemusena tekib DTO-dest omamoodi domeenimudel, mis omakorda põhjustab üsna ohtliku coarse-grained ja sügava sisend- ja väljundhierarhiaga teenuse liidese, mis põhjustab DTO ja domeenimudeli struktuuride teisendamisel teineteiseks päris tõsist vaeva. Tõenäoliselt võivad sellised teenused omandada veel mitmetähendusliku käitumise, kus teenuse nime järgi tehtavale tegevusele tehakse lisaks veel miskiseid tegevusi, mis on kodeeritud objektistruktuuride muudatuste kujul. Samas on selle mustril isegi miskitpidi pointi transaktsionaalsuse haldamisel, kuid kogu selle antimustri kirjeldamine võiks olla lausa eraldi pikk jutt Smile Mõistlik on DTO-d pigem hoida võimalikult flatid ja parajasti nii suured, kui palju teenuse kontekst tahab.

Optimeerimisest teenuste liidese disainil. Flat-iks tegemisel ja DTO-de kokkusättimisel ei maksa karta suuri andmehulkasid liidese disainimisel. DTO-d ongi suurte batchide andmete ümbertõstmiseks Smile ja igasugune optimeerimine reaalsete testandmeteta selles faasis on üsna rumal tegevus, mis raiskab aega ja viib fookust sisulise probleemi lahendamiselt vasakule.

DTO-d kasutajaliideses.

Domeeniobjektid UI-s
Kui UI on kasutatavate teenustega tihedalt seotud (ehk kogu UI tehtav ongi teenuste kasutamine ja domeeni kasutab ainult see UI), siis pole võibolla mõistlik ajaliselt ja rahaliselt seda abstratksiooni hallata. Täiesti mõeldav võib olla UI-le ligipääsu andmine domeenimudeli objektidele või -teenustele. Kuigi siin blogijutus on domeenimudeli objektide väljapaistmist halvaks peetud, võib hoopis küsida, et miks peab domeenimudeli tegema sellise, et seda keegi kasutada ei oska või miks peab domeenimudelit UI eest ilmtingimata peitma, kui UI ja domeenimudel väga tihedalt seotud on.

2. DTO-d UI-s
Ilmselt kehtib suures plaanis sama jutt, mis veebiteenuste puhul - DTO-de kasutamine UI-s sõltub olukorrast. Kui UI ja domeenimudeli suhtlemisel kasutada DTO objekte, siis tekib paratamatult kerge overhead domeenimudeli pakutavate teenuste ja UI kavatsuste omavahelises tõlkimises, sest nad on teineteise küljest kaugele abstrahheeritud selliselt, et vahepeal käib ka üks paradigmamuutus (OO -> protseduurne andmetöötlus), mida on jälle tülikas disainida/hallata. Aga jällegi, see kõik sõltub UI ja domeenimudeli sisulisest sidususest või selle vähesusest. Mõnikord võib olla mõistlik DTO-sid kasutada.

3. Domeenimudelile DTO-genereerimise liidesed.
Esiteks, mis minu domeenisilma riivab on see, et domeenimudelile tekib sõltuvus DTO-kihist, mis on ilmutatud C# liideste (interface kujul). See jätab mulje, et domeenimudel implementeerib DTO-de andmete tekitamiseks vajalikku loogikat, mitte ei ürita ilmutatud kujul valdkonnaloogikat koodimudelisse valada. Selline lahendus on mõeldav juhul, kui võib kindel olla et iga domeeniobjekti kohta vastab ainult üks DTO objekt. Samas enamasti kipub nii olema, et ühe domeeniobjekti kohta tekib mitu DTO-vaadet, vastavalt (veebi)teenuse kasutamise kontekstile. Samuti võib muutuda raskemaks domeenimudeli refactordamine (DTO-liidese implementeerimiseks ei tarvitse leiduda piisavalt infot omavat klassi), kuigi see poleks ilmselt võimatu mingi tasemeni. Lisaks kumab siin jällegi läbi see anti-muster, millest ennem kirjutasin, mis üritab DTO-d teha domeenimudeliks. Ilmselt saad sellest aru, kui üritad ühe klassi asemel lahendada mitmete klasside kobarate DTO-deks tegemist.

lihtsalt sellised lühidad mõtted pikkadest teemadest.
ehk on abiks Smile


oktoober 19. 2007 23:04

Tere Gunnar. Väga põhjalik ja asjakohane vastus Smile


Ka mina olen neid raamatuid lugenud ja tõesti korrektseid disainivõtteid järgides DTO on see viis, kuidas asju lahendada (Klient-Server kontekstis).


Antud lahendus ei sobi asendama DTO -d, kuid võib lihtsustada arendust, kui tegu on mitte klient-server lahendusega vaid ühes masinas jooksva lahendusega (mis ei kasuta veebi teenuseid vms). Näiteks oleks desktoplahendus, mille kõik komponendid on samas masinas, aga ülesehitus on kihiline (DAO – Domeen – Domeeni teenus – Presenters – UI). Mulle tundub, et sellise ülesehituse juures saab interface -i kasutades vähendada tülikat koodiloomist (ja haldust), mida keegi teha ei taha (samas on niisuguse ülesehitusega lahendusi vähe?).


Pean kurbusega tõdema, et interafce ei ole sobilik lahendus n-ö klient-server suhtluseks, kuna interface -i ei saa serialiseerida (see ei ole andmetüüp) (tegin veidi proovi nii vanade .Net -i veebiteenustega kui ka WCF -i teenustega). Kui tegu on klient-server lahendusega, siis tihedamini soovitakse täiesti eraldada domeeni objekti ja objekti, mis üle kantakse (näiteks nhibernate -i kasutades on domeeni objekti andmed laetud nii, see on kindlas Unit Of Work –s ning te ei saa seda objekti kasutada pärast kliendilt tagastuse saamist (see ei ole enam kõlbulik – järjepidavus on katkenud). DTO on ainus, mida kasutada saab.) DTO on ühele kindlale eesmärgile pühendunud klass ja tavaliselt ei oma komplekset loogikat – üheselt mõistetav, lihtne disain.  


Kindlasti võib DTO loogika viimine Domeeni klassi hakata segama Domeeni klassi loogikat, puhtust. See ei ole domeeni objekti põhiülesanne. Antud lahendus ei ole just kõige ilusam ja puhtam viis realiseerida domeeni objekti suhtlust UI poolega. Samas on ta võte, mida kaaluda. Kusjuures ise olen niisugustel juhtudel edastanud domeeni objekti enda UI kihti ja teinud reeglid selgeks arendajatele sõnadega (ja code review –dega). Ei ole näinud DTO kasulikkust, kui tegu ei ole Klient-Server keskkonnaga (liiga palju ekstra haldustööd, kui muutub domeeni objekt). Kuigi algselt DTO niisuguste lahenduste juurde mõeldud poldud, on DTO just olnud tihedamini mõeldud lahendusvariant.


Eks igas lahenduses tuleb teha omad otsused – kõik sõltub kontekstist.


Mitu kassi said tuvastatud?



oktoober 20. 2007 04:15

Minu kommentaar sai lisatud lugemata Karu kommentaari. Avastasin just hetk tagasi, et see on Spam alla läinud ning publitseerisin käsitsi Smile


Tänud karu mõtete eest, otse täkkesse. Väga põhjalik.


Head poindid liidese kasutamisest 3. punkti all.



oktoober 20. 2007 22:19
NHibernate-iga tegime kunagi ühe päris massiivse katse. Lähemalt ei hakka seletama, karmilt pikk kirjatükk tuleks. Kirjutasin sellest kunagi ka kande, mis segane nagu eelmise presidendi kõne mahepõllumajandajatele: www.dt.ee/.../">.Net Remoting, NHibernate ja generic kollektsioonid. See, et objekt edasi-tagasi loksub, pole NHibernate-i jaoks probleem. Session.SaveOrUpdateCopy() teeb töö kenasti ära.

Interface-ide ja generice kasutamisega soovitan olla hoolikas ja ettevaatlik, sest mõlemaid, kui neid kasutada, peab tundma ka suhtluskanali teine pool ja viga, mida tihti generice kasutamisega tehakse, on see, et eeldatakse, et need on alles ka peale kompileerimist. Paraku on generic asi, mis peale kompileerimist kaob ning selle põhjal tehakse valmis vaid need tüübid, mida on kompileeritavas koodis kasutatud ja mida on definitsiooni juures öeldud, et vaja on.

Ahjaa, täna oli siin kõva päev - seitse kassi tuli kokku. Tong


oktoober 23. 2007 03:10
Meeldiv uudis, et oled NHibernate -ga mässanud Smile Õige, SaveOrUpdateCopy() saab hakkama objekti uude sessiooni "viimisega".

Geneerikutega tuleb tõesti ettevaatlik olla, tegu on tõesti määratud tüübiga. See et Genericuks on List ja sul on olemas ka TeineKlass -i implementatsioon. Ei tähenda, et sa saad implicitly muuta List -ks - tüüp on fikseeritud (loe: kompileerimisel kirjutatakse sisse).

DTO -de haldamiseks võib tõesti teha automaatse genereerija klassi põhjal (eraldi console rakendus) või siis custom tool, mida saab käivitada klassi pealt (nagu siis, kui soovid resx failist strongly typed ressurssi teha).

Veebiteenuste juures Interface -i kasutamine minul tekitas kaks väljundit:

WCF: WCF on tublim, ta tagastab sulle objektid. Aga sinu kliendi pool tõesti teab vaid object tüüpi Frown

Old Web Services:melborp.net/.../...hOldWebServicesAndInterface.png


Kui soovid kasse vältida, sisi registreeritud kasutajatel neid ei küsita Smile


oktoober 25. 2007 16:19
NHibernate-i kasutame päris palju. Ma loobusin kohe algul heaga sellest ideest, et hakata ise DAL-i ja objektide runtime-i looma. See on jube tegemine ja efektiivse lahenduseni jõudmine eeldab ikka tõsise profi teadmisi.

Mis puutub DTO-de automaatset genereerimist, siis võib uurida näiteks sellist vidinat nagu CodeSmith (http://www.codesmithtools.com/). Äkki on seal võimalik luua vastav template. Kuigi see ei pruugi ehk kogu tööd ära teha, aitab see ehk tubli paar sammu soovitud eesmärgile lähemale.

P.S. Kasside lugemise vastu pole mul midagi. Lahe tegemine bittide ja baitide vahele ju Smile

Lisa kommentaar




  Country flag

biuquote
  • Kommentaar
  • Preview
Loading



Autorist

Taavi Kõosaar

 Tere, olete sattunud mu blogi peale. Olen Taavi Kõosaar - tarkvara arendaja, arhitekt ja konsultant keskendudes arendamisele .NET -i platvormil. Hetkel asun peamiselt Rootsis, kus töötan Süsteemi Arhitektina toote/teenuse arendamisel, mida kasutatakse üle Euroopa. Lisaks tööle blogin, kirjutan artikleid, pean loenguid, treeninguid, reisin, loen raamatuid, sukeldun, teen sporti, fotografeerin, osalen Eesti arendajate kommuunis ...

Siit leiate minu mõtisklused ja seiklused tarkvara arendamisega, .NET -ga ja Team Systemiga.

Kalender

<<  september 2010  >>
estekonerela
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

Liikmelisus

www.eneta.ee

Team System MVP

Tutvu minu LinkedIn profiiliga

Minu Eneta profiil

Lugejatest

Kaart:

Lugejad:

Hetkel lehel:

hit counters

Külastajaid:

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Siin toodud arvamuseid saab käsitleda vaid kui minu isiklike arvamusi, need ei kajast vähimalgi kombel ühegi minu tööandja arvamusi ja nägemusi.

© Copyright 2010 Melborp.NET