Visual Basic 2005 Coach



Dovnload 477.64 Kb.
Pagina10/13
Datum20.08.2016
Grootte477.64 Kb.
1   ...   5   6   7   8   9   10   11   12   13

7.4. Conclusie

Object-oriëntatie vormt de hoeksteen van het .NET Framework en de volledige Base Class Library die bij het .NET Framework hoort is gebouwd op object-oriëntatie. Daarom is het cruciaal deze concepten goed te beheersen, niet alleen om gebruik te kunnen maken van bestaande functionaliteit maar ook om eigen klassen, interfaces en dergelijke te definiëren die uw software uitbreidbaarder en eenvoudiger te onderhouden zullen maken door een verbeterde modulariteit.


Komen deze concepten in eerste instantie overweldigend over dan hoeft u evenwel niet te panikeren. De MSDN documentatie bevat een heleboel informatie die u zeker vooruit helpt bij het verstaan van de diverse concepten en via het net zijn tal van voorbeeldapplicaties beschikbaar waarin u deze concepten in de praktijk ontmoet. Het loont zeker de moeite waard dergelijke voorbeelden op te zoeken en nader te bestuderen indien u nog niet vertrouwd bent met object-geöriënteerd ontwerp.

8. Exceptiebeheer

Vooraleer we onze pijlen richten op Visual Basic 2005 nemen we eerst een kijkje op een belangrijk concept dat min of meer in verband staat met object-oriëntatie. Hoe je het draait of keert, bij het uitvoeren van een applicatie zullen steeds fouten optreden. Onder fouten verstaan we hier geen bugs maar eerder problemen die de kop opsteken bij het uitvoeren van de applicatie. Een klassiek voorbeeld is het pogen tot openen van een bestand dat gelockt is door een ander proces. Dergelijke uitzonderlijke omstandigheden kunnen we moeilijk allemaal anticiperen op voorhand maar zullen evenwel optreden in de praktijk. Voor dergelijke problemen dienen we te beschikken over een hulpmiddel om deze excepties af te handelen. Hoe gebeurde het afhandelen van fouten vroeger en nu? Een overzicht.



8.1. Vroeger

Voor de komst van talen zoals C++ en runtimes zoals .NET werd het afhandelen van fouten geregeld via foutcodes. Bij het oproepen van functies werd de returnwaarde steeds gereserveerd voor een statuscode, te vergelijken met de exitcode van een proces. In de wereld van ATL en COM gebeurde dit onder andere met een HRESULT:


HRESULT hr = CoInitialize(NULL);

if(FAILED(hr))

wprintf(L"CoInitialize failed with HRESULT %X\n", hr);
Dergelijke code leidt al gauw tot een onoverzichtelijk kluwen van geneste if-structuren en het blijft maar zeer de vraag hoe we dergelijke fouten op een gestructureerde manier laten propageren naar de oproeper van de oproeper van de ... tot op een punt waar de fout kan afgehandeld worden (à la limite door het weergeven van een foutmelding of het genereren van een foutrapport).
In Visual Basic (pre .NET) werden runtime fouten opgeworpen onder de vorm van foutcodes. Persoonlijk herinner ik me twee getallen levendig: 53 voor “File Not Found” en 76 voor “Path Not Found”. Via het statement Error kon verder een dergelijke fout opgeworpen worden vanuit code. Indien een dergelijke fout optreedt en de applicatie er niet op voorzien is, crasht de applicatie. Foutafhandeling kon dan gebeuren via het On Error statement waarin een actie werd gespecifieerd die diende genomen te worden als een fout optrad. De “gemakzuchtige oplossing” ziet eruit als On Error Resume Next. Een alternatief is een stukje code te schrijven dat de fout afhandelt op een iet wat elegantere manier via het statement On Error Goto ... of On Error GoSub ....

8.2. Nu

In de wereld van .NET gebeurt alle foutafhandeling via excepties, objecten die een fout voorstellen at runtime. Via de mechanismes van exception management kunnen dergelijke uitzonderlijke toestanden afgehandeld worden at runtime. Een overzicht van deze mechanismen.



