Zoek

Uitgebreid zoeken Artikelen per auteur

  

De kracht van Object Oriëntatie op een relationele database

In dit artikel een praktisch voorbeeld van de toepassing van objectgeoriënteerde syntax van Visual Objects (VO). We gaan in op het integreren van eigen classes in de gegenereerde code. Een voorbeeld hiervan is dat we, gebruik makend van traditionele DBF tabellen en RDD (Replaceble Database Driver) technologie uit Clipper, toch gemakkelijk en generiek referentiële integriteit kunnen waarborgen. Alle voorbeelden zijn toe te passen in zowel VO 1.0 als 2.0. Dit artikel is vooral bedoeld voor Clipper programmeurs die de overstap naar VO overwegen of gaan maken en VO programmeurs die verder willen gaan dan het benutten van de standaard geboden functionaliteit.

 

Tot het moment dat objectgeoriënteerde databases in de praktijk meer toegepast worden, zullen we nog vele applicaties ontwikkelen die via objectgeoriënteerde talen relationele databases benaderen. Met deze benadering zijn ook nu al duidelijke voordelen te behalen. Dan bedoel ik voordelen bovenop de voordelen die objectoriëntatie normaal gesproken al biedt, zoals robuustheid, herbruikbaarheid en goede onderhoudbaarheid.

 

Visual Objects Architectuur

 

We hoeven in VO niet van de grond af aan te beginnen. De hele benadering van tabellen via werkgebieden die we kennen uit de xBase wereld, is reeds ingebouwd in de meegeleverde class library. Daarnaast is ervoor gezorgd dat de benadering van SQL databases op vrijwel identieke wijze kan plaatsvinden. Zowel de class voor benadering van SQL tabellen (SqlTable) als die voor benadering van DBF files (Dbserver) erven namelijk van dezelfde base class (DataServer) en hebben zeer veel overeenkomstige methoden en eigenschappen. Bovendien gebruikt de class waarop de data entry schermen gebaseerd zijn, een DataServer-instance voor de benadering van de data. Op deze manier is het dus kinderspel geworden van databron te wisselen. Sterker nog: omdat de SQL-classes eigenlijk ODBC gebruiken kunnen zelfs andere ODBC-bronnen gebruikt worden zoals TXT files of Excel sheets. Uiteraard biedt ook het product VO2Ado aantrekkelijke mogelijkheden op dit vlak.

Naast dit soort overduidelijke voordelen is het op deze manier voor de traditionele Clipper programmeur een ideaal groeipad naar een SQL omgeving. Om daar nog meer in tegemoet te komen zorgt CA (Computer Associates) niet alleen voor veel ODBC-drivers bij VO, maar wordt bij VO ook een single-user SQL-Server geleverd. Bij 1.0 was dat de Watcom-engine, bij 2.0 wordt de ‘eigen’ Open Ingres Desktop database ingesloten.

 

Op zich klinkt dit goed, maar er is natuurlijk nog wel wat werk te verzetten. Zo is (CA) niet zover gegaan als mogelijk is met bijvoorbeeld de Dbserver class. Zij gaan ervan uit dat derde partijen dit gat zullen invullen, en in zekere zin is dat reeds het geval.

CA heeft ervoor gezorgd dat de SqlTable-class zich gedraagt als een record georiënteerd mechanisme, en met een gebufferde Dbserver wordt het mogelijk commit en rollback te implementeren op DBF files. Dit laatste is een van de zaken die CA nog niet voor ons geregeld heeft, maar die wel te vinden is in diverse voorbeelden die op conferenties zijn gepresenteerd. Veel zijn te downloaden via www.cavo.com.

 

SQL versus DBF

 

Bij gebruik van een SQL omgeving kunnen regels als ‘alle offerte-regels moeten worden verwijderd bij verwijdering van de offerte’ of ‘een klant-record mag niet worden verwijderd als er nog opstaande posten voorkomen voor die klant’, worden opgenomen als integriteitregel op de database. Zo worden deze regels geforceerd, hoe je de database ook benadert. In een omgeving die gebruik maakt van DBF files moet je dit soort regels in elke applicatie zelf coderen. Met behulp van de OO benadering in VO is dit niet langer noodzakelijk. De enige afspraak die nodig is, is dat de tabellen altijd via de geschreven Dbserver class, of een afstammeling daarvan, worden benaderd. Deze classes kunnen worden opgenomen in een library, zodat meerdere applicaties daar gezamenlijk gebruik van kunnen maken. Neveneffect hiervan is dat de regels, indien ze worden aangepast, automatisch beschikbaar zijn voor alle applicaties die er gebruik van maken.

 

