Software architectuur bij Windows Forms en webprojecten

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Dit probleem houdt mij al een tijdje bezig..

Ik werk vaak aan projecten waarbij code gedeeld wordt tussen Windows Forms applicaties en webapplicaties. In de praktijk komt het vaak voor dat dit veel minder netjes gebeurt dan je zou willen (lees: er wordt vaak code gekopieerd en aangepast in plaats van hergebruikt, omdat het toch niet helemaal lekker werkt).

Omdat we hierdoor 1 grote rommel krijgen in onze backend code probeer ik hier oplossingen voor te vinden. In theorie lukt mij dat prima, in de praktijk wat minder, omdat elke abstractielaag leidt tot extra werk.. met als consequentie dat collega's er niet altijd aan willen beginnen (begrijpelijk).

Iets dat ik bijvoorbeeld handig vind, is het gebruik van een stateless service layer. Omdat de code stateless is, kun je hem bijna overal voor gebruiken.

Maar goed, als ik dan een Windows Forms scherm ga bouwen dan krijg je al snel:
- De service layer (met ORM models, repositories, transactiemanagement, etc)
- Een viewmodel (die de echte programmacode en state bevat zeg maar)
- De Windows Forms controls / form (die door middel van databinding werken met het viewmodel)

In de praktijk kun je echter ook gewoon de Windows Forms controls aan een DataSet hangen en gewoon de wat complexere code in aparte functies / modules plaatsen en klaar is kees.

De herbruikbaarheid is dan zoek, maar ja.. het scherm bouw je bijna 3 keer zo snel.

En moet je dan een webversie ervan maken, dan gebeurt precies hetzelfde. Code die gevoelig is voor verandering, vanwege een grote complexiteit (een kortingsroutine bijvoorbeeld), wordt dan wel in een gedeelde library geplaatst. Maar de rest wordt vaak opnieuw gebouwd of gekopieerd en aangepast.

Persoonlijk zit ik nu in dubio qua wat wijsheid is.

"Good architecture" vs "Getting shit done" zeg maar. En daar een goede balans in te vinden.

Kortom, hoe ver ga je met het scheiden van functionaliteit? Hoe belangrijk is de reusability? Enzovoorts.

Ik heb jarenlang erg pragmatisch gewerkt en mij eigenlijk niet zo druk gemaakt om een goede architectuur. De laatste jaren ben ik er wel erg mee bezig (design patterns, code reusability, dependency injection, SOLID principes etc), maar vaak wel erg in dubio wat praktisch haalbaar is en wat niet.

Het kan bijna niet dat ik de enige ben die hier tegen aanloopt, dus ik ben benieuwd hoe ver jullie hier in gaan.

Bijvoorbeeld:

Gebruiken jullie altijd een ORM bij Windows Forms? Of toch ook wel gewoon DataSet's omdat het simpelweg makkelijker werkt? Data binding in Windows Forms is immers beperkter dan in WPF. Ik kan het allemaal prima fixen met viewmodel classes die INotifyPropertyChanged implementeren (maar ja, extra werk dus).

Ik lees vaak dat het "not done" is om objecten uit een datalaag te exposen aan de user interface. Gebruiken jullie altijd een mapper tussen ORM classes en viewmodel classes? Of komt het ook weleens voor dat je proxy classes van een ORM aan een user interface hangt?

Enzovoorts.

Ik kan ook niet zo heel veel qua best practices over Windows Forms vinden :) Tegenwoordig is iedereen van de HTML5 SPA's, of MVC web apps, misschien nog WPF. Maar ja, voorlopig werk ik de rest van het jaar aan een Windows Forms applicatie :X En dan wil ik daar toch het beste van maken. Bij web development loop ik minder tegen deze problemen aan, omdat het tegenwoordig sowieso nodig is om een web api te bouwen om nieuwe frameworks als AngularJS te ondersteunen (die min of meer zelf een viewmodel managen, in Angular de scope).

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • SaphuA
  • Registratie: September 2005
  • Laatst online: 10-09 22:00
.