8.2.1. De exceptie der excepties: System.Exception

Excepties zijn objecten zoals eerder vermeld en erven dus over van System.Object, zij het onrechtstreeks via het type System.Exception. In de Base Class Library bevinden zich reeds een heleboel dergelijke exceptietypes die door de diverse klassen in het framework kunnen opgeworpen (throw) worden bij de uitvoering van een programma. Een aantal voorbeelden:


NullReferenceException wordt opgeworpen wanneer een null-referentie (Nothing) wordt gebruikt bij aanroep van een procedure of iets dergelijks:
Dim auto As Auto

Dim str As String = auto.ToString()


In de debugger ziet een exceptie er als volgt uit:

We zouden nog een tijdje kunnen doorgaan met het opsommen van de diverse excepties in het .NET Framework, maar laten we het houden bij een paar kleine voorbeeldjes.

ArgumentOutOfRangeException treedt op indien een parameter buiten een bereik valt dat toegestaan is, bijvoorbeeld:
Dim naam As String = "Bart"

Dim deelVanNaam As String = naam.Substring(10)


IOException wordt gebruikt bij bestandsinvoer en –uitvoer indien een operatie niet kan uitgevoerd worden of problemen oplevert:
File.Create("c:\temp\test.txt")

8.2.2. Excepties opvangen

Het doel van exceptiebeheer is uiteraard te vermijden dat programma’s crashen door uitvoeringsfouten door de excepties op te vangen (catch). Hoe dit in de praktijk gebeurt, ziet u hieronder in een klein voorbeeldje:


Try

Dim nul As Integer = 0

Dim a As Integer = 1 / nul

Catch ex As OverflowException

MsgBox("Oops foutje." + vbCrLf + vbCrLf + "Details: " + ex.Message)

End Try
Uitvoering van dit stukje code leidt tot:



Het gebruik van de Try-Catch-structuur wordt gebruikt om excepties op te vangen die in het bewaakte stuk tussen het sleutelwoord Try en Catch optreden. Het stuk tussen Catch en End Try bevat de code die gebruikt wordt voor de foutafhandeling die hoort bij het geassocieerde type exceptie (in ons geval een OverflowException).
Door gebruik te maken van de klassenhiërarchie kan je excepties opvangen op allerhande niveaus. Wens je alle excepties op te vangen, dan doe je iets als volgt:
Try

'Stoute code...

Catch ex As Exception

'...wordt netjes opgeruimd.

End Try
Alternatief kan men zelfs het volgende schrijven:
Try

'Stoute code...

Catch

'...wordt netjes opgeruimd.



End Try
waarbij de declaratie van het exceptietype achterwege gelaten wordt. Men kan dan evenwel geen informatie over de opgeworpen exceptie bekomen (zoals de Message-property).
Indien een exceptie niet opgevangen wordt in een bepaalde methode, dan propageert deze doorheen de call stack naar de oproeper van de huidige methode. Bereikt de exceptie het hoogste niveau van deze call stack, met name het entry point van de applicatie (Sub Main) dan crasht de applicatie zonder meer. Volgende code illustreert dit principe:
Module Module1
Sub Main()

Try


DoeIets()

Catch ex As Exception

MsgBox("Oops... " + ex.Message)

End Try


End Sub
Sub DoeIets()

DoeNogIets()

End Sub
Sub DoeNogIets()

Dim nul As Integer = 0

Dim a As Integer = 1 / nul

End Sub
End Module



8.2.3. Opgeruimd staat netjes

Excepties kunnen aardig roet in het eten gooien wat betreft de betrouwbaarheid van een applicatie, ook al worden ze “netjes” opgevangen. Stelt u zich het volgende scenario voor. Een applicatie schrijft uitvoer naar een bestand maar in het midden van de schrijfoperatie treedt een fatale fout op. De applicatie was hier echter op voorzien en vangt de fout netjes op:


Sub SchrijfNaarBestand(ByVal bestand As String)

Dim file As File = File.Open(bestand)

Try

'Voer schrijfoperaties uit



Catch ex As IOException