De praktijk

 

Na deze theoretische inleiding nu de praktische invulling ervan. Als eerste gaan we ervoor zorgen dat er geen weeskinderen meer kunnen ontstaan na verwijderen van een ouder-record. We gebruiken de eerder genoemde Offerte/Offerteregels combinatie als voorbeeld.

Als via de Dbserver-editor een tabel-class wordt gegenereerd, erft de gegenereerde class van de VO Dbserver-class. Deze class heeft een delete method waarmee het actuele record kan worden verwijderd. Dit is dus de eerste kans om in te grijpen. Het is vrij eenvoudig om een delete method te schrijven die ook alle offerteregels verwijdert. In het codevoorbeeld ga ik ervan uit, dat de offerte-class dbsOff heet en de offerteregel-class dbsOffRgl (dbs staat voor Dbserver, net als frm als prefix voor een Form oftewel window kan dienen en mnu als prefix voor een gegenereerd menu).

 

De oplettende lezer zal opmerken, dat in deze oplossing steeds het offerteregel bestand opnieuw wordt geopend. In de praktijk zult u wellicht in een subclass van dbsOff een dbsOffRgl-object opnemen en openen in de init-method (niet vergeten dit object dan ook weer te sluiten in de close-method van dbsOff!).

Voor de volledigheid heb ik hierna de source van deze oplossing opgenomen. Ik ben ervan uitgegaan dat we de gegenereerde code voorzien van een underscore als eerste karakter van de naam. Hierdoor is er goed onderscheid te maken tussen door VO gegenereerde en handgeschreven code.

 

CLASS dbsOff INHERIT _dbsOff

  PROTECT oOffRgl AS dbsOffRgl

 