[ Voor 133% gewijzigd door SaphuA op 31-01-2022 14:50 ]


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 14-10 00:53
Ik heb jarenlang erg pragmatisch gewerkt en mij eigenlijk niet zo druk gemaakt om een goede architectuur.
Hier ga je ook de fout in : pragmatisch houdt per definitie in dat je een goede architectuur hebt/maakt. Echter, een goede architectuur op een pragmatische manier houdt in dat je niet in de YAGNI val trapt en dat is best lastig.

Een architectuur met 10 lagen is niet perse een goede architectuur.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
SaphuA schreef op dinsdag 21 april 2015 @ 09:52:
[...]
Hier zit de fout ;)

Een goede architectuur hoeft helemaal niet zo veel extra tijd te kosten. Het zorgt er juist voor dat je applicatie beter onderhoudbaar en uitbreidbaar is. Daarnaast maakt het je code (beter) testbaar, wat weer een betere kwaliteit oplevert.
Het vinden van die "goede" architectuur echter.. pfff :)

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
farlane schreef op dinsdag 21 april 2015 @ 11:28:
[...]
Hier ga je ook de fout in : pragmatisch houdt per definitie in dat je een goede architectuur hebt/maakt. Echter, een goede architectuur op een pragmatische manier houdt in dat je niet in de YAGNI val trapt en dat is best lastig.

Een architectuur met 10 lagen is niet perse een goede architectuur.
Die YAGNI val is inderdaad hetgene waar ik bang voor ben. Aan de ene kant wil je bepaalde lagen introduceren, om de herbruikbaarheid te bevorderen. Aan de andere kant is het de vraag of je die "altijd" nodig hebt, met andere woorden "ga ik alles wel hergebruiken".

Dit kan grote gevolgen voor de architectuur hebben natuurlijk. Zo kun je ook een plattere architectuur hebben die alleen herbruikbare taken heeft.

Bijvoorbeeld "de juiste korting berekenen" of "een order verwerken", maar als we het gaan hebben over CRUD opdrachten in een onderhoudscherm, dat dit wel direct mag met een DataSet, omdat het best kan voorkomen dat je dit nergens anders meer gaat doen.

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 14-10 16:46
Lethalis schreef op dinsdag 21 april 2015 @ 11:35:
[...]
Bijvoorbeeld "de juiste korting berekenen" of "een order verwerken", maar als we het gaan hebben over CRUD opdrachten in een onderhoudscherm, dat dit wel direct mag met een DataSet, omdat het best kan voorkomen dat je dit nergens anders meer gaat doen.
Ik heb een aantal gedachtes bij deze post...

Realiseer je je dat dat deze gedachtegang ontzettend veel invloed heeft op je framework API? :)

Ik bedoel: Als je een framework zou ontwerpen welke toegang moet verschaffen tot een goed gedefinieerd probleem domein. En je wilt dat business logica binnen dit framework blijft en niet zomaar gecopy-paste wordt.
Dan ga je niet ontkomen aan een strak gedefinieerde API voor toegang tot de data in je Domein.

Op het moment dat je toe gaat staan dat er 'shortcuts' zijn tot deze data, waarbij je dus de API van je framework omzeilt dan faciliteer je in feite dit copy paste gedrag.

Naast dat het niet wenselijk is, want je begint wellicht met simpel CRUD. Maar het is altijd slechts een kwestie van tijd voordat er business logica aan toegevoegd moet worden. Met alle gevolgen van dien.

Maargoed, dat gezegd hebbende, niemand verplicht je om ieder aspect van je Domein op dezelfde manier toegankelijk te maken. ;)

Het belangrijkste doel van een framework welke over je probleem domein ligt is dat je je framework verantwoordelijk maakt voor de consistentie van je domein. Dit is helemaal belangrijk als je meerdere clients hebt die je domain consumeren.
Je wilt tenslotte niet dat iedere client zelf verantwoordelijk is voor het op de juiste manier aanmaken van een order in je database (om maar een voorbeeld te noemen).

