Commando instellen DSL-model

advertisement
VOORWOORD
SAMENVATTING
INHOUDSTAFEL
VOORWOORD ..................................................................................................... 2
SAMENVATTING ................................................................................................. 2
INHOUDSTAFEL .................................................................................................. 2
INLEIDING ......................................................................................................... 3
ALFABETISCHE LIJST VAN GEBRUIKTE AFKORTINGEN ....................................... 4
1
QFRAME ............................................................................................... 5
1.1
1.2
1.3
1.4
.NET gespecialiseerd ............................................................................
Behandelen van projecten ....................................................................
Aanbieden Consultancy ........................................................................
Werknemers ........................................................................................
2
STAGEOPDRACHT ................................................................................. 7
2.1
2.1.1
2.1.2
2.1.3
2.1.4
Uitvoering ............................................................................................ 7
Eerste fase ..............................................................................................8
Tweede fase ............................................................................................8
Derde fase ..............................................................................................9
Vierde fase ..............................................................................................9
3
REALISATIE ....................................................................................... 10
3.1
3.2
3.3
Diagram ............................................................................................. 10
Generatie ........................................................................................... 11
Import en export ............................................................................... 11
4
DOMAIN SPECIFIC LANGUAGE ........................................................... 12
4.1
4.2
4.3
4.3.1
4.3.2
4.3.3
4.3.4
4.3.5
Ontwikkelingstools ............................................................................ 13
DSL-Tools ........................................................................................... 13
Belangrijkste vensters ....................................................................... 13
Toolbox ................................................................................................ 13
Hoofdscherm ......................................................................................... 13
Proporties ............................................................................................. 13
DSL Explorer ......................................................................................... 14
DSL details ............................................................................................ 14
5
INSTELLEN DSL-MODEL ...................................................................... 15
5.1
5.2
5.3
5.3.1
5.3.2
5.4
5.4.1
5.4.2
5.4.3
Aanmaken DSL - project..................................................................... 15
Opstarten DSL-Model ......................................................................... 15
Aanmaken nieuwe elementen ............................................................ 16
Elementen ............................................................................................. 16
Connectoren .......................................................................................... 17
Eigenschappen toekennen ................................................................. 17
Type bepalen ......................................................................................... 17
Enumeraties toevoegen .......................................................................... 18
Soort bepalen ........................................................................................ 18
5.4.3.1
5.4.3.2
5.4.3.3
Normal ............................................................................................................................. 18
Calculated ......................................................................................................................... 18
Custom Storage ................................................................................................................. 19
5.4.5.1
Text Decorator .................................................................................................................. 21
5.4.4
5.4.5
5
6
6
6
Sleuteleigenschap bepalen ...................................................................... 20
Decorators toekennen............................................................................. 20
3
5.4.5.2
Icon Decorator................................................................................................................... 21
6
DSL-MODEL BEKIJKEN ....................................................................... 26
6.1
6.2
Elementen toevoegen......................................................................... 26
Overzicht elementen bekijken ............................................................ 26
7
COMMANDO INSTELLEN DSL-MODEL .................................................. 28
7.1
7.1.1
7.1.2
7.1.3
7.1.4
7.1.5
7.2
7.3
7.3.1
7.3.2
7.3.3
Aanmaken menu commando’s ............................................................ 28
Symbols ............................................................................................... 28
Commandplacements ............................................................................. 29
Buttons ................................................................................................. 29
Menu’s .................................................................................................. 29
Groups ................................................................................................. 30
Toewijzen constanten ........................................................................ 30
Acties toekennen aan Commando ...................................................... 30
Toevoegen aan model: ........................................................................... 30
Statusfunctie bepalen: ............................................................................ 31
Actie bepalen......................................................................................... 32
8
GEBRUIK VOOR GENERATIE ............................................................... 33
8.1
8.2
8.3
8.3.1
8.3.2
8.4
8.5
8.6
Instellen processor ............................................................................ 33
Opstellen Templates .......................................................................... 35
Aanmaken Templates ......................................................................... 35
Losse templates ..................................................................................... 35
Templates via constante waarden ............................................................ 35
Template schrijven............................................................................. 36
Methode schrijven .............................................................................. 36
Extra functionaliteiten schrijven ........................................................ 38
9
EXPORTEER DSL-MODEL ..................................................................... 39
9.1
9.2
9.3
Gebruik maken store .......................................................................... 39
Schrijven basisclass ........................................................................... 39
Schrijven export class ........................................................................ 40
10
IMPORTEER NAAR DSL-MODEL ........................................................... 41
10.1
10.2
10.3
Importeer vanuit DSL ......................................................................... 41
Importeren buiten DSL ...................................................................... 42
Positioneren Shapes .......................................................................... 43
5.5
5.6
5.7
5.8
Groeperen van elementen ..................................................................
Acties op shapes ................................................................................
Rules en validatie ...............................................................................
Custom Editor instellen ......................................................................
21
22
23
24
BESLUIT .......................................................................................................... 43
LITERATUURLIJST ............................................................................................ 43
BIJLAGEN ......................................................................................................... 44
INLEIDING
4
ALFABETISCHE LIJST VAN GEBRUIKTE AFKORTINGEN
DB
Database
DSL
Domain Specific Language
EA
Enterprise Architecture
T4
Text Templating
UML
Unified Modeling Language
XML
Extensible Markup Language
XSLT
Extensible Stylesheet Language Transformation
5
1
QFRAME
QFrame is het .NET competence center binnen Cronos NV, de bekende e-business
integrator uit Kontich. Cronos NV is een groep van ondernemingen die vaak nauw
samenwerken maar dan gespecialiseerd in hun domein. Qframe heeft zich
gespecialiseerd in maatwerk voor .NET en Microsoft Office toepassingen en stelt 30
mensen tewerk.
De focus ligt op technische kennis en QFrame tracht dan ook continu op de hoogte te
blijven van de laatste nieuwigheden op dat gebied. Toch zijn ze bovenal bezig met het
zoeken naar de meest pragmatische oplossing in de context van de klant, wat niet altijd
betekent de meest recente technologie.
Het merendeel van de QFrame-klanten is marktleider of is een belangrijke speler
binnen hun bedrijfstak. Deze status aanhouden is vanzelfsprekend geen sinecure en
enkel mogelijk mits een strenge bewaking van de verschillende bedrijfsprocessen. Het
is dan ook niet verwonderlijk dat deze bedrijven bij de selectie van hun IT-partner
nauw toekijken op de ervaring en kwaliteit van de externe medewerkers die men wenst
in te schakelen. Wij zijn er van overtuigd dat specialisatie, mits de juiste omkadering
en begeleiding, een antwoord vormt op de vraag naar de nodige expertise en kwaliteit.
1.1
.NET gespecialiseerd
Microsoft .NET is de laatste jaren uitgegroeid tot hét referentieplatform voor
ontwikkelen van software wereldwijd. Deze technologie wordt alom geloofd
zijn zeer uitgebreide mogelijkheden, snelheid en productiviteit bij het ontwikkelen.
.NET kunnen diverse types toepassingen ontwikkeld worden, wij concentreren
echter vooral op bedrijfskritische data-entry en backend systemen.
het
om
Met
ons
QFrame was trouwens al vóór het ontstaan van .NET erg actief met het ontwikkelen
van administratieve maatsoftware, toen nog in COM-technologie. Deze kennis, vooral
rond ontwikkeltool Visual Basic 6, is nog steeds in huis en ook veel gevraagd. Sinds de
introductie van .NET in 2002 wordt voor nieuwe ontwikkelingen bijna integraal voor
.NET gekozen.
We ontwikkelen zowel Windows- als Web toepassingen, maar ook de ontwikkeling van
Webservices en integratie modules met andere platformen behoren tot de activiteiten.
Voor dataopslag wordt bij voorkeur Microsoft SQL Server
connectiviteit naar Oracle databases verloopt probleemloos.
ingezet, echter
ook
Voor maatwerk .NET projecten richt QFrame een gestandaardiseerde projectflow in,
waarin centraal versiebeheer, geautomatiseerde tests en builds en hiermee
geïntegreerde communicatie en rapportage via Visual Studio Team System centraal
staan.
6
1.2
Behandelen van projecten
QFrame houdt zich vooral bezig met het realiseren van projecten. Elk project krijgt een
team toegekend. In dit team zullen alle belangrijkste technische taken op zich worden
genomen: developer, technical coach & technical architect, … Wanneer andere zaken
nodig zijn kunnen ze altijd beroep doen op gespecialiseerde mensen van andere
bedrijven uit de Cronos groep.
Het gebeurt ook dat het gemengde projectteams zijn. Deze teams bestaan uit
medewerkers van QFrame maar ook medewerkers van de klant. Dit zorgt er voor dat
de klant op een korte termijn een uitgebreide ervaring op doet.
Steeds wordt er aan de klant duidelijke afspraken rond gemaakt hoe ze QFrame
makkelijk kunnen bereiken. Dit gebeurt via het “Single point to contact” concept dat ze
hanteren. Steeds een plaats waar ze QFrame kunnen bereiken.
1.3
Aanbieden Consultancy
Klanten die nood hebben aan assistentie of technische kennis kunnen ook terecht bij
QFrame. Wanneer er een project tijdig afgerond moet worden en ze even fulltime
assistentie nodig hebben om dit te realiseren. Vooral om een specialist voor een
beperkte tijd in te huren of om meer coaching te hebben bij een project.
Maar buiten de .NET en office ontwikkelaars hebben ze een uitgebreid pakket van
activiteiten aan te bieden zoals:






1.4
het opstellen van een verkennende studie
maken van een (UML gebaseerde) functionele analyse
ontwerpen van een applicatie architectuur
interne voorstellen realiseren
intern project management
bugfixing op bestaande projecten, etc.
Werknemers
Voor QFrame zijn de werknemers ook belangrijk. Ze kiezen ervoor om een goede
reputatie te creëren voor hun medewerkers. Omdat voor vele computers een hobby is
en sommige medewerkers sleutelposities beschikken op forums en newsgroups van
Microsoft. Een paar medewerkers zijn zelf gecertificeerde Microsoft trainers.
Medewerkers hebben voluit de kans om zich bij te schaven door middel van cursussen,
(inter)nationale congressen en conferenties.
7
2
STAGEOPDRACHT
Qframe heeft een framework ontwikkelt met de naam Leaf.net. Dit framework helpt
hen om snel bepaalde klassen te genereren die verder helpt om snel applicaties te
kunnen starten. Dit gebeurt nu via omzetting van een commit-model naar xml. Uit deze
xml-files worden dan via een tool die gebruikt maakt van bepaalde XSLT-bestanden om
de xml-files om te zetten naar code.
De bedoeling is dat dit via een nieuwe methode te doen. Het commit-model wordt dan
omgezet naar een domain specific language model. De opdracht is dus om een dslmodel te ontwikkelen en ervoor te zorgen dat je een commit-model kunt omzetten naar
een dsl-model. Het is ook de bedoeling om het dsl-model om te zetten naar code via
texttemplating.
De stap om het commit-model om te zetten naar een dsl-model moet ook in de
omgekeerde richting gebeuren. Dit is namelijk voor het feit dat er bepaalde
noodzakelijke scripts bestaan die gebruik maken van het Commit-model, vooral de
scripts die de tabellen opvullen met de informatie uit het Commit-model.
Dit zou ook helemaal in het bestaande gedeelte moeten worden opgenomen. Dus dat
het via hun tool gemakkelijk kan worden gebruikt om code te genereren want de
andere opties moeten nog steeds beschikbaar zijn als mensen daar voor kiezen. Dit is
wordt in de toekomst wel anders, het wordt de bedoeling dat ze in de toekomst enkel
met DSL gaan werken en de stappen om code te genereren reduceren naar twee
stappen. Namelijk het ontwikkelen van het model en van daaruit dan code te generen
Als extra kan het nog zijn dat het via Guidance Automation Toolkit mogelijk moet zijn
om via de xml-file van de dsl-model en de templates om daarmee de code te
genereren.
2.1
Uitvoering
Qframe heeft in de loop van de jaren een aantal tools ontwikkelt die hen helpt in het
ontwikkelen van een applicatie. Zo is er een framework ontstaan met de naam
“LeaF.net”. Dit staat voor “Large Enterprise Application Framework”. Het is een soort
van uitbreiding voor het .net framework van microsoft.
Leaf.net framework is een uitgebreid framework dat hen helpt bij het creëren van
uitgebreide zoekmogelijkheden, rolebased security of meertaligheid. Dit zijn niet de
enige functies want hier boven is eigenlijk ook de codegenerator ontwikkeld. Dit helpt
hen verder in het schrijven van de classes rond de data invoer van een applicatie.
Hierbij zal dus de ontwikkeltijd verkorten en zal de kwaliteit aardig toenemen.
Omdat dit voor mij de belangrijkste functionaliteit is omdat hier mijn nieuwe
functionaliteit behoort.
8
Hier is een schema met de functionaliteiten van nu en wat het zou moeten worden:
Om dit te realiseren is het verdeeld in vier fases. De eerste fase is de belangrijkste fase
omdat dit centraal staat in de nieuwe generatie. Fase drie en vier zijn minder belangrijk
omdat deze stappen in de toekomst misschien overbodig worden. Fase 1 en 2 blijven
dan de belangrijkste stappen in de generatie van code.
2.1.1
Eerste fase
Aanmaken van het model zelf. Het model is de basis voor alles, je kan niet beginnen
aan de generatie voordat je model af is. Je kan ook niet beginnen aan de import of
export als er geen model is. Eerste fase is dus om het model zo op te stellen dat het
voldoet aan alle noden voor het Leaf.NET framework. Alles wat in het bestaande
commit-model zit zou je moeten terugvinden in het nieuwe DSL-model.
Ook moet er voor gezorgd worden dat het een duidelijk overzicht heeft en dat je
rekening houdt met alle soorten relaties tussen alle elementen.
2.1.2
Tweede fase
Generatie is redelijk belangrijk omdat anders het DSL-model nutteloos is (buiten het
bekijken ervan). Allereerst moet ik ervoor zorgen dat je vanuit het DSL-model kan
genereren naar meerdere files. Daarna moet ik zorgen dat de T4-scripts worden
aangemaakt voor elk soort van bestand. Daarna moet ik zorgen dat het mogelijk dat ik
het resultaat van de generatie rechtstreeks naar bestaande projecten kan genereren.
9
2.1.3
Derde fase
Derde fase is in de toekomst misschien niet meer nodig maar momenteel is het nog wel
een belangrijke stap. Het importeren van een commit-model naar je DSL-model. Dit
zou vanuit de bestaande generator moeten kunnen gebeuren zonder dat je het DSL
project moet opstarten.
In principe zou je dan niets meer moeten aanpassen aan je DSL-model om te kunnen
genereren naar de juiste code. Omdat DSL een object georiënteerde taal is moet de
import best gebeuren via objecten want je kan het ook via xml doen maar dit is niet zo
gebruiksvriendelijk voor de aanpasbaarheid. Later kunnen er zaken aan het commitmodel wijzigen zodat het snel kan worden aangepast.
2.1.4
Vierde fase
De vierde fase en de derde fase kunnen worden omgewisseld. Omdat de medewerkers
vertrouwd zijn met het Commit-model en omdat er nog tooltjes bestaan die gebruik
maken van een Commit-model moet het mogelijk zijn om een bestaand DSL-model te
exporteren naar een Commit-model. Dit Commit-model kan je dan makkelijk gebruiken
in de bestaande tools. Importeren en exporteren zijn gelijkaardig en wanneer je één
stap kan, zal de omgekeerde stap via dezelfde manier lukken. In principe zou je een
model kunnen exporteren en nadien weer importeren. Dit zou dan hetzelfde resultaat
moeten geven dan voordien.
10
3
REALISATIE
Voor de grootste gedeelte van de opdracht heb ik me bezig gehouden met fase 1 en 2
van mijn opdracht. Ik kon vertrekken van een bestaand model dat standaard werd
meegeleverd met de DSL-Tools. Dit was natuurlijk het minimum van het minimum dat
nodig was. Een uitbreiding was noodzakelijk om alle elementen die Qframe gebruikt in
hun generatie te tonen.
3.1
Diagram
Een diagram bestaat meestal uit classes maar kan ook tabellen bevatten. Tussen beide
elementen bestaat er eventueel een link. Elke class heeft de mogelijkheid om attributen
en methodes toe te kennen. Een tabel bevat dan weer velden en bevat foreign keys en
primary keys.
Tussen beide soort van elementen kan je relaties trekken. Er bestaan twee soorten
relaties tussen dezelfde soort van elementen. Tussen twee tabellen of twee classes kan
je relaties leggen die één richting uitgaan of relaties leggen die gelden langs beide
richting. Er is wel een speciale soort van relaties namelijk relaties met een veel op veel
multipliciteit. Dit is enkel tussen twee classes mogelijk omdat tabellen dit niet kunnen
bevatten.
De link tussen beide is dan weer enkel mogelijk tussen één tabel en één class. Je kan
geen meerdere tabellen aan één class hangen. Weer heb je hier het speciaal item voor
veel op veel relaties. Hier heb je steeds een tabel die gelinkt is met de veel op veel
relatie. Dit moet in DSL met een tussenstuk omdat je geen associaties kon leggen
tussen associaties en elementen. Het tussenstuk bevat maximum twee classes en één
tabel als link.
Zo kan een diagram er uitzien:
11
3.2
Generatie
Voor het generatie gedeelte was het lang een zoekwerk hoe ik voor elke class een
aparte file kon genereren. Dit kon uiteindelijk door een commando toe te kennen en zo
via een bepaalde methode de generatie te regelen. Standaard zal de generatie gewoon
gebeuren in het model maar er is de mogelijk om een andere locatie te selecteren. Zo
kan je snel kiezen om het resultaat van de generatie te gebeuren in een bestaand
project of op een bepaalde locatie.
Wanneer een bestand bestaat zal hij het bestand overschrijven. Zo zijn er baseclasses
die de grootste informatie bevatten van de modellen. Voor elke baseclass bestaat er
een class die gebruikt maakt van de baseclass. Een baseclass moet bij elke generatie
worden aangepast maar de class die gebruik maakt van deze baseclass niet. In deze
class wordt er eigen code bijgeschreven die zeker niet mag worden verwijderd door een
nieuwe generatie. Dit wordt voorkomen door te controleren of het bestand bestaat of
niet. Wanneer het al bestaat zal hij het niet uitvoeren, anders zal hij een nieuw bestand
aanmaken met de gepaste code.
Via verschillende commando’s kan je bepalen welke taal en welke classes je kunt
genereren. Je kan ook per tabel beslissen of je wilt dat het wordt gebruikt in de
generatie.
3.3
Import en export
Import en export gebeurt op dezelfde manier. Telkens wordt er voor elke class of tabel
een object aangemaakt. Die wordt dan opgevuld met de correcte informatie. Wanneer
alles over het object is ingevuld zal hij het object toevoegen aan de algemene collectie.
Een verschil is dat import buiten het DSL-model wordt gebruikt en dat zorgt voor een
lastiger pakket. Een DSL-bestand is eigenlijk een XML-bestand, maar omdat je het
model kunt bekijken in een speciale designer bevat het een hoop extra informatie. Alle
elementen worden in een soort van collectie opgeslagen. Het toewijzen in een collectie
gaat nog wel maar om een collectie toe te kennen aan een bestand is veel moeilijker.
Een XML-bestand bevat geen extra instellingen. Dit is voorkomen door een bepaald
element te gebruiken van het DSL-model. Je kan een store zo toekennen aan bestand.
Het importeren gebeurt via de bestaande generator. Je kan nu een nieuwe optie kiezen
“Commit To DSL” tussen de opties. Er zal dan een formulier worden getoond waar je
informatie kunt wijzigen zoals de locatie en de naam. Zo kan je dan bevestigen zodat
er een nieuw DSL-model word aangemaakt.
Het exporteren gebeurt gewoon via een commando. Je moet dan de naam en locatie
invullen. Wanneer je bevestigt, wordt er een nieuw Commit-model aangemaakt op de
locatie.
12
4
DOMAIN SPECIFIC LANGUAGE
Domain specific language is een ruim begrip. Het is eigenlijk een soort van abstracte
taal die gebruikt wordt om ontwikkelde systemen duidelijker te maken. Het is een soort
van analysetaal waarbij je modellen verduidelijkt. Het is mogelijk om schema’s op te
stellen die bepaald zijn naar uw eigen eisen. Het hangt ook niet vast aan één bepaalde
programmeertaal, het staat volledig los daarvan en kan dus zowel gemaakt worden
voor Java schema’s, .net schema’s of andere talen.
De naam zegt ook waarvoor het dient, het is een taal die veel gericht is op een bepaald
domein. Elk model is dan ook anders en is gebaseerd op het systeem dat ontwikkelt
moet worden. Het geeft dan ook een heel goed beeld over het toekomstige systeem.
Het kan ook voor andere zaken gebruikt worden dan voor programmeerzaken weer te
geven. Je kan het echt puur gebruiken om analysezaken weer te geven. Bijvoorbeeld
om de structuur van je website te ontwikkelen of zelfs helemaal niets met informatica
te maken hebben. Wanneer je een elektrische schakeling wilt tonen aan klanten.
Maar het dient vooral dus voor programmeren. Met de domain specific language tools
is het mogelijk om je eigen modellen te maken en vanuit die modellen code te
genereren. Dit bestond al wel voor UML modellen maar die modellen zijn vast bepaald
en bij dsl kan je de modellen zo aanpassen naar je systeem.
Domain specific language zal nooit alles verduidelijken maar het is gewoon veel
gerichter op je behoeftes dan programma’s. Het is ook een vrij nieuw begrip dus
momenteel staat de ontwikkeling van Dsl-tools nog niet helemaal op punt.
13
4.1
Ontwikkelingstools
Om domain specific language te ontwikkelen bestaan er verschillende tools want het is
geen vast gedefinieerde taal. Doordat er geen vast stramien voor de taal is, kan
eigenlijk Word al ideaal zijn. Soms is het maar tekstueel weergeven van een systeem.
Maar om het visueel toch iets beter voor te stellen en om sneller te kunnen werken
heeft Microsoft een tool ontwikkelt. Het heeft de simpele naam meegekregen “Dsl
tools”. Dit zit niet standaard in Visual studio. Dit zit wel in de sdk van Visual studio die
je gratis kan downloaden van de microsoft site. Opgelet: Visual studio moet de
professional edition zijn. Anders zal je dsl tools wel kunnen installeren maar niet
gebruiken.
In 2005 versie was het nog in de kinderschoenen en zullen er wel vaak
stabiliteitsproblemen opduiken. Sinds 2008 is het beter maar je merkt wel weinig
verschil maar hij zal veel stabieler werken.
4.2
DSL-Tools
Dsl-tools is eigenlijk een soort verzameling van classes in c# die samen met een
achterliggende compiler zorgen voor de weergave van het klassemodel. Elk object dat
je aanmaakt zal ook zijn eigen classes krijgen.
De structuur van de tool is altijd uit twee c#-solutions namelijk DSL en DSLpackage.
DSL is de verzameling van de objecten met al hun classes. Hierbij zul je dus geen
classes vinden die te maken hebben met het creëren van het model. Dat is aanwezig in
DSLpackage. Hier vind je alles dat te maken heeft met de weergave van het dsl-model
maar niets rond de objecten die getoond worden.
4.3
Belangrijkste vensters
Dsl-tools is bijna identiek aan Visual studio maar heeft natuurlijk extra vensters die
gericht zijn op domain specific language.
4.3.1
Toolbox
Toolbox heeft elk Visual studio project ook maar voor dsl is er een aparte categorie aan
toegevoegd die alle elementen bevat voor het aanmaken van een dsl-model. Ook alle
elementen die niet tot een class diagram behoren zijn hier in weergegeven.
4.3.2
Hoofdscherm
Het hoofdscherm is in principe gewoon een scherm waar je bestanden kan wijzigen.
Standaard staat hier dsldefinitions.dsl open. In dit bestand worden de nieuwe
elementen toegevoegd voor je model. Dit is een bestand waar je de elementen van de
toolbox naar toe sleept. Eigenlijk is het een dsl-model op zich.
4.3.3
Proporties
Dit is ook identiek aan Visual studio. Hier vind je niets speciaal in buiten dat de
proporties gebaseerd zijn op elk element van het model.
14
4.3.4
DSL Explorer
Dsl Explorer bestaat uit de verzameling van elementen in het dsl-model. Elk soort
collectie vind je hier terug. Bepaalde zaken kan je alleen hier instellen. Alles is hier
ingedeeld in collecties. Hier vind je ook gewoon de verzameling terug van elementen en
relaties maar ook kan je hier een overzicht krijgen hoe de xml in elkaar zit. Elk element
kan je bekijken welke attributen en relaties er zijn.
4.3.5
DSL details
Dit vind je standaard onderaan terug. Hier kan je gedetailleerde informatie wijzigen.
Vooral rond decorators, compartimenten en ook alle informatie rond relaties wijzigen.
15
5
INSTELLEN DSL-MODEL
5.1
Aanmaken DSL - project
Het aanmaken op zich is geen moeilijk proces. Alleen sommige elementaire zaken zijn
belangrijk dat je die goed kiest. Bijvoorbeeld welke extensie je diagrammen gaan
hebben. Deze moet uniek zijn en nog niet bestaand. Daarom kan je beter iets langer en
een bepaalde afkorting gebruiken.
1. Je opent Visual studio en selecteert “New project”
2. Je kiest bij Other project types onder de categorie extensibility voor: Domain specific
language designer
3. Selecteer in het keuze venster voor het gewenste diagram. (Voor mijn opdracht is het Class
Diagram)
4. Je kiest een naam voor je project
5. Je kiest je unieke extensie. (Bij bestaande extensies ga je problemen krijgen)
6. Daarna vul je een naam van project in en tot wie het behoort en de namespace
7. Kies voor New key of voor bestaande keyfile (assembly informatie file)
8. Druk op finish
5.2
Opstarten DSL-Model
Standaard wordt er een basis gemaakt voor een class diagram. In Visual studio is er
een class diagram viewer aanwezig voor elk project. (rechtermuisknop -> view as
class diagram). Dit class diagram wordt als basis genomen voor de dsl-tools.
Wanneer je het standaard class diagram wil bekijken, hoef je enkel op het groene
pijltje of menuoptie start debugging te kiezen in het menu debug. Er zal een nieuwe
Visual studio geopend worden. Het is geen normale Visual Studio maar een
Experimental Hive versie. Dit is de versie waar je zaken kunt proberen die invloed
hebben voor de Visual Studio omgeving. Omdat het nogal kritisch is om de gewone
Visual Studio te gebruiken, gebruiken ze een versie die bij beschadiging gemakkelijk
kan hersteld worden zonder dat je de hele Visual Studio moet herinstalleren.
Wanneer je nog niets aangepast hebt, zal hij altijd een voorbeelddiagram aanmaken.
Dit vind je terug in de solution Explorer van je model met de naam: sample.”extensie”.
Dit bevat een voorbeelddiagram waar alle elementen aanwezig zijn van het model.
De omgeving is vertrouwd. Standaard bestaat de omgeving uit een toolbox aan de
linkerkant, centraal dan de ruimte voor bekijken van de modellen. Aan de rechterkant
bevind zich dan het proporties venster en de solution Explorer. Onderaan bevind er zich
nog de error-list.
16
Opmerkingen:
In xp kunnen er fouten gebeuren en kan het zijn dat je geen Diagram editor kan
openen van je bestand. Dit moet je oplossen door de buildopties van DSLpackage aan
te passen in je project. Je volgt deze stappen om er voor te zorgen dat dit gebeurd:
1. Selecteer proporties bij DSLpackage
2. Kies build events
3. Vul in: "C:\Program Files\Microsoft Visual Studio 2008
SDK\VisualStudioIntegration\Tools\Bin\regpkg.exe"
/root:Software\Microsoft\VisualStudio\9.0 “$(TargetPath)”
4. Rebuild voor uittesten of het werkt
In principe zou dit standaard moeten gebeuren. Standaard zal hij bij stap 3 9.0exp
kiezen. Maar bij XP wordt deze map soms niet gevonden. Daarom zal hij het niet
uitvoeren zoals je wenst. Een foutmelding geeft hij niet maar wanneer je opstart krijg
je een “Package Load Failure”.
Het is belangrijk om ervoor te zorgen dat je telkens twee acties uitvoert: “transform all
templates” en dat je daarna het project build via “Build solution”. Daarom kan je best
een macro opbouwen die de twee acties uitvoert.
1. Selecteer tools -> macros -> new macro project
2. Rechtermuisknop op nieuwe macro -> Set as recording project
3. Selecteer tools -> macros -> recording temporaryMacro
5.3
Aanmaken nieuwe elementen
Omdat het noodzakelijk is om nieuwe elementen toe te voegen die meer tot uw noden
behoren moet je alles eens grondig doornemen. Meestal kan je de basis wel gebruiken
en moet je enkel nieuwe elementen toevoegen.
Een nieuw element kan je gewoon slepen vanuit de toolbox. Je hebt keus tussen drie
verschillende types:
5.3.1
Elementen
Een element is een item dat kan toegevoegd worden aan het diagram zonder echt
afhankelijk te zijn van andere elementen. Natuurlijk is dit enkel het geval wanneer het
element mag toegevoegd worden aan het rootelement. Elk diagram heeft één
rootelement die eigenlijk de verzameling vormt van alle elementen. Sommige
17
elementen zijn wel speciaal. Zij behoren niet tot het rootelement maar tot een
basiselement. Dit is vaak een embedded element: voorbeeld is een modelattribuut van
een class. Wanneer je dus het basiselement verwijderd, zal hij alle subelementen mee
verwijderen.
Om een element te tonen moet je er een Geometric shape of een image shape aan
koppelen. Zonder shape zal hij het niet tonen. Een geometric shape is een bepaalde
vorm: een vierkant, cirkel, ruit, … en een image shape is een afbeelding die je zelf wil
gebruiken voor het element. Een compartiment shape is een speciale shape die bedoelt
is om subelementen weer te geven. Elk compartiment wordt dan gelinkt aan een
subelement en zo zullen de subelementen worden weergegeven in het hoofdelement.
5.3.2
Connectoren
Connectoren zijn de relaties tussen de elementen. Zonder connectoren kan je geen
elementen met elkaar verbinden. Er zijn twee types: embedded connectoren en
referenced connectoren. Hier bepaal je dus of het element een alleenstaand geval is of
het element een onderdeel is van een ander element.
Een referenced connector is altijd afhankelijk van twee elementen. Dit kan twee
verschillende elementen zijn maar kan ook hetzelfde element zijn. Bij elke relatie kan
je dan bepalen welke multiplicity het bevat. Wanneer aan beide kanten 0..* is
geselecteerd, zal hij geen extra proportie voorzien maar bij een 0..1 zal hij in het
element een proportie aanmaken waarbij je een element kan selecteren dat voldoet
aan de relatie.
Ook een connector heeft een connector shape nodig om het te tonen. Wanneer dit niet
gebeurd, kan je wel relaties leggen maar kan je ze niet zien. Dit kan problemen geven
wanneer je nieuwe relaties wil leggen en relaties wilt verwijderen.
5.4
Eigenschappen toekennen
Eigenschappen kan je aan alles toekennen. Zowel aan connectoren, elementen en zelfs
aan shapes. Elk ingesteld eigenschap kan je standaard eigenschappen toekennen.
Eigenschappen kunnen echt dienen als statische informatie voor het element. Een
eigenschap kan van elk soort type zijn: boolean, string, integer of een eigen type.
Types kan je definiëren in de dsl explorer bij domain types. Hier hoef je enkel de naam
en namespace ingeven. Dus wanneer je een eigen class heb aangemaakt en je wil
objecten daarvan gebruiken moet je hier de naam van de class ingeven en de
namespace.
5.4.1
Type bepalen
Standaard ontbreken er een paar dus als voorbeeld kan je zorgen je het type color kunt
toevoegen. Dit zal er voor zorgen dat je bij je eigenschap nu een listbox krijgt met alle
mogelijke kleuren.
18
1. Je selecteert dsl explorer
2. Je klikt met je rechtermuisknop op het hoofdelement en selecteert “add external type”
3. Je vult als naam in: Color
4. Je vult als namespace in: System.drawing
Vanaf nu kan je bij het type in plaats van string of integer ook color selecteren.
5.4.2
Enumeraties toevoegen
Enumeraties zijn lijsten met mogelijke keuzes. Het is mogelijk dat een eigenschap
enkel vier mogelijkheden mag bevatten. Dit kan je best oplossen door een enumeratie
toe te voegen. Enumeraties bevinden zich gewoon tussen de domain types. Hierbij kan
je dus gewoon de enumeratie selecteren als type.
1. Je selecteert dsl explorer
2. Je klikt met je rechtermuisknop op het hoofdelement en selecteert “add enumeral type”
3. Je vult als naam in van de enumeratie
4. Je kan nu via de rechtermuisknop steeds nieuwe elementen aan de enumeratie toevoegen
5.4.3
Soort bepalen
Een eigenschap kan afhankelijk zijn van andere eigenschappen. Daarom is er een
proportie “Kind”. Deze optie heeft drie mogelijkheden:
5.4.3.1
Normal
De eigenschap is van niets afhankelijk. Dit zal gewoon een eigenschap zijn dat je kan
aanpassen naar wat je wilt. Deze wordt standaard geselecteerd als je een nieuwe
domainproperty aanmaakt. Wanneer je van een andere optie voor deze optie kiest, dan
zal hij geen rekening meer houden met de aangemaakte methodes die nodig zijn voor
de andere opties.
5.4.3.2
Calculated
Wanneer dit geselecteerd is, betekend dat de eigenschap afhankelijk is van andere
eigenschappen. Vanaf nu is de eigenschap ook read-only. Je kan de eigenschap niet
meer manueel aanpassen. Het zal wel telkens aanpassen als je de afhankelijke
eigenschappen aanpast.
Je moet hier wel een methode schrijven waar je bepaald welk de gerelateerde
eigenschappen zijn. Het kan ook dat je gewoon een functie schrijft die een bepaalde
formule uitvoert zonder dat er een gerelateerde eigenschap achter hangt.
De naam van de functie is niet standaard te kiezen. Je kan best eerst alles builden om
de naam te achterhalen. Hij zal dan een foutmelding geven dat er een bepaalde
methode ontbreekt. Die methode schrijf je dan in een aparte class die dezelfde naam
heeft als het element van de eigenschap.
19
1. Selecteer de gewenste domain property
2. Verander de property kind naar calculated
3. Transform all templates en rebuild
4. Krijg je foutmelding
5. Maak nieuwe klasse aan in DSL
6. Zorg voor de juiste klasse bij “public partial XXX” -> xxx is domain class name
7. Schrijf de functie die ontbreekt (zie foutmelding voor de naam)
8. Voer dan je acties toe en return het resultaat
Stel dat: De maxlength van een attribuut van een class is afhankelijk van het type. Dan
moet je deze class schrijven:
Public partial class ModelAttribute
{
Public Int GetMaxlengthValue()
{
If(this.Type.equals(“String”))
{
Return 255;
}else{
Return 50;
}
}
}
5.4.3.3
Custom Storage
Dit gaat eigenlijk een stap verder als calculated. Het verschil is dat dit de eigenschap
niet read-only maakt. Je kan het attribuut aanpassen maar hier is het mogelijk dat
wanneer je het attribuut aanpast, dat je dan ineens de afhankelijke attributen aanpast.
Hier is natuurlijk voorzichtigheid geboden want als je het verkeerd invult, zal hij
misschien één van de twee afhankelijke eigenschappen niet mee aanpassen.
1. Selecteer de gewenste domain proportie
2. Verander de proportie kind naar customStorage
3. Transform all templates en rebuild
4. Krijg je foutmelding
5. Maak nieuwe klasse aan in DSL
20
6. Zorg voor de juiste klasse bij “public partial XXX” -> xxx is domain class name
7. Schrijf de functie die ontbreekt (zie foutmelding voor de naam)
8. Voer dan je acties toe en return het resultaat
Hier heb ik in je in plaats van een Get-methode een Set-methode nodig. Om het
voorbeeld van hierboven aan te vullen:
Public void SetMaxLength(int newValue)
{
If(newValue==255){
this.Type=”String”;
}else{
this.Type=”Integer”;
}
}
5.4.4
Sleuteleigenschap bepalen
Sleuteleigenschappen zijn standaard niet nodig omdat elk element een ID toegewezen
krijgt. Maar ID’s zijn niet echt bruikbaar wanneer je interacties gaat doen in code later.
Daarom is het handig om een domainproperty als vervanging te kiezen. Hiervoor moet
je bepaalde instellingen aanpassen.
1. Selecteer de gewenste domainproperty
2. Verander de proportie “IsElementName” naar true
3. Ga naar de DSL explorer
4. Zoek in de categorie “XML Serialization Behavior” naar het bijhorende element
5. In element data selecteer je dan de element data waar je “IsElementName” verandert
hebt.
6. Verander “IsMonikerKey” naar true
Vanaf nu zal de domainproperty gelden als ID in je model. IsElementName moet niet
op true staan maar is wel belangrijk wanneer je meerdere items aanmaakt. Want dit
moet namelijk identiek zijn anders kan je problemen krijgen wanneer je het voor de
tweede keer wilt openen.
5.4.5
Decorators toekennen
Eigenschappen kunnen soms iets bepalend zijn voor je diagram. Standaard zal een
bijhorende shape niets tonen van gegevens. Dit kan je oplossen door decorators. Een
decorator kan je op alle soorten shapes toevoegen. Dus ook op connectoren is het
mogelijk om bijhorende tekst te voorzien. Er bestaan twee types: text decorator en
icon decorator.
21
5.4.5.1
Text Decorator
Wanneer je bijvoorbeeld de naam wil weergeven van een class moet je een decorator
aanmaken in de bijhorende shape. Dit doe je steeds door via rechtermuisknop op add
text decorator. Je bepaalt dan de naam van de decorator en waar dat de decorator
moet komen op de plaats.
Een text decorator moet ook nog gelinkt worden aan een eigenschap. Dit doe je niet in
de shape zelf maar in de link tussen de shape en het element.
1. Selecteer de link
2. Ga naar het venster “Dsl Details”
3. Ga naar het tabblad “Decorator maps”
4. Selecteer de decorator
5. Selecteer bij display proportie de gewenste eigenschap
6. Bepaal eventueel een filter (dit is alleen voor enumeraties) wanneer het geldt.
Vanaf nu zal dus de eigenschap te zien zijn op de plaats die je bepaald. Wanneer je
twee decorators op eenzelfde plaats zet, zal hij het op elkaar zetten. Daarom is het
best om eerst na te denken waar je het plaatst. Hij houdt dus geen rekening van: hier
staat al een decorator dus moet ik naar beneden. Je kan wel manueel bepalen waar het
moet komen via de verticaal of horizontal offset. Hiermee kan je echt bepalen waar de
decorator moet komen. Opgelet: dit gaat niet met grote stappen. Wanneer je twee
zaken ondereen wil plaatsen is het voldoende om een vertical offset te nemen van
0.15.
5.4.5.2
Icon Decorator
Hier is eigenlijk niet veel verschil met de text decorator. Het enige verschil is misschien
dat een icon decorator meestal niet af hangt van een eigenschap. Hier kan je gewoon
een icoon plaatsen in het element. Het icoon zal dan in elk element identiek zijn. Het
kan wel dat je het laat afhangen van een eigenschap. Wanneer je bv een icoon wil
tonen als de eigenschap multiplicity op 0..* moet je een filter instellen op de icon
decorator op dezelfde manier als bij een text-decorator.
5.5
Groeperen van elementen
Het is mogelijk om elementen te groeperen. Hierbij moet je een abstract element
aanmaken. Dit doe je door de proportie “inheritance modifier” in te stellen op abstract.
Elk element kan je een base class toe verwijzen. Dit gaat enkel met abstracte
elementen.
Het handige aan gegroepeerde elementen is dat je relaties kunt leggen naar meerdere
elementen door gewoon een relatie te leggen tussen een element en de groep. Een
groep is meestal een groep van gelijkaardige objecten. Het is ook mogelijk één
domainproporty op de groep aan te maken zodat die overal bestaat in de
subelementen.
22
Een gegroepeerd element moet niet per sé verbonden zijn met een element. Het kan
ook gewoon dienen als een verzameling voor bepaalde elementen die dezelfde
eigenschappen hebben. Je kan dus een boomstructuur ontwikkelen zodat groepen van
elkaar overerven. Ook voor decorators kan dit handig zijn. Een decorator kan je dan
maar één keer toewijzen aan een gegroepeerde eigenschap. Let wel op dat je dan ook
een gegroepeerde structuur van shapes voorziet. Je moet dan ongeveer dezelfde
structuur uitbouwen met een abstracte shape.
Relaties kan je ook groeperen. Als je verschillende types van relaties hebt tussen
dezelfde elementen kan je een extra relatie leggen maar een abstracte. Het verschil is
dat je zo eigenschappen kan toekennen aan alle relaties zonder dat je dat meerdere
keren opnieuw moet doen.
5.6
Acties op shapes
Shapes dienen enkel voor het uiterlijk van elementen. Maar het is mogelijk dat het
uiterlijk afhankelijk is van sommige eigenschappen. Daarom kan je zorgen dat wanneer
je de eigenschap aanpast. Dat de lay-out automatisch mee wijzigt.
1. Maak dus de nieuwe class aan
2. Schrijf een functie die alles initialiseert.
protected override void InitializeResources(StyleSet
classStyleSet)
{
base.InitializeResources(classStyleSet);
AssociationConnector.AssociateValueWith(this.Store,
Association.TypeDomainPropertyId);
}
3. Schrijf een algemene functie “onPropertyChanged”, dit is de functie die wordt opgeroepen
wanneer je iets verandert aan een proportie van het element waartoe de shape behoort.
protected override void
OnAssociatedPropertyChanged(PropertyChangedEventArgs e)
{
}
4. Maak een if-methode om de juiste proportie te halen. Je vergelijkt eigenlijk gewoon de
naam tussen “” met de e.propertyName via de equals – methode.
5. Schrijf dan een switch methode die de nieuwe waarde opvangt en cast naar het gewenste
type. Je vergelijkt het dan met mogelijke waardes per case.
6. Verander het object door this.(item) = .....
23
5.7
Rules en validatie
Niet alles is toegelaten, daarom moet je soms via code alles controleren. Om een
voorbeeld te nemen: Overerving kan niet in beide richtingen gebeuren, daarom moet je
ervoor zorgen wanneer je een nieuwe overerving tekent, dat er wordt gecontroleerd of
er al één bestaat tussen de twee classes. Dit geldt ook voor overerving van zichzelf, dit
wordt niet toegelaten. Daarom moet je dus een regel schrijven dat dit verbied.
Aanmaken regel:
[RuleOn(typeof(Generalization), FireTime = TimeToFire.TopLevelCommit,
InitiallyDisabled = true)]
internal sealed class CyclicInheritanceAddRule : AddRule
{
public override void ElementAdded(ElementAddedEventArgs e)
{
string message = string.Empty;
Generalization g = e.ModelElement as Generalization;
if (g != null)
{
if
(!CyclicInheritanceAddRule.TestValidInheritance(g.Subclass,
g.Superclass, ref message))
{
throw new InvalidOperationException(message);
}
}
base.ElementAdded(e);
}
Testmethode:
internal static bool TestValidInheritance(ModelClass sourceClass,
ModelClass targetClass, ref string errorMessage)
{
if (sourceClass != null && targetClass != null)
{
if (object.Equals(sourceClass, targetClass))
{
errorMessage = "Reflexive inheritance detected.";
return false;
}
ModelClass current = targetClass.Superclass;
// Loop until we detect an exisiting loop or the root
of the hierarchy.
while (current != null && current != targetClass)
{
if (object.Equals(current, sourceClass))
{
errorMessage = "Inheritance loop detected.";
return false;
}
current = current.Superclass;
}
}
return true;
}
24
5.8
Custom Editor instellen
Omdat je niet altijd voor alles een vaste enumerator kan je een eigen editor schrijven.
Dit zorgt ervoor dat je bijvoorbeeld een listbox kan maken met alle namen van de
aanwezige classes. Dit kan dus handig zijn als je informatie wil bijhouden rond
bepaalde elementen zonder dat er noodzakelijk een link ligt.
Wanneer je zoals bij een attribuut van de class wil dat je een eigen lijst hebt met types
dan kan je dit hier ook bepalen. Meestal zal dit een listbox zijn. Het voordeel is dan dat
je ook nieuwe waarden kan ingeven die niet in de listbox staan. Bij standaard
enumeraties heb je enkel de keuze uit de mogelijkheden van de enumeratie. Hierbij is
het mogelijk dat je met nieuwe elementen komt zonder dat je die moet gaan toevoegen
in de listbox.
Voorbeeld lijst met types:
1. Maak een nieuwe class aan
2. Instellen van using references
using
using
using
using
using
using
using
using
using
using
using
System;
System.Collections;
System.ComponentModel;
System.ComponentModel.Design;
System.Diagnostics;
System.Drawing;
System.Drawing.Drawing2D;
System.Drawing.Design;
System.Windows.Forms;
System.Windows.Forms.Design;
Microsoft.VisualStudio.Modeling.Design;
3. Overerven van base UITypeEditor
4. StandaardCode toevoegen (voor listbox toch)
private IWindowsFormsEditorService _wfes;
public
override
UITypeEditorEditStyle
GetEditStyle(ITypeDescriptorContext context)
{
if (context == null)
{
return base.GetEditStyle(context);
}
return UITypeEditorEditStyle.DropDown;
}
protected void List_Click(object pSender, EventArgs pArgs)
{
if (_wfes != null)
{
_wfes.CloseDropDown();
}
}
private DialogResult ShowForm(IServiceProvider provider, Form form)
{
IUIService service = (IUIService)provider.GetService(typeof(IUIService));
if (service != null)
{
return service.ShowDialog(form);
25
}
return form.ShowDialog();
}
5. Main Methode toevoegen
public override object EditValue(
ITypeDescriptorContext context,
IServiceProvider provider,
object value)
{
if
((context
==
null)
||
(provider
==
null)
(context.PropertyDescriptor == null))
{
return base.EditValue(context, provider, value);
}
||
_wfes
=
(IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditor
Service));
ListBox listBox = new ListBox();
listBox.Sorted = true;
listBox.Click += new EventHandler(List_Click);
listBox.Items.Add("Boolean");
listBox.Items.Add("Byte");
listBox.Items.Add("Char");
listBox.Items.Add("Currency");
listBox.Items.Add("DateTime");
listBox.Items.Add("Decimal");
listBox.Items.Add("Document");
listBox.Items.Add("Double");
listBox.Items.Add("Email");
listBox.Items.Add("Guid");
listBox.Items.Add("HyperLink");
listBox.Items.Add("Integer");
listBox.Items.Add("Object");
listBox.Items.Add("Password");
listBox.Items.Add("Picture");
listBox.Items.Add("PrimaryKey");
listBox.Items.Add("RichString");
listBox.Items.Add("Single");
listBox.Items.Add("String");
listBox.Items.Add("TimeSpan");
listBox.Items.Add("ForeignKey");
listBox.SelectedItem = value;
_wfes.DropDownControl(listBox);
return listBox.SelectedItem;
}
6. Custom attribute toekennen aan proportie:
System.ComponentModel.EditorAttribute
typeof(QFrame.DSLModel2.PropertyTablePropertyEditor)
typeof(System.Drawing.Design.UITypeEditor)
7. Transform all templates en buid solution
26
6
DSL-MODEL BEKIJKEN
Wanneer je een model hebt ontwikkelt wil je het natuurlijk bekijken. Een model is
eigenlijk een platform waarbij je elementen kunt op slepen. Het model is zo groot als je
maar wenst, er zijn geen echte grenzen. Een model wordt altijd opgestart wanneer je
een DSL-project runt.
Op zich lijkt dit echt op een gewoon project want alles is er aanwezig van een gewone
Visual Studio. Er is een toolbox, solution Explorer, Proporties, … maar het verschil zit
vooral de eigen elementen. Je toolbox is volledig aangepast aan de elementen die jij
hebt toegevoegd. Er is de mogelijkheid om een menuoptie bij te creëren in de
menubalk of een eigen contextmenu als je op je rechtermuisknop klikt.
6.1
Elementen toevoegen
Een element toevoegen kan meestal door het slepen van elementen uit de toolbox. De
editor zal het element ook plaatsen waar dat je het sleept. Het is niet zoals bij het
ontwerpen van DSL dat de elementen automatisch ondereen komen. Je bent hier echt
vrij om te slepen. Je kan zelfs elementen op elkaar plaatsen.
Sommige elementen hangen natuurlijk vast aan een bepaald element. Wanneer je dan
een verkeerde actie doet, zal je een verbodsteken krijgen. Dit betekent dus dat het
element hier niet hoort. Subelementen zijn zo een voorbeeld die je enkel kan
toevoegen aan compartimenten. Wanneer die ontbreken kan je geen subelementen aan
je model toevoegen.
Om connnectoren toe te voegen heb je steeds twee elementen nodig. Een element dat
als bron dient en een element dat als target dient. Dit hoeven wel geen twee
verschillende elementen te zijn, je kan ook een connector aanmaken tussen één
element waarbij de bron en target identiek zijn.
6.2
Overzicht elementen bekijken
27
Er bevindt zich in het dsl-model een apart scherm. Dit dient ervoor om een overzicht te
krijgen van alle elementen. Wanneer je grote schema’s hebt en je kan niet alles direct
terugvinden kan je dat zeker met de Class Diagram Explorer . Dit is eigenlijk een
overzicht uit xml. Hier zijn alle elementen gewoon gerangschikt zonder al die
tekeningen. Wanneer je dus een element zoekt kan je het hier opzoeken en kan je
dezelfde acties doen die je anders op het element kunt doen. Bij kleine schema’s is het
beter om in het diagram te doen dan hier. Relaties kan je hier ook niet leggen dus dat
ben je wel verplicht in het model.
28
7
COMMANDO INSTELLEN DSL-MODEL
De tweede stap eigenlijk om er voor te zorgen dat je DSL-model klaar is voor generatie
van code of voor andere zaken. Anders blijft je model toch op zichzelf en is er buiten de
weergave van modellen geen andere functie.
Standaard zijn er geen commando’s verzien buiten op een compartiment shape. Dus
bijvoorbeeld op een class om attributen toe te voegen. Maar het is mogelijk om dus
hier extra methoden te voorzien. Commando’s kunnen ofwel in het contextmenu als je
op rechtermuisknop klikt of in de menubar zelf.
Je kan ook de menu’s indelen per categorie. Achter een menu-item kan je dan code
toevoegen om bepaalde acties uit te voeren. Voorbeelden rond mogelijke commando’s
zijn om connectoren van stijl te veranderen. Je kan voor elke stijl een menucommando
voorzien.
Een menu commando zit altijd gespreid over drie bestanden:
-
7.1
Commands.vsct
Constants.cs
Commandset.cs
Aanmaken menu commando’s
Alle commando’s worden gedefinieerd en gecatalogiseerd in het bestand:
Commands.vsct. Standaard zit er één bestand in DSLpackage maar die is leeg buiten
de zes basisitems die je zeker nodig hebt in een vsct-bestand.
<Extern href="stdidcmd.h"/>
<Extern href="vsshlids.h"/>
<Extern href="msobtnid.h"/>
<Extern href="virtkeys.h"/>
<Extern href="DSLToolsCmdID.h"/>
<Include href="GeneratedCode\GeneratedVsct.vsct"/>
Dit is een soort van xml-file waarbij je vijf categorieën hebt:
7.1.1
Symbols
Hier maak je eigenlijk het object aan. Elk item moet hier gedistantieerd worden anders
kan je het niet gebruiken in de andere categorieën. Je moet bijna altijd twee items
creëren voor één menucommando. Een commando moet je altijd toekennen aan een
bepaalde groep. Een groep heeft ook altijd een item nodig. Bij veel commando’s kan je
best in groepen verdelen om een beter overzicht. Daarom moet je zelfs de groep nog
eens toekennen aan een groep.
Een symbol bestaat steeds uit een naam en een waarde. Die waarde moet verplicht
uniek zijn anders ga je problemen krijgen later. Je moet ook rekening houden dat je
best de basisitems voor de commands de laagste waarden toekent. Dit enkel om
structuur te houden want die waardes heb je nodig in het bestand constants.cs.
Er is ook een standaard symbol om je collectie in op te slagen. Dit heeft als waarde een
registerwaarde. Dit is nodig omdat de menu-items eigenlijk worden opgeslagen in het
register.
<GuidSymbol
9f30973980ff}" >
name="guidCmdSet"
value="{322191bb-83c0-4781-a974-
29
Er zijn wel enkele uitzonderingen. Standaard bied Visual studio al een uitgebreide set
van Commands. Er zijn meer dan honderden standaardwaarden. Echt een lijst is hier
niet van opgesteld, je vindt ze wel terug als je in de subfolder van de Visual studio SDK
gaat kijken: Visual studio integration/inc. Hier vind je veel .h bestanden, je zoekt hier
de vijf bestanden die bovenaan in het .vsct worden toegevoegd en in die bestanden
vind je al de gebruikte ID’s.
7.1.2
Commandplacements
De naam zegt veel: hier plaats je eigenlijk de commando’s in de juiste groep. Bij elk
commando moet je de correcte IDSymbol naam toekennen aan de ID. Omdat een
commandplacement zelden alleen voorkomt, ken je het toe aan een parent-element
waarbij je dan de juiste IDSymbol invult. Guid is steeds de verbinding tussen alle
elementen.
<Naam> = naam
<parent>= waar de groep toe behoort
<volgorde> = volgorde van de items
<CommandPlacement guid="guidCmdSet" id="<naam>" priority="<volgorde>" >
<Parent guid="guidCmdSet" id="<parent>"/>
</CommandPlacement>
7.1.3
Buttons
Elk item dient als een knop want je moet in staat zijn om er op te klikken. Daarom
moet je hier ook definiëren om bepaalde standaardwaarden toe te kennen. Hier is het
mogelijk om ervoor te zorgen dat de menu standaard is gedisabled of niet zichtbaar is.
Je bepaalt ook de tekst die wordt weergegeven.
<Button guid="guidCmdSet" id="<naam>" priority="<volgorde>" type="Button">
<Parent guid="guidCmdSet" id="<parent>"/>
<CommandFlag>DefaultDisabled</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText><titel></ButtonText>
</Strings>
</Button>
7.1.4
Menu’s
Hierbij maak je menu’s aan. Dit zowel voor contextmenu’s als voor menu’s bovenaan.
Bij menu’s kan je ook werken met gegroepeerde items. Ofwel plaats je dus een groep
in het menu ofwel plaats je gewoon een item in een menu. Elke groep in de
contextmenu werkt dus ook met een menu-item.
<Menu guid="guidCmdSet" id="<Naam>" priority="<volgorde>" type="Context">
<Parent guid="guidCmdSet" id="<parent>"/>
<Strings>
<ButtonText><titel></ButtonText>
</Strings>
</Menu>
30
7.1.5
Groups
Een group is eigenlijk een collectie van menucommands. Hierbij bepaal je dus tot
welke group de group eventueel zelf behoort. Een van de belangrijkste items want
zonder een Group kan je geen menucommando’s toevoegen. Hier instantieer je alleen
maar de groups. In “Menus” en “Button” voeg je items toe aan de groepen.
<Group guid="guidCmdSet" id="<Naam>" priority="<volgorde>">
<Parent guid="guidCmdSet" id="<parent>"/>
</Group>
7.2
Toewijzen constanten
De tweede stap bij het aanmaken van menucommando’s. Elk menucommando kan niet
herkend worden als er geen constante voor gedefinieerd wordt. Een constante is de link
tussen Commands.vsct en Commandoset.cs. Veel lijnen bevat dit bestand niet, per
commando bevat dit één lijn.
De structuur van een commando is als het volgt:
<naam> = elk commando heeft een naam nodig
<id> = deze naam vind je terug in de constants.cs bij generatedCode.
<waarde> = dit is de waarde van het item. Dit vind je terug bij commands.vsct
in de categorie symbols.
public static readonly CommandID <naam> = new CommandID(new Guid(<ID>),
<waarde>);
7.3
Acties toekennen aan Commando
De laatste stap in het maken van een commando. Elk commando heeft een
achterliggende actie. Standaard is die niet aanwezig wanneer je een nieuwe commando
aanmaakt.
Zonder wijzigingen in het commandoset.cs zal je niets zien in het model. Want
commandoset.cs bevat de belangrijkste zaken voor een commando. Hier volgt hoe je
een commando nu echt toevoegt aan je model en hoe je er acties toekent. Alles
gebeurt in de file “commandoset.cs”.
7.3.1
Toevoegen aan model:
1. Override de menuoptie: GetMenuCommands ()
2. Begin onder de baselijn: IList<MenuCommand> commands =
base.GetMenuCommands();
3. Voeg een command toe via commands.Add()
4. Als parameters geef je mee: new
Microsoft.VisualStudio.Modeling.Shell.DynamicStatusMenuCommand(a,b,c)
5. DynamicStatusMenuCommand bevat zelf ook drie parameters.
31
a. Eerst geef je de functie die bepaald wanneer het menu getoond wordt
b. De functie die bepaalt wat het commando moet doen
c. Hier geef je de constante in die behoort tot de menucommando. Elk
constante begint met constants en dan de naam van de constante. Dit
vind je terug in constants.cs.
6. Zo ga je verder voor elk commando
7.3.2
Statusfunctie bepalen:
Statusfunctie is iets belangrijk maar kan voor meerdere commando’s dienen. Dit moet
je maar één keer schrijven als het voor drie commando’s geldt. Hier kan je bijvoorbeeld
controleren of het bestand wel een model is of dat het menucommando enkel geldig is
wanneer je een class selecteert.
1. Schrijf de hoofding
2. Vang het menucommando op: MenuCommand command = sender as
MenuCommand;
3. Schrijf een if-functie om te controleren of het niet null bevat
4. Bepaal welke status het heeft
Voorbeeld uit mijn project:
internal virtual void OnStatusSelect(object sender, EventArgs e)
{
MenuCommand command = sender as MenuCommand;
if (command != null)
{
command.Visible = true;
if
(this.CurrentDocData.Store.ElementDirectory.FindElements<ModelRoot>().Count
0)
{
command.Enabled = true;
}
else
{
command.Enabled = false;
}
}
}
>
Dit zal er dus voor zorgen dat de menucommando’s die deze functie als status
gebruiken enkel zichtbaar zijn als het een model is. Een model bevat altijd een
modelroot.
32
7.3.3
Actie bepalen
Actie is eigenlijk de hoofdfunctie van een commando. Deze code wordt uitgevoerd als je
het commando selecteert. Hier kan je van alles uitvoeren: formulieren tonen, objecten
toevoegen, objecten onzichtbaar maken, ….
1. Schrijf de hoofding
2. Bepaal de acties naar wat je wenst
Voorbeeld uit mijn project:
internal virtual void OnMenuShowClass(object sender, EventArgs e)
{
foreach
(TableShape
table
in
this.CurrentDocData.Store.ElementDirectory.FindElements<TableShape>())
{
table.Hide();
}
foreach
(ClassShape
classe
in
this.CurrentDocData.Store.ElementDirectory.FindElements<ClassShape>())
{
classe.Show();
}
foreach
(ManyToManyAssociationShape
many
in
this.CurrentDocData.Store.ElementDirectory.FindElements<ManyToManyAssociation
Shape>())
{
many.Show();
}
}
Bij dit commando gaat hij al de soorten objecten af. Wanneer het een tabel is zal hij de
tabel onzichtbaar maken. Een class of een manytomanyassociation zal hij laten tonen.
Natuurlijk is hier een gelijkaardige functie op die het omgekeerde doet en een functie
die alles toont.
33
8
GEBRUIK VOOR GENERATIE
Generatie van bestanden is geen standaard voor een DSL-Model. Er zijn wel twee kleine
voorbeelden aanwezig maar dat gaat steeds over één bestand. Maar het is meestal niet
de bedoeling om alles in een bestand te generen. Eigenlijk kan je alles integreren in
DSL door middel van de commando’s. Generatie is een van de belangrijkste doelen
voor een DSL-Model in mijn project.
Genereren gebeurt via T4-templates. Dit is een methode die je kan gebruiken voor alle
soorten bestanden zoals .html, .cs, .vb, .jsp, … wanneer je het bestand beziet zal het
vrij gelijkaardig zijn aan het type bestand dat je wenst. Enkel zal je stukken code in het
bestand zien staan tussen <# #> tekens. Je hebt drie soorten:
-
<# #> wanneer je variabelen wil toekennen of iets in code wil uitvoeren.
<#= #> schrijft iets neer in het bestand. Hiermee kan je variabelen afdrukken in het
bestand
<#+#> is bedoeld om methodes te schrijven. Hier schrijf je alle methodes die je kan
gebruiken in je template.
Het is mogelijk om met If-structuren en lussen te werken zodat je dezelfde code kunt
gebruiken voor een heel collectie. Ook kan je methodes schrijven die je bijkomende
code vergemakkelijken. Eigenlijk is het herkenbaar voor iemand die C# schrijft of een
andere programmeertaal. Alles kan je hiervan gebruiken. Je kan ook Libraries
gebruiken door ze te importeren, zo kan je zelfs eigen gebruikte methodes schrijven
zodat je de templates zoveel mogelijk spaart van extra code.
Templates worden opgeslagen in het model zelf. Je kan dus de templates niet bekijken
wanneer je het model opgestart hebt. Eigenlijk bepaal je het zelf maar voor de
commando’s is het gemakkelijker dat je ze in de resources map bewaard onder
DSLpackage.
Een template omzetten naar code gebeurt niet zomaar. Je hebt een processor nodig.
Dit is een soort van omzetter voor de templates. Standaard wordt er telkens één
aangemaakt wanneer je een nieuw DSL-model opstelt. Maar de processor kan geen
filter aan dus daarom zal je deze processor moeten aanpassen zodat je kunt zorgen dat
de templates enkel gelden voor één element of één categorie uit het model.
8.1
Instellen processor
Wanneer je iets wil aanpassen moet je altijd een extra class maken die dezelfde naam
gebruikt als de bestaande class. Hij zal dan rekening houden met beide classes. Zo kan
je de functies schrijven die dienen om een parameter toe te voegen aan de class
DirectiveProcessor.
1. Aanmaken eigen class
2. Verander hoofding van de class naar : public sealed partial class
<modelnaam>DirectiveProcessor
3. Schrijf de methode voor de extra property. Dit is van het type required omdat
dit een verplicht veld is. Het moet ingevuld worden anders zal het fout lopen.
protected override void InitializeRequiresDictionary(string directiveName,
System.Collections.Generic.IDictionary<string, string> requiresDictionary)
{
34
base.InitializeRequiresDictionary(directiveName, requiresDictionary);
requiresDictionary.Add("name", Guid.Empty.ToString());
}
4. Schrijf eventueel een methode wanneer je wenst als je met twee modellen in
één template wil werken. Bepaald ook de naamgeving van this.(argument).
(optioneel: leeg laten betekend dat je gewoon de standaard gebruikt this.Table)
protected
override
void
InitializeProvidesDictionary(string
directiveName,
System.Collections.Generic.IDictionary<string, string> providesDictionary)
{
base.InitializeProvidesDictionary(directiveName, providesDictionary);
providesDictionary.Add("Table", "Table");
}
5. Als je helemaal wil gebruik maken van “this.<naam>” in je templates moet je
een variabele toevoegen en een proportie. Dit gebeurt in de override methode
GenerateTransformCode
protected override void GenerateTransformCode(string directiveName, StringBuilder
codeBuffer,
System.CodeDom.Compiler.CodeDomProvider
languageProvider,
System.Collections.Generic.IDictionary<string,
string>
requiresArguments,
System.Collections.Generic.IDictionary<string, string> providesArguments)
{
base.GenerateTransformCode(directiveName,
codeBuffer,
languageProvider, requiresArguments, providesArguments);
codeBuffer.AppendLine("private Table _" + providesArguments["Table"] +
";");
codeBuffer.AppendLine("public Table " + providesArguments["Table"] + "{
get { return _" + providesArguments["Table"] + " ; } }");
}
6. Als laatste moet je dan de methode schrijven die enkel de tabel die je wenst
filtert.
protected override void GeneratePostInitializationCode(string directiveName,
System.Text.StringBuilder codeBuffer, System.CodeDom.Compiler.CodeDomProvider
languageProvider,
System.Collections.Generic.IDictionary<string,
string>
requiresArguments,
System.Collections.Generic.IDictionary<string,
string>
providesArguments)
{
base.GeneratePostInitializationCode(directiveName,
codeBuffer,
languageProvider, requiresArguments, providesArguments);
// Initialize the ModelClass property
codeBuffer.AppendLine(@"foreach
(Table
eachTable
this.Store.ElementDirectory.FindElements<Table>())");
codeBuffer.AppendLine(@"{");
codeBuffer.AppendLine(@"
(StringComparer.Ordinal.Compare(eachTable.Name,
"""
requiresArguments["name"] + @""") == 0)");
codeBuffer.AppendLine(@" {");
codeBuffer.AppendLine(@"
this._" + providesArguments["Table"] + "
eachTable;");
codeBuffer.AppendLine(@" break;");
codeBuffer.AppendLine(@" }");
in
if
+
=
35
codeBuffer.AppendLine(@"}");
}
8.2
Opstellen Templates
Templates bestaan meestal uit twee delen. Eventueel een derde deel kan als je extra
methodes nodig hebt. Een template heeft altijd een hoofding waar je alles toevoegt van
libraries en ook bepaal je welke processor je nodig hebt om de templates te laten
omzetten naar code. Een ander deel is de code zelf. Dit deel bevat meestal een hoop
tekst met delen code. Het derde deel kan als je met uitgebreide functies zit om
informatie op te halen.
8.3
Aanmaken Templates
Er zijn twee manieren: ofwel kies je ervoor om met losse templates te werken of je kan
zorgen dat je aan de templates een constante toewijst. Je hebt sowieso een soort van
collectie nodig die alle templates bijhoudt. Daarom kan je een Dictionary aanmaken in
code waarbij de locatie en de naam bijgehouden wordt van de templates. Zo kan je
snel de juiste template achterhalen.
8.3.1
Losse templates
Je kan ervoor kiezen om met losse locaties te werken.
templates nodig hebt is dit een goede keuze. Vooral
templates kan dit handig zijn. Dan moet je de locatie wel
gaat zo sneller dan er steeds constante waarde aan vast te
Wanneer je telkens andere
bij het testen van nieuwe
telkens aanpassen maar dit
hangen.
In je templatedictionary plaats je de locatie van de templates. Elk template moet je
zeker een naam geven om later de juiste template terug te kunnen vinden. Wanneer je
werkt met één folder waar alle templates zich bevinden, werk je dus best met een
variabele waar je de locatie invult. Zo moet je dat niet op twintig plaatsen aanpassen.
Voorbeeld van een templatedictionary:
Dictionary templates = new Dictionary()
templates.Add(new KeyValuePair<”Action_cs”,”c://”>());
templates.Add(new KeyValuePair<”Action_vb”,”c://”>());
templates.Add(new KeyValuePair<”BL_vb”,”c://”>());
8.3.2
Templates via constante waarden
Er is een mogelijkheid om de templates in een bestand te steken en er een constante
aan toe te kennen. Dit heeft het voordeel dat je niet heel de locatie moet overtypen om
de template te bemachtigen. Het is veel gebruiksvriendelijker in je systeem. Zo maak
je minder kans op fouten in de locatie. Wanneer je lange locaties hebt, kan het zijn dat
je typefouten maakt en zo krijg je natuurlijk last dat hij een template niet vindt.
1. Open het bestand VSPackage.resx
2. Ga naar de categorie Files
3. Voeg de templates toe
36
Nu kan je de templates makkelijk bereiken door VSPackage.action bijvoorbeeld. Dit zal
dan de achterliggende file ophalen.
8.4
Template schrijven
Een template schrijven begint altijd met een hoofding. De hoofding bevat de
belangrijke lijnen voor de omzetting. Dit bevat voornamelijk het type processor. In mijn
project was dat een aangepaste processor met twee parameters: één die de naam van
het bestand bevatte en een die de naam van de tabel bevatte.
Voorbeeld: <#@ DSLModel2 processor=”DSLModel2DirectiveProcessor”
requires=”filename=’<@@filename@@>’,tablename=’<@@tablename@@>’” #>
Het speciale is dat de beide parameters toegekend zijn met een soort van variabele.
Deze variabele zal door de methode worden omgezet naar de juiste gegevens.
Het is mogelijk om namespaces te declareren zodat je in de code niet de volledige
naam van types moet ingeven. Dit doe je door de namespace te importeren:
Voorbeeld: <#@ import namespace=”System.Collections.Generic” #>
Wanneer je een dll wil gebruiken in je templates kan je die dan toekennen door een
assembly toe te voegen:
Voorbeeld: <#@ assembly name=”System.Drawing.dll” #>
Meestal kan je automatisch de extensie bepalen en de encoding van het bestand. Dit is
enkel noodzakelijk wanneer je de template gebruikt voor een heel model. Wanneer je
met de methode werkt zal je de extensie toekennen in de methode en niet in de
template.
Voorbeeld: <#@ output extension=”.cs” encoding=”utf-8” #>
Templates kan je ook combineren door een template te includen. Dit is misschien
handig las je een template in meerdere templates kan gebruiken. Zo vermijd je
herhaling:
Voorbeeld: <# include file=”FileToInclude.tt” #>
8.5
Methode schrijven
Er is natuurlijk een methode nodig die zorgt dat je de template kan gebruiken voor
meerdere files te genereren. In feite gaat hij de parameters vervangen door de juiste
gegevens. Dus zal hij steeds de tabelnaam en de bestandsnaam bepalen door
<@@filename@@> en <@@tablename@@> te vervangen met de correcte waarden.
Hij overloopt alle tabellen. Bij elke tabel zal hij de twee variabelen vervangen via een
replacefunctie. Daarna zal hij door middel van de aanwezige templateservice de
template omzetten naar code. Dit resultaat zal dan via een streamwriter worden
weggeschreven naar het bestand met de juiste naam op de gekozen locatie.
Hier kan je natuurlijk zorgen dat je met bepaalde if-structuren of extra for-lussen
ervoor zorgen dat het resultaat iets verschilt maar dit hangt er vanaf hoe uitgebreid dat
je het wenst.
37
De eenvoudigste code ziet er als volgt uit:
private void GenerateTemplate(String extra, String baseTemplate, string
genCodeDir, Table eachTable)
{
// Replace the marker text in the template with the name of the class to
generate and the model file to load
string specificTemplate = baseTemplate.Replace("@@CLASSNAME@@",
eachTable.Name);
specificTemplate = specificTemplate.Replace("@@MODELFILE@@",
_genSettings.Dte.ActiveDocument.FullName);
string output = _genSettings.TemplatingService.ProcessTemplate("",
specificTemplate, null, null);
string filePath = Path.Combine(genCodeDir, eachTable.Name + extra + "." +
_genSettings.Extension);
if ((eachTable.ManyToManyAssociation!=null) &&
(filePath.Contains("Collection"))){
}else{
if (! File.Exists(filePath))
{
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.Write(output);
writer.Flush();
}
}
else
{
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.Write(output);
writer.Flush();
}
}
}
try
{
_genSettings.Project.ProjectItems.AddFromFile(filePath);
}
catch
{
}
}
38
8.6
Extra functionaliteiten schrijven
Er bestaat natuurlijk de mogelijkheid om er voor te zorgen dat de generatie zo optimaal
mogelijk gebeurd. Je wilt niet altijd aan de standaardeisen voldoen. Je kan bijvoorbeeld
voorzien dat je kunt zorgen dat je elk element kan laten bepalen of het standaard
wordt mee gegeneerd. Wanneer je dan genereert moet je wel een if-functie aanmaken
in je generatie methode. Die controleert dan de aangemaakte proportie van de tabel of
het true of false is. Wanneer het false is, zal hij de tabel overslagen.
Je kan er ook voor kiezen om het resultaat naar een andere locatie te sturen dan naar
de standaardlocatie. Dit heb ik opgelost door een commando die een
folderbrowserdialog toont. Wanneer je dan een locatie selecteert zal dit worden
bijgehouden in een algemene proportie. Dit kan je ook doen met bijvoorbeeld het path
van de templates. Wanneer je templates wil gebruiken die niet op de standaardlocatie
staan. Dit kan zijn als je lokaal wil testen of je templates in orde zijn voor generatie.
Een derde extra functie is dat je zelf de templates kunt selecteren. Wanneer je
bijvoorbeeld maar één aangepaste template hebt, kan je de template selecteren via
een formulier. In het formulier wijs je een categorie aan de template toe en geef je
mee voor welke taal deze template dient. De gegevens worden dan bijgehouden in een
collectie. Omdat collecties nog niet volledig worden ondersteund, zal hij de gegevens
niet bijhouden wanneer je afsluit.
39
9
EXPORTEER DSL-MODEL
Een DSL-model exporteren kan omdat het eigenlijk een verzameling is van objecten. Je
kan gegevens ophalen uit de objecten en ze dan omzetten naar andere soorten
elementen. Je hebt enkel een project nodig die dit voor je regelt. Elk element wordt
ingelezen en omgezet naar het nieuwe element.
Het enige moeilijke is eigenlijk de verzameling. Alle elementen zitten in een bepaalde
store. In mijn project heb ik de store in een proportie gestoken van de export class
zodat ik makkelijk de store kon gebruiken in de exportfunctie. Hij leest nadien alle
elementen in en plaats die dan in de overeenkomende elementen. In de
exportmethode kan je dan bepalen welke elementen er moeten worden geëxporteerd.
9.1
Gebruik maken store
Een store is een verzameling van alle aanwezige elementen. Dit wil niet zeggen alle
zichtbare elementen. Het kan zijn dat je elementen toegekend hebt aan een store maar
niet toegekend hebt aan een object. Dan loop je later het gevaar dat je met foute
gegevens zit in een geëxporteerde resultaat.
Om u een overzicht te geven wat een store eigenlijk is:
U ziet hier eigenlijk gewoon een soort van boekenkast. Alle elementen staan hier in een
bepaalde volgorde in. Ik heb ze gerangschikt via afhankelijkheid: groep 2 behoort tot
groep 1 en groep3 behoort tot groep 2.
9.2
Schrijven basisclass
Je kan best met een basis class werken. Dit is een class die je makkelijk kan
hergebruiken. Wanneer er verschillende mogelijkheden zijn om te exporteren, kan je
deze class makkelijk gebruiken bij elke mogelijkheid. Dit werkt natuurlijk enkel voor
tussen dezelfde type elementen. Wanneer je wenst te exporteren naar een ander soort
van objecten dan moet je een nieuwe basis class schrijven die gebaseerd is op het
andere model.
Een basis class bevat voor elk mogelijk object een functie en wanneer er verschillende
importmogelijkheden zijn kunnen er meerdere functies voor hetzelfde object zijn. Deze
functies kan je dan gebruiken in andere classes.
40
9.3
Schrijven export class
Een export class zorgt meestal voor de invoer en voor de structuur. Dit erft alles over
van de basis class. Je overloopt hier alle elementen van het model dat je wil overlopen.
Op basis van je noden bepaal je welke functies je nodig hebt en hoe dat je ze gebruikt.
Wanneer je bijvoorbeeld twee opties hebt om te exporteren kan je dus een
verschillende export classes schrijven die wel gebruik maken van dezelfde basis class.
De code verschilt wel maar de gebruikte functies blijven hetzelfde. Dit is voor
hergebruik een groot voordeel. Je moet niet opnieuw elke functie gaan herschrijven als
ze al bestaat. Het voordeel is ook als je de basis class gebruikt voor andere projecten
dat je niet dezelfde code op tien plaatsen moet wijzigen.
41
10
IMPORTEER NAAR DSL-MODEL
Importeren gebeurt op dezelfde manier als exporteren. Het is een gebruik van
objecten. Het enige verschil is dat ik hier twee mogelijkheden heb uitgewerkt. Hier heb
ik een project geschreven die een DSL-model aanmaakt. Maar dit gebeurt nu niet in de
DSL-editor. De basiscode blijft wel hetzelfde, maar de aanroepcode verschilt.
Het importeren is belangrijk voor oudere modellen of andere soorten modellen om te
zetten naar DSL. Omdat het logisch is dat de bestaande generator voor een deel wordt
hergebruikt, dat je hier ook een optie biedt om meteen te exporteren naar DSL. Er
wordt dan een nieuw bestand aangemaakt op een gekozen locatie. Dit bestand heeft de
extensie van het DSL-model en hier wordt de store aan toegevoegd.
10.1
Importeer vanuit DSL
Het importeren vanuit DSL vereist niet echt moeilijke code. Je zorgt ervoor dat de store
van het bestaande bestand wordt doorgegeven aan de import-project. Zo wordt de
store opgevuld met de correcte gegevens. In een formulier kies je dan het model dat je
wenst te importeren. Dit model zal worden gebruikt voor importatie. De importfunctie
zal alle elementen overlopen en toevoegen. Natuurlijk zal je een foutmelding krijgen als
het model niet voldoet aan de eisen. Je kan enkel modellen importeren van hetzelfde
type.
In principe is importeren hetzelfde als exporteren maar de omgekeerde weg. Het
speciale is wel als je iets toevoegt moet je met twee zaken steeds rekening houden. Bij
het aanmaken van een object, ken je het automatisch toe aan een store. Nadien vul je
het nieuwe object gewoon op met de gegevens. Het object zit dan al wel in de store
maar is niet toegekend aan de root bijvoorbeeld. Je gebruikt dan de ADD-functie van
een collectie om dit object toe te kennen aan de root.
Wanneer je dus tijdelijk een object nodig hebt, kan je beter zorgen dat je zorgt dat het
wordt verwijderd op het einde. Dit voorkomt foute gegevens in de store.
Voorbeeld:
Protected virtual ImportClass(string name, Table table)
{
ModelClass newClass = new ModelClass(store);
newClass.Name=name
newClass.Table=table;
Root.types.Add(newClass);
}
42
10.2
Importeren buiten DSL
Je zou denken dat als je kunt importeren in DSL dat je dit ook automatisch kan buiten
DSL. Niets is minder waar, wanneer je in DSL importeert gebruik je automatisch de
correcte store. Maar als je niet meteen beschikt over een store moet je een nieuwe
aanmaken. Dit is niet het grote probleem, het is vooral het toekennen van de store aan
een bestand. De store opvullen gebeurt op een identieke manier als in DSL eigenlijk
automatisch doet wanneer je een DSL-model aanmaakt.
System.Runtime.Serialization.SerializationBinder binder = new
DSLModelBinder();
NewModel = model;
Store store = new Store();
Type[] modelTypes = new Type[] {
typeof(Microsoft.VisualStudio.Modeling.Diagrams.CoreDesignSurfaceDomain
Model),
typeof(QFrame.DSLModel2.DSLModel2DomainModel)};
store.LoadDomainModels(modelTypes);
//CoreDesignSurfaceDomainModel m1 = new
CoreDesignSurfaceDomainModel(store);
//DSLModel2DomainModel newModel = new
DSLModel2DomainModel(store);
string fileName = name+".leafDSL";
string filePath = Path.Combine(location, fileName);
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.Flush();
}
using (Transaction t =
store.TransactionManager.BeginTransaction("Creating new diagram"))
{
DSLModel2SerializationHelper.Instance.LoadModel(store,
filePath, null, null);
StoreModel = store;
Root = new ModelRoot(StoreModel);
Root.AuditFields = false;
Root.Name = NewModel.Name;
ImportClasses();
ImportTables();
ImportRelations();
SetGeneralizations();
SetTableParent();
SetMultiplicity();
t.Commit();
}
// Save the model
SerializationResult result = new SerializationResult();
DSLModel2SerializationHelper.Instance.SaveModel(result, Root,
@filePath);
43
10.3
Positioneren Shapes
Omdat je toch een beetje structuur wenst in de objecten wanneer je iets imponeert,
kan je ervoor kiezen om een bijkomende functie te schrijven die alle objecten overloopt
en ze op een bepaalde logica rangschikt. Je kan er voor kiezen om alle gelijkaardige
objecten onder elkaar te plaatsen. Dit zorgt voor een duidelijkere structuur dan
wanneer alle objecten door elkaar staan.
Een echt diagram ga je moeilijk kunnen maken omdat een element geen vaste locatie
heeft in een diagram. Maar eigenlijk heb je het niet echt in de hand, ook al schrijf je
een degelijke functie, je zou bijna extra plaats moeten houden om zaken te scheiden.
Hij doet het niet echt perfect, maar iets is beter dan niets zeggen ze vaak.
Voorbeeldcode hoe je een shape van locatie verandert:
Double x = diagram.AbsoluteBounds.Left;
Double y = diagram.AbsoluteBounds.Top;
int aantal = 0;
foreach (ClassShape shape in
this.CurrentDocData.Store.ElementDirectory.FindElements<ClassShape>())
{
shape.AbsoluteBounds = new RectangleD(x, y,
shape.Bounds.Width,shape.Bounds.Height);
y += shape.Bounds.Height;
aantal++;
if (aantal == 10)
{
x+=shape.Bounds.Width;
y = 0;
}
}
BESLUIT
LITERATUURLIJST
44
BIJLAGEN
1. Gegevens behandelen
Hij/zij kan gegevens verzamelen, opslaan en ter beschikking stellen, zodanig dat deze
op een correcte en gebruiksvriendelijke manier kunnen worden opgevraagd.
Dit gaat over verschillende projecten. Elk project heeft wel oplossingen nodig en niet
alle oplossingen zijn meteen aanwezig. Daarom is het steeds vereist om een bepaalde
zaken op te zoeken op internet. Internet heeft niet altijd het juiste resultaat. Daarom
moest ik altijd met gerichte zoektermen leren werken om tot de juiste oplossingen te
vinden. Ook was het handig om bepaalde resultaten te bewaren om herhaling te
vermijden.
In verband met het omgaan van gegevens voor een project kan ik als voorbeeld het
asp-project nemen. Dit project had niet een kant en klare uitleg. Hier moest je over
nadenken hoe je alles ging uitwerken door alle gegevens te verzamelen en die
gegevens dan te verwerken in een paar modellen.
Gegevens uit grote gehelen halen was vooral nodig uit alle informatie uit het internet.
Wanneer ik iets op zocht moest je steeds rekening houden met de echtheid van de
gegevens. Daarom maak ik altijd een samenvatting met allemaal kleine puntjes zodat
ik het begrijp zonder alle tekst te herlezen.
Gegevens moeten meestal via een login ter beschikking komen. In het asp-project
moet alles wat aangepast kan worden of belangrijke informatie kon bevatten beveiligd
worden met de juiste login. Elke login had zijn eigen rechten.
45
2. Analyseren
Hij/zij kan, zelfstandig of onder begeleiding en eventueel in teamverband, de
informatiebehoeften van een organisatie gestructureerd en overzichtelijk weergeven.
Voor analyse was er eigenlijk een vak dat zich leidde naar juiste analyses. Elk project
dat ik maakte had een analyse nodig. In begin is dat maar een kleine oppervlakkige
analyse maar in de loop van mijn opleiding werd die analyse uitgebreider en gebruikte
ik modellen die speciaal bedoelt waren om project vereisten te analyseren.
Het business project in het derde jaar was eigenlijk de grootste analyse. Dit project was
eigenlijk een analyse van 13 weken om een file management systeem te ontwikkelen.
Alle informatie om dit project te voltooien moest worden omgezet in een deftig plan van
aanpak. Dit is een methode waar vele soorten informatie duidelijk wordt weergegeven
zodat de klant gemakkelijk kan volgen. Dit zorgt er ook ineens voor dat ik bepaalde
gegevens duidelijk en gestructureerd kon weergeven in een document.
Dit project had verschillende mogelijkheden voor een oplossing. Daarom was het ook
nodig om elke optie duidelijk onder de loep komen en een vergelijkende studie te
verrichten.
46
3. Oplossingen uitwerken
Hij/zij kan voor de organisatie nieuwe IT-oplossingen uitwerken, zodanig dat de
opdrachtgever tevreden blijft.
Hier kan ik mijn stageopdracht goed gebruiken. Dit is een behoorlijk grote opdracht die
toch de nodige structuur vereist. Voorwaarden waren bijvoorbeeld dat alles goed kan
worden hergebruikt wanneer er veranderingen komen bij één van de stappen. Ook de
code moet zo duidelijk mogelijk zijn. Ik heb ook rekening gehouden met de aanwezige
structuur. Ik heb bekeken hoe het programmeren ginder werkte en heb uit de code
geleerd om mijn code beter te structureren. Ook heb ik met allerlei trukken geleerd om
code zo proper en om wijzigingen te doen in projecten.
Mijn project was ook een materie waar weinig informatie over beschikbaar is daarom
was het vaak lang zoeken om tot een goede oplossing te komen. Dit heb ik zelfstandig
allemaal moeten opzoeken en implementeren. Om dit allemaal duidelijk te houden voor
andere heb ik alles wat niet echt duidelijk was om toe te passen gedocumenteerd in
een handleiding. Er is ook voor de technische mensen een technical documentation
opgesteld, deze is bedoeld voor aanpassingen aan de code.
Ik heb mijn project vaak getest door alle mogelijke manieren eens uit te testen. Ik had
een checklist gemaakt waar alle opties aanwezig waren. Ik ben alles één voor één
afgegaan om echt geen fouten te voorkomen. Dankzij de testen van mijn
stagebegeleider kon ik ook weten hoe het systeem werkt op andere computers.
47
4. Oplossingen beheren
Hij/zij kan op een adequate wijze IT-oplossingen configureren, beveiligen en
aanpassen, zodanig dat ze blijven beantwoorden aan de veranderende behoeften van
de organisatie.
48
5. Projectmatig werken
Hij/zij is in staat om een opdracht op een projectmatige wijze aan te pakken, zodanig
dat de planningen gerespecteerd worden.
49
6. Communiceren
Hij/zij kan mondeling en schriftelijk communiceren met alle betrokkenen, zodanig dat
hij/zij zijn/haar gesprekspartners correct begrijpt en zijn/haar boodschappen helder
overkomen.
50
7. Eigen gedrag aanpassen
Hij/zij is in staat om over het eigen gedrag te reflecteren en op basis daarvan het aan
te passen zodanig dat hij/zij in wisselende omstandigheden optimaal kan functioneren.
51
8. Kwalitatief handelen
Hij/zij streeft naar kwaliteitsvolle taakuitvoering zodanig dat het resultaat voldoet aan
de eisen van een steeds wisselende economische en maatschappelijke omgeving.
Download