'Schakel de opruimdienst in

End Try

End Sub
Bovenstaande code bevat echter een paar cruciale fouten die de applicatie zeker geen goed zullen doen. Wat er ook gebeurt, het bestand blijft na gebruik open wat resulteert in een lek. Het bestand dient dus gesloten te worden:


Sub SchrijfNaarBestand(ByVal bestand As String)

Dim file As File = File.Open(bestand)

Try

'Voer schrijfoperaties uit



Catch ex As IOException

'Schakel de opruimdienst in

End Try

File.Close()



End Sub
Dit is al ietsje beter, maar wat gebeurt er als er een fout optreedt? Het bestand blijft open. Om dergelijke situaties te vermijden is er ook een Finally-blok:
Sub SchrijfNaarBestand(ByVal bestand As String)

Dim file As File = File.Open(bestand)

Try

'Voer schrijfoperaties uit



Catch ex As IOException

'Schakel de opruimdienst in

Finally

File.Close()



End Try

End Sub
De code tussen Finally en End Try wordt steeds opgeroepen, ongeacht of er al dan niet een fout optrad in het Try-Catch-gedeelte. U zult later zien dat in sommige gevallen een alternatief bestaat (nieuw in Visual Basic 2005) met behulp van het sleutelwoord Using.



8.2.4. Uw eigen excepties definiëren

Bij het bouwen van uw eigen applicaties krijgt u ongetwijfeld te maken met het afhandelen van foutsituaties. Daarom is het nuttig eigen exceptietypes te creëren die ingezet worden in de applicatie om foutieve situaties te rapporteren aan de oproeper van een stuk code, die dan de gepaste acties kan ondernemen. Om een dergelijk exceptietype te creëren gaat u als volgt te werk:


Class MotorException : Inherits ApplicationException
Sub New()

MyBase.New()

End Sub
Sub New(ByVal message As String)

MyBase.New(message)

End Sub
Sub New(ByVal message As String, ByVal innerException As Exception)

MyBase.New(message, innerException)

End Sub
End Class
Ten eerste maakt u een klasse (met een naam die – per conventie – eindigt op Exception) en erft u over van ApplicationException. Vervolgens definieert u 3 typische constructoren die telkens de constructor van het bovenliggende type oproepen. Het gebruik van InnerException (zie laatste constructor) is overigens van belang om excepties te kunnen nestelen in elkaar. Stel dat uw applicatie ergens intern een IOException te verwerken krijgt dan zou u deze kunnen inpakken (wrap) in een eigen exceptietype via een InnerException.
Uiteraard kan uw exceptietype extra constructoren en members definiëren, bijvoorbeeld met referenties naar andere objecten die nuttige informatie bevatten die bij de afhandeling van de exceptie van belang kunnen zijn. Vermijd echter het gebruik van bijvoorbeeld een property genaamd ErrorCode die een foutcode bevat, vermits u dan terugkeert naar het pre-.NET tijdperk met een vlakke structuur van foutcodes. Prefereer dus het creëren van een klassenhiërarchie van excepties over het gebruik van foutcodes.

8.2.5. Excepties opwerpen

Nadat u de benodigde exceptietypes hebt gedefinieerd zoals in vorige paragraaf uiteengezet werd, dient u deze uiteraard te gebruiken waar relevant. Het opwerpen van een exceptie bestaat uit twee delen:




  1. Instantiëren van het exceptietype;

  2. Opwerpen van het exceptieobject met behulp van Throw.

Dit alles wordt hieronder in een concreet voorbeeld weergegeven:

Class Auto
Sub Start()

'Start motor en dergelijke

'Voer systeemtest uit

If BenzinePeil < 1.0 Then

Throw New MotorException("Benzinepeil te laag.")

End If
End Sub


Tot slot merken we op dat excepties goed gebruikt dienen te worden en bijvoorbeeld niet de “normale controleflow” van de applicatie mogen definiëren.



1   ...   5   6   7   8   9   10   11   12   13


De database wordt beschermd door het auteursrecht ©opleid.info 2017
stuur bericht

    Hoofdpagina