Dit zorgt er inderdaad voor dat je abstractielagen krijgt, en ja, hierdoor kan het meer tijd kosten om hier schermen bovenop te bouwen dan als je direct naar de database gaat via een dataset oid.
Maar nogmaals je framework is er voor om je domein te bewaken, en de toegang tot deze data zo eenvoudig mogelijk te maken, op een manier dat alle business regels e.d. gewaarborgd blijven.
Dat je daardoor iets meer werk hebt om bij je data te komen, small price to pay als je het mij vraagt.

Maar als je collega's hebt welke je framework niet willen gebruiken omdat ze het te complex vinden. Wellicht moet je je framework dan eens her-evalueren of je hun specifieke use-case niet beter kan ondersteunen.

Aan de andere kant, als je collega's je framework niet willen gebruiken omdat ze de meerwaarde er niet van zien. Dan is dat misschien het eerste probleem wat je moet oplossen :+

Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
D-Raven schreef op dinsdag 21 april 2015 @ 12:37:
[...]
Dit zorgt er inderdaad voor dat je abstractielagen krijgt, en ja, hierdoor kan het meer tijd kosten om hier schermen bovenop te bouwen dan als je direct naar de database gaat via een dataset oid.
Maar nogmaals je framework is er voor om je domein te bewaken, en de toegang tot deze data zo eenvoudig mogelijk te maken, op een manier dat alle business regels e.d. gewaarborgd blijven.
Dat je daardoor iets meer werk hebt om bij je data te komen, small price to pay als je het mij vraagt.

Maar als je collega's hebt welke je framework niet willen gebruiken omdat ze het te complex vinden. Wellicht moet je je framework dan eens her-evalueren of je hun specifieke use-case niet beter kan ondersteunen.

Aan de andere kant, als je collega's je framework niet willen gebruiken omdat ze de meerwaarde er niet van zien. Dan is dat misschien het eerste probleem wat je moet oplossen :+
Het probleem is niet dat ze het niet willen, en de meerwaarde zien ze er ook wel van. Het is meer dat de tijd er niet is (vanuit management). En wellicht dat ze ook niet gewend zijn om op een andere manier te werken.

Als ik backend code schrijf die zij kunnen gebruiken, dan is er sowieso niks aan de hand. Het probleem zit hem meer in het feit dat de projecten waaraan we werken zo groot zijn dat ik nooit alles zou kunnen schrijven, dus zij moeten het dan ook op diezelfde manier gaan bouwen / uitbreiden. En dan kom je in de situatie terecht dat zij er nog meer tijd aan kwijt zijn dan ik. Dat is dan ook nog eens tijd die er niet is.

Het is al moeilijk om de meeste deadlines te halen als je allerlei shortcuts neemt :)

Daarom ben ik ook aan het her-evalueren, zoals je dat zo mooi zegt. "Is het allemaal wel nodig?" is daarbij de voornaamste vraag die ik mezelf stel. In principe zeg jij "ja, want het domein model bewaakt ook alle business regels".

Dit kan in de praktijk ook weer anders zijn dan je verwacht. Zo kan ik veel regelen in de database met triggers en stored procedures. Die regels zijn dan ook meteen universeel.

Al is dit ook weer zoiets dat tegenwoordig minder populair is, omdat het niet in de agile spirit past. Refactoring tools en databases zijn meestal niet elkaars beste vriendjes :) En in de praktijk zie ik wel steeds meer de wens om iteratief te ontwikkelen. De cyclus van iets neerzetten bij de klant, het vervolgens aanpassen en opnieuw releasen, wordt steeds korter.

En dan word je weleens gek van al die code die overal en nergens rondzweeft. Soms moet je iets op 20 plekken aanpassen en dat zou met een goed gedefinieerd domein model vaak gewoon op 1 plek kunnen.

Op dit moment bevind ik me tussen een grote berg oude spaghetti code, een nieuw deel dat ik met meerdere lagen heb ontworpen maar waarmee ik niet snel genoeg kan ontwikkelen, en de vraag hoe ik verder moet.

PS:
Wat ik in mijn vorige post bedoelde was dus het Transaction Script idee:
http://martinfowler.com/eaaCatalog/transactionScript.html

Ask yourself if you are happy and then you cease to be.

Pagina: 1