METHOD Init(cDBF, lShare, lRO, xRdd) CLASS dbsOff

  Super:Init(cDBF, lShare, lRO, xRdd)

  Self:oOffRgl := dbsOffRgl{}

  Self:SetSelectiveRelation(Self:oOffRgl, #OffNr )

RETURN Self

 

METHOD Close() CLASS dbsOff

  Self:oOffRgl:Close()

RETURN Super:Close()

 

Hoewel dit al een werkbare oplossing levert, kunnen we nog een stapje verder gaan door dit op een generieke wijze op te lossen. We missen dan eigenlijk een method AddChild bij de Dbserver-class, en de afhandeling in de Dbserver delete method. VO biedt echter wel een mogelijkheid deze functionaliteit zelf aan te brengen. Een gegenereerde Dbserver-class hoeft namelijk niet van Dbserver te erven; een property in de Dbserver-editor kan worden gebruikt om te erven van een eigen class die dan op zijn beurt natuurlijk weer erft van Dbserver, zodat de wel aanwezige functionaliteit gewoon kan worden benut. Daar was het namelijk allemaal om te doen in objectoriëntatie. De bedoelde property heet ‘Inherit From Class’ en is beschikbaar in vrijwel iedere visuele editor in VO, voor vrijwel alle objecten.

 

De generieke code voor de DbChildServer class zal er ongeveer zo uit kunnen zien:

 

CLASS DbChildServer INHERIT DbServer

  PROTECT aChildren := {} AS ARRAY

 

ACCESS NrOfChildren CLASS DbChildServer

RETURN ALEN(Self:aChildren)

 

METHOD AddChild( oChild, sKey ) CLASS DbChildServer

  AADD( aChildren, oChild )

  Self:SetSelectiveRelation( oChild, sKey )

RETURN Self

 

METHOD Delete() CLASS DbChildServer

LOCAL nI AS WORD

// Return-waarde

LOCAL lRetval := True AS LOGIC        

 

FOR nI := 1 TO Self:NrOfChildren

  IF .not. Self:aChildren[nI]:DeleteAll()

    lRetVal := False

    EXIT

  ENDIF

NEXT

IF lRetVal // Alle kinderen gelukt

  lRetVal := SUPER:Delete()

ENDIF

RETURN lRetVal

 

METHOD Close() CLASS DbChildServer

ASEND( Self:aChildren, #Close )

RETURN Super:Close()

 

Hieronder volgt de code om deze functionaliteit in een applicatie toe te passen, b.v. in samenwerking met een Datawindow:

 

METHOD OpenOfferteWindow CLASS StandardShellWindow

LOCAL oWin AS OfferteWin

LOCAL oOfferteServer AS dbsOff

 

oOfferteServer := dbsOff{}

oOfferteServer:Addchild(dbsOffRgl{}, #OFFNR )

 

oWin := OfferteWin{Self,,oOfferteServer}

oWin:Show()

RETURN Self

 

Mocht het nodig zijn om b.v. in een subform de offerteregels te tonen, dan kan dit gemakkelijk doordat de OffRgl-server op deze wijze ook direct beschikbaar is. Maak het subform zoals normaal, maar haal daarna de inhoud van de server-property weg. Dan wordt namelijk geen Use-aanroep gegenereerd. Dat kunt u dan later handmatig doen. Hieronder een voorbeeld van benodigde code gebaseerd op dit principe:

 

ACCESS oSfOffRglForm CLASS OfferteWin

// Nodig omdat oSf… een protected-var is.

RETURN Self:oSfOfferteWin_Detail

 

ACCESS oOffRgl CLASS dbsOfferte

RETURN Self:aChildren[1]

 

METHOD OpenOfferteWindow CLASS StandardShellWindow

LOCAL oWin AS OfferteWin

LOCAL oOfferteServer AS dbsOff

 

oOfferteServer := dbsOff{}

oOfferteServer:Addchild( dbsOffRgl{}, #OFFNR )

 

oWin := OfferteWin{ Self,,oOfferteServer }

oWin:oSfOffRlgForm:Use( oOfferteServer:oOffRgl )

oWin:Show()

 

RETURN Self

 

Het is helaas niet mogelijk een volledig functionele class te beschrijven die al dit soort principes in zich heeft; daar zou zo ongeveer een heel boek voor nodig zijn. Zo zou de hiervoor beschreven DbChildServer eenvoudig kunnen worden aangepast voor relaties die andersom liggen. Op die manier kan dan gecontroleerd worden of een record wel mag worden verwijderd, hetgeen b.v. het geval zou kunnen zijn als er geen referenties meer naar zijn; vooral handig bij referentie tabellen.

Ook is in de gepresenteerde voorbeelden de foutafhandeling nauwelijks aanwezig, hetgeen deze code niet bruikbaar maakt binnen een omgeving met meerdere programmeurs. Dit laatste druist juist in tegen de principes van objectoriëntatie. Op dit vlak is er dus duidelijk nog wat werk aan de winkel. De bedoeling was echter wat ideeën te geven waarop u zelf uw dataserver-class kunt baseren, en wel onder het motto: ‘Steel het idee, niet de code’.

Ik wens u daarmee veel succes en ben gaarne bereid via de nieuwsgroepen uw vragen te beantwoorden.

 

Ed Richard

Commentaar van anderen:
ChristianLouboutin op 14-8-2010 om 11:27
Christian Louboutin Shoes, Christian Louboutin, Christian Louboutin Shoes, Wedding Shoes, Christian Louboutin Copyright 2010, Chemicals Chemistry via VerticalNews. Christian Louboutin Shoes, Wedding Shoes Pattinson great actorly virtue is that he wears clothes well, so it too bad he slackered-out in cargo pants here. Christian Louboutin, Christian Louboutin Shoes, Wedding Shoes, Discount Christian Louboutin, Manolo Blahnik Shoes Tyler is less revealed than telegraphed through accessories a dead brother depth, a pack-a-day habit angst, a bookstore job smart, Discount Christian Louboutin, Louboutin, Christian Louboutin Sale, Louboutin Shoes, Sale Christian Louboutin Rodita zip sandals New style Black 14 a rich, aloof, and permanently disappointed daddy Pierce Brosnan. Louboutin Sale, Herve Leger Bandage Dress, Herve Leger Dress, Herve Leger V Neck Dress, Herve Leger Bandage Dress Falling for You Love, angst, and something else is in the air in Remember Me Remember Me Herve Leger Dress, Chanel Shoes, Yves Saint Laurent Shoes, Manolo Blahnik Shoes Platform Cage Sandal 13 by Allen Coulter Summit Entertainment Opens March 12 Putatively a new romance starring Robert Pattinson, Remember Me begins like a vigilante movie Alexander Wang Shoes, Louboutin Shoes, Louboutin Sale, Louboutin, Christian Louboutin Sale, Buy Christian Louboutin A Brooklyn subway platform, a racially charged stickup girl watches her mother get shot. Christian, Christian Louboutin Discount, Christian Dior Shoes, Christian Louboutin Pumps Pattinson great actorly virtue is that he wears clothes well, so it too bad he slackered-out in cargo pants here.
Geef feedback:

CAPTCHA image
Vul de bovenstaande code hieronder in
Verzend Commentaar