|
Heinpragt.com
(c) Hein Pragt |
Taalfoutje melden! | Mijn
|
|
|
|
|
Een internet pagina voor 'C' en 'C++' software ontwikkelaars.Op deze pagina probeer ik een soort naslagwerk voor 'C' en 'C++' programmeurs te maken, in het Nederlands. Deze pagina is niet beschikbaar in de Engelse versie, omdat er voor de Engelse taal al hele goede internet sites zijn.
1. Een introductie in 'C++' voor 'C' programmeurs.(c) Hein Pragt 1998In dit artikel probeer ik een aantal goede redenen te geven om over te stappen op 'C++' zonder het object georiënteerd deel te gebruiken. Dit is in mijn visie de eerste stap die 'C' programmeurs kunnen maken zonder een cultuur schok door te maken. Object georiënteerd programmeren is namelijk een andere denk en ontwerp wijze in plaats van alleen wat nieuwe functies. Maar 'C++' is heel goed te gebruiken zonder object georiënteerd te werken. Toen ik 8 jaar geleden voor het eerst kennismaakte met 'C++' zei ik spottend tegen een collega, "Alles wat in 'C++' mogelijk is, kan ik ook in standaard 'C' maken, ik zie het nut niet zo". Ik had volkomen gelijk, en vele collega 'C' programmeurs waren het met me eens. Het was pas twee jaar later toen ik helemaal 'om' was voor het object georiënteerd programmeren, dat ik mij verder ging verdiepen in 'C++'. Ik ontdekte ook dat zonder object georiënteerd programmeren de taal 'C++' een sterk verbeterde 'C' is, en ik zal proberen uit te leggen waarom. Inhoud opgave deel 1
Hele strikte type controleDe controle op variabele en functie types is heel strikt in 'C++', dit houdt in dat als U alles heel goed moet declareren. Als U een ander type parameter wilt gebruiken dan de gedeclareerde, of in een expressie verschillende data types gebruikt, bent U verplicht een cast te gebruiken. Dit geld ook voor signed en unsigned en char naar int conversie. Zo slordig als we in 'C' kunnen zijn kan in 'C++' absoluut niet. Dit lijkt wat omslachtig maar het zorgt ervoor dat we beter aangeven aan de compiler wat we eigelijk willen, en voorkomt veel programmeer fouten.Ik vind het prettig om goed door een compiler op mijn vingers gekeken te worden, en compileer dan ook meestal op het hoogste warning niveau. Dit is gratis controle door de compiler, en dit heeft me al redelijk wat bugs bespaart. Helaas is het met Microsoft nog wel eens zo dat hun eigen include files niet zonder warning op het hoogste warning niveau gecompileerd kunnen worden. Dit los ik dan op door rond de #include file een #pragma te gebruiken om de warnings tijdelijk uit te zetten. Terug naar inhoud opgave Verbeterd commentaar'C++' heeft een verbeterde methode om commentaar te plaatsen. Naast de bestaande methode door middel van /* ... */ staat C++ het ook toe, door middel van een // dubbele slash de rest van de regel als commentaar te beschouwen. (Dit was in de meeste ANSI compilers ook al mogelijk.) De twee commentaar stijlen kunnen ook door elkaar gebruikt worden.
void testfunc(int i) // Dit is een commentaar tot einde regel.
{ /* Dit is oude commentaar stijl
en kan over meerdere regels lopen. */
}
Terug naar inhoud opgave
Andere cast methode'C++' kent een verbeterde cast, in plaats van (long) var kan nu ook long(var) geschreven worden, wat een stuk duidelijker aangeeft wat we bedoelen.result = long(var1) * var2; TestFunc(long(IntVar),Str);Terug naar inhoud opgave Verplichte functie declaratiesIn 'C++' moet elke functie gedeclareerd worden voor ze gebruikt word, dit verplicht de programmeur tot netjes declareren. Ook dit is weer extra controle door de compiler van de programmeur. Als deze de functie anders wil aanroepen, is hij verplicht een cast te gebruiken. (Dit was in ansi 'C' ook al aanbevolen maar niet verplicht.)Terug naar inhoud opgave Functie overloadingBinnen 'C++' word behalve de functie naam ook de parameters en de return waarde gebruikt in de symbol table. Dit houdt in dat we dezelfde functie met andere parameters kunnen declareren zonder iedere keer een andere naam te bedenken. Denk hierbij aan de functies atoi() atof() atol() uit de standaard 'C' library, welke in 'C++' een functie kunnen zijn.In 'C' zouden we het afdrukken van verschillende types zo oplossen:
void DrukafInt(int getal)
{
// Code
}
void DrukafLong(long getal)
{
// Code
}
void DrukafStr(char *str)
{
// Code
}
void TestFunc()
{
DrukafInt(10);
DrukafLong(423424L);
DrukafStr("test");
}
In 'C++' zoekt de compiler de goede functie afhankelijk van de parameters.
void Drukaf(int getal)
{
// Code
}
void Drukaf(long getal)
{
// Code
}
void Drukaf(char *str)
{
// Code
}
void TestFunc()
{
Drukaf(10);
Drukaf(423424L);
Drukaf("test");
}
Dit houdt in dat we voor alle parameter types een functie naam kunnen gebruiken.
Terug naar inhoud opgave Default parametersIn 'C++' kunnen we een functie met een variabel aantal parameters aanroepen, als we gebruik maken van default parameters.
void TestFunc(char *Str, int i = 5)
{
cout << Str << " " << i; // Druk resultaat af!
}
TestFunc("Dit is met twee parameters",10); // Dit drukt 10 af
TestFunc("Dit is met een parameter"); // Dit drukt 5 af
Terug naar inhoud opgave
Meer vrijheid in het declareren van variabelenIn 'C++' kunnen variabelen overal gedeclareerd worden, en hun scope is het block {} waarbinnen ze zich bevinden. In 'C' moeten declaraties vooraf gaan aan statements, in 'C++' mag daar waar een statement toegestaan is, ook een declaratie staan. Dit maakt het mogelijk om bijvoorbeeld binnen if code blokken locale variabelen te gebruiken.
int TestFunc()
{
int var1; // Deze variabele is globaal voor de hele functie
// code
if (var1> 100) {
int var2; // De scope van deze variabele is dit if block
// code
} // Einde variabele var2
int var3; // Hier begint variabele var3
// code
} // Hier eindigen var1 en var3;
Terug naar inhoud opgave
Verbeterd FOR statementIn 'C++' kunnen we de loop variabele in het for statement declareren. De scope van deze variabele is het vorige {} code block, hoewel we misschien verwachten dat de scope de for loop zou zijn. In dit voorbeeld is de variabele ind na de for loop ook nog te gebruiken.
void TestFunc()
{
for (int ind=0; ind < 10; ind++)
{
// code
}
}
Terug naar inhoud opgave
Eenvoudigere struct, enum en union notatieIn 'C++' kunnen we als we een structure gedeclareerd hebben, variabelen van dit soort zonder het woord struct declareren. Dit kon in 'C' ook wel door middel van een typedef, maar is in 'C++' prettiger opgelost.
struct Stype {int a, int b };
Stype StructVar;
Dit geld ook voor enum en union.
enum Boolean { FALSE, TRUE };
Boolean Gereed = FALSE;
Terug naar inhoud opgave
Echte constantenIn 'C++' maakt het keyword const een variabele een echte constante. De compiler zal ook een foutmelding geven als de programmeur de waarde probeert te veranderen.
const int Cvar = 100;
void Test(const int index)
{
index = 5; // Hier geeft de compiler een foutmelding
}
void Test()
{
Cvar = 10; // Ook hier geeft de compiler een foutmelding
}
int Varray[Cvar]; // Dit zou in 'C' een foutmelding geven.
Terug naar inhoud opgave
Nieuwe input en output methodeEen van de belangrijkste wijzigingen in 'C++' is de vervanging van de standaard I/O library stdio in iostream. Het gebruik van iostream is heel wat eenvoudiger dan stdio, al is het even wennen voor de doorgewinterde 'C' programmeur. Hier volgen enkele voorbeelden:
cout << "Hello world\n"; // Output Hello world met een newline
cout << "Hello world" << endl; // Idem
int VarInt = 4;
int Var1,Var2;
float VarFloat = 3.14;
char *Str = "Hello";
cout << Str << VarInt << VarFloat << endl;
// Resulteert in Hello43.14
cout << setw(6) << setfil('*') << 134;
// Resulteert in ***134
cin >> VarInt;
// Leest 1 integer uit de input stream
cin >> Var1 >> Var2;
// Leest 2 integers uit de input stream
In 'C' schrijven we vaak voor standaard I/O:
while (var1 = getchar())
putchar(var1);
Dit schrijven we in 'C++' als:
while(cin >> var1)
cout << var1;
Terug naar inhoud opgave
Nieuwe geheugen beheer methodeIn 'C++' kunnen we nu in plaats van de zeer omslachtige en overloaded functies alloc() en free() waarbij we zelf de lengte van objecten moesten berekenen, nu ook new en delete gebruiken. Dit hebben ze duidelijk van de taal Pascal geleend, en werkt heel prettig en efficiënt.
void TestFunc()
{
int *IntPointer;
IntPointer = new int;
*IntPointer = 12;
cout << *IntPointer;
delete IntPointer;
}
void TestFunc()
{
int *IntPointer;
IntPointer = new int(100);
IntPointer(10) = 12;
cout << IntPointer(10);
delete [] IntPointer; // Let op bij arrays altijd [] gebruiken
}
Dit is zeer gemakkelijk in vergelijking met de oude 'C' methode. Terug naar inhoud opgave Call by referenceIn 'C++' kunnen we nu met call by reference werken in plaats van pointers. Dit maakt de code in bepaalde gevallen, heel wat duidelijker.In 'C' zouden we het volgende schrijven:
void Swap(int *Var1, int *Var2)
{
int Tmp = *Var1;
*Var1 = *Var2;
*var2 = Tmp;
}
void TestFunc()
{
int V1, V2;
Swap(& V1, & V2); // Voorbeeld aanroep functie swap;
}
In 'C++' kunnen we dit op de volgende wijze doen:
void Swap(int& Var1, int& Var2)
{
int Tmp = Var1;
Var1 = Var2;
var2 = Tmp;
}
void TestFunc()
{
int V1, V2;
Swap(V1,V2); // Voorbeeld aanroep functie Swap in C++
}
Terug naar inhoud opgave ConclusieBij de meeste compilers is het omschakelen van 'C' naar 'C++' simpelweg het veranderen van de extensie van de source file van TEST.C in TEST.CPP waardoor de compiler weet dat de source file een 'C++' file is. Als U dit doet moet U dit voor alle files doen, omdat 'C' code geen 'C++' kan aanroepen. Omgekeerd is wel via een speciale declaratie mogelijk maar ik raad het af 'C' en 'C++' files door elkaar te gebruiken. Verder kan het aanroepen van zelfgeschreven library functies problemen gaan geven, omdat deze verwachten volgens de 'C' conventie aangeroepen te worden.Omdat 'C' een subset is van 'C++' kan elk 'C' programma ook door een 'C++' compiler gecompileerd worden. Laat U niet afschrikken door het grote aantal warnings, en zet vooral het warning level niet lager om het aantal warnings terug te brengen. Besteed daarentegen eens een tijdje aan het plaatsen van casts en de kans is groot dat U terloops ook nog een programmeer fout ontdekt. Tot mijn verbazing zijn er nog steeds bedrijven waar code uitgeleverd word, met een flink aantal compiler warnings, omdat de programmeur denkt dat hij weet wat hij doet, en hij vindt dat de compiler te kieskeurig is. In mijn visie is elke warning een mogelijke programmeer fout, en moet weggewerkt worden. Als U vragen of opmerkingen heeft, hoor ik het graag. Terug naar inhoud opgave 2. Vragen en antwoorden.
C en C++ - De programmeertaal C++ Nog geen vragen binnen deze rubriek!2. Boeken voor 'C' en 'C++' programmeurs.(c) Hein Pragt 1998Ondanks de elektronische manuals, en de zeer uitgebreide help files bij de huidige compilers, geef ik toch de voorkeur aan een boek. Een boek kun je overal lezen, zelfs in bed, achtertuin of trein. Met een elektronisch boek gaat dit niet zo best. (geloof me ik heb het geprobeerd!) Ik ben zelf de trotse bezitter van een paar meter boeken, en ik schaf me gemiddeld één boek per maand aan. Dit zijn ook boeken die zijdelings met mijn vak te maken hebben, zoals de gehele reeks Dilbert boeken. Het probleem hierbij is vaak het vinden van een goed boek. Heel vaak krijg ik een tip van een collega, of zie ik een recensie in een tijdschrift. Van de boeken die de taal 'C' en 'C++' behandelen, laat ik hier mijn favoriete boeken zien.
Als U vragen of opmerkingen heeft, of een leuk boek kent, hoor ik het graag. Berichtje aan Hein Pragt 3. Een OOP aanpak in standaard 'C'.(c) Hein Pragt 1998Een tijdje geleden had ik een gesprek met een collega, en een bevriende programmeur uit Amerika over een OOP aanpak ik 'C'. Ik moest namelijk een bestaand project van het begin af aan herschrijven in 'C'. Voor deze embedded applicatie was alleen een ANSI 'C' compiler beschikbaar. Als je aan OOP gewend geraakt bent, mis je dit als je in standaard 'C' moet gaan werken. Ik wist dat de eerst 'C' met classes puur standaard 'C' was, met een speciale pre-processor. Dit gaf me het idee een systeem op te zetten in standaard 'C' om data hiding, en class interfaces te realiseren. Na wat ruggespraak met collega's kwam hier een aardig systeem uit welke ik nu gebruik als ik in standaard 'C' moet werken. De code die dit systeem genereert is bijna niet groter dan een standaard 'C' aanpak. Hoe werkt het!Het voorbeeld bevat twee classes test1 en test2. Deze bestaan uit een include file met de class definitie, en een 'C' file met de implementatie. De include file bevat een structure, die pointers bevat naar de member functies van de class, en een extern definitie van de class structure. Dit is op deze wijze gedaan omdat in oudere 'C' compilers geen functies opgenomen kunnen worden binnen structures, maar wel pointers naar functies.Ik kreeg dit idee na het lezen van het boek van Stroustrup, the 'C++' programming language, waarin hij er voorkeur aan geeft een class met alleen maar public members een struct te maken.
/* -------------------------------------------------------------- */
/* Include file for test class */
/* (c) Hein Pragt 1998 */
/* -------------------------------------------------------------- */
struct _test1_class /* Class definition */
{
void (*func1)(int); /* Modifier */
int (*func2)(void); /* Selector */
};
extern const struct _test1_class test1;
De bijbehorende 'C' file bevat de implementatie van de class. Hier declaren
we ook de data die bij deze class hoort, de public data kan gewoon gedeclareerd
worden en dus ook door andere modules rechtstreeks benaderd worden. De private
variabelen declareren we static zodat ze alleen binnen deze module
benaderd kunnen worden. Data hiding is dus bereikt doordat de static
data binnen de class alleen door de member functie benaderd kunnen worden.In dit voorbeeld heb ik een modifier en een selector functie gemaakt. De member functies zijn ook static zodat ze nooit rechtstreeks aangeroepen kunnen worden, maar alleen via de interface structure. Een modifier member functie veranderd iets aan de staat van de interne variabelen, een selector member functie geeft een interne waarde terug aan de module van waar deze aangeroepen werd. De struct is de gedefinieerde interface. Het vullen van de functie pointers gebeurd tijdens het compileren zodat een aparte constructor/destructor niet direct nodig zijn. Deze kunnen echter gewoon als member functies toegevoegd worden. Ze moet echter wel apart aangeroepen worden, omdat dit niet automatisch gebeurd.
/* ---------------------------------------------------------------- */
/* Implementation file of test1 class. */
/* (c) Hein Pragt 1998 */
/* */
/* Demonstration of data and member function hiding in standard 'C' */
/* ---------------------------------------------------------------- */
#include "test1.h" /* Definition of test1 class */
/* ------------------------------------ */
/* These member functions are static */
/* and can only be called trough the */
/* class member interface. */
/* ------------------------------------ */
static void func1a(int);
static int func2a(void);
/* ------------------------------------ */
/* Local data cannot be accesed outside */
/* this module and be accessed trough */
/* class members functions. */
/* ------------------------------------ */
static int local_data;
/* Trick to init the class */
struct const _test1_class test1 = { func1a, func2a };
/* ------------------------------------ */
/* Class function 1 */
/* This is a modifier. */
/* ------------------------------------ */
static void func1a(int b)
{
printf("Test1 class func1 set local variable to %d and adds 100\n",b);
local_data = b + 100;
}
/* ------------------------------------ */
/* Class function 2 */
/* This is a selector. */
/* ------------------------------------ */
static int func2a()
{
printf("Test1 class func2 return the value %d\n",local_data);
return(local_data);
}
Overerving (dit is ook niet mijn favoriete deel van OOP) is met dit
systeem echter niet mogelijk. Maar het kunnen opzetten van een programma
met ingekapselde objecten, en goed gedefinieerde interfaces is al een stap
in de goede richting. Het systeem staat en valt wel met consequent gebruik.
Het is geen beveiliging tegen slecht programmeren.Als laatste volg de main code die de class gebruikt.
/* ---------------------------------------------------------------- */
/* Main module uses test class. */
/* (c) Hein Pragt 1998 */
/* */
/* Demonstration of data and member function hiding in standard 'C' */
/* ---------------------------------------------------------------- */
#include "test1.h" /* Get definition of test1 class */
#include "test2.h" /* Get definition of test2 class */
main()
{
int res;
printf("\n\nDit is een test van OOP methode in standard 'C'\n\n");
test1.func1(234); /* Call a modifier function */
res = test1.func2(); /* Call a selector function */
printf("The return value is: %d \n\n",res);
test2.func1(333); /* Call a modifier function */
res = test2.func2(); /* Call a selector function */
printf("The return value is: %d \n\n",res);
}
Om het wat eenvoudiger te maken heb ik hier de volledige sourcecode van
dit voorbeeld gezet, zodat U dit kunt downloaden. Ik sta open voor suggesties,
verbetering (taalfouten) en andere reacties. Wilt U reageren (Wat uiteindelijk
mijn bedoeling is), stuur me dan een email. Berichtje
aan Hein Pragt Ik lees de email zeker eens per dag. De sourcecode kunt U hier downloaden.
4. Een vergelijking tussen Visual C++ en C++ Builder.(c) Hein Pragt 1999Na jaren met Microsoft Visual C++ gewerkt te hebben, heb ik op aanraden van een collega, een tijdje met C++ Builder van Borland (Inprise) gewerkt. Ik was erg onder de indruk van C++ Builder maar na een paar maanden keek is wat ontnuchterd naar beide compilers en moest voor mezelf een besluit maken welke compiler is verder zou gaan gebruiken, voor nieuwe projecten. Dit leverde een weloverwogen keuze op, in het voordeel van Microsoft Visual C++. Dit ondanks mijn jarenlange kritiek op Microsoft. Ik moet bekennen dat Visual C++ een erg goed product is. Hieronder staat een persoonlijk objectief vergelijk tussen Visual C++ en C++ Builder. De versies zijn 4.2 en 5.0 voor Visual C++ en versie 3 voor C++ Builder. Het blijft echter mijn mening, als U het er niet mee eens bent laat het mij dan weten via een email.
Slot conclusie.Beide producten hebben hun voor en nadelen, en zijn bijna even goed. Voor de beginnende C++ programmeur is waarschijnlijk C++ Builder een goede keuze. Een groot voordeel voor C++ builder is ook de meegeleverde Database Engine, dit is een groot nadeel van Visual C++. Ook is C++ Builder in het voordeel als er snel even een applicatie gemaakt moet worden. Echter voor solide zakelijke applicaties zal ik de voorkeur geven aan Visual C++, mede omdat het betrouwbare, compacte en snelle code maakt.5. De basis van object georiënteerd programmeren.(c) Hein Pragt 1999Voordat ik begin uit te leggen wat object georiënteerd (vanaf nu OO) programmeren is, begin ik met een definitie wat objecten zijn. Objecten zijn alle dingen die wij kunnen bevatten, met duidelijk afgebakende grenzen. Voorbeelden zijn, een punt op het scherm, een pomp, een bankrekening, een computer, een mens of een programmeertaal. Twee verschillende objecten zijn duidelijk van elkaar te onderscheiden. Een object heeft een aantal kenmerken:Een class is een definitie van een object, waarmee instances (echte objecten) van de class gemaakt kan worden. Een class op zich is geen object, er kunnen objecten mee gemaakt worden. Van een class kunnen we meer dan een object (instances) maken. De class is vergelijkbaar met een gietvorm waar we veel dezelfde beeldjes mee kunnen gieten. In de class definiëren we een interface. We kunnen alleen met een object communiceren via deze interface. Ook definiëren we in de class de interne data, waarin we de toestand van een object opslaan. Interne data is dus ingekapseld en niet direct benaderbaar door de buitenwereld. OO software is gebaseerd op deze objecten. Een object kunnen we beschouwen als een "gesloten apparaat" met een vast gedefinieerde interface. We hoeven niet te weten wat er zich in het object bevind, we kennen de interface waarmee we communiceren met het object. Een voorbeeld is een televisie toestel. We hoeven niet weten wat er in de T.V. zit, we gebruiken alleen de knoppen en het scherm als interface. Als we een andere zender willen kiezen, veranderen en we niet de afstemkring door binnen in het toestel aan een van de onderdelen te draaien, maar we geven de interface via een knop de opdracht op een andere zender af te stemmen. Via deze knoppen kunnen we ook zenders zoeken en in het geheugen van de T.V. opslaan. Hoe dit intern gebeurt willen we niet weten, en is voor het normaal gebruik van het toestel niet belangrijk. Intern kan dit in verschillende toestellen anders opgelost zijn, vanuit de interface zien we hetzelfde. Deze inkapseling van data en methodes is de basis van OO programmeren. De interface functies zijn ook weer onder te verdelen in vier soorten:De constructor en destructor zijn interne functies van het object, de modifier en de selector zijn van buiten het object te gebruiken. Doordat de buitenwereld geen directe toegang heeft op de interne data van een object, kan via de interface functies bijvoorbeeld validatie plaatsvinden. Als gedefinieerd is dat een bankrekening niet negatief mag zijn kan de member functie VerlaagSaldo een controle uitvoeren of het saldo door deze bewerking niet negatief kan worden. In dit geval kan de member functie een fout afhandeling starten of een foutmelding genereren. De interface bewaakt dus de interne toestand van een object. De tegenhanger van OO programmeren is het procedure gericht programmeren. Hier staan de bewerkingen centraal, in tegenstelling van OO programmeren waar de gegevens en hun toestand centraal staan. In OO begint men met een data model, waarna men deze via objecten in categorieën onderbrengt, om daarna de interface en de bewerkingen te definiëren. Dit is duidelijk een andere aanpak, die het ook nodig maakt eerst over het programma en het data model na te denken. Dit in contrast met procedure gericht programmeren waar vaak een globale opzet van een programma word gemaakt, waarna deze procedures uitgewerkt worden. Dit is niet per definitie een slechtere aanpak, maar een andere, die ook zijn voordelen kan hebben. Ik heb wel eens te horen gekregen, als is een ontwerp op papier aan het maken was, "wanneer begin je nu met het project". Deze mensen dachten dat het inkloppen van code het programmeren is. Dit is echter maar een klein deel van het programmeer werk. Het meeste is ook zonder computer te doen. Een tweede eigenschap van OO programmeren is overerving.Als we eenmaal een class gedefinieerd hebben, ligt deze vast. Als er nu een specialisatie plaats moet vinden, kan de reeds ontworpen class als basis dienen voor een nieuwe class. De nieuwe class bevat alle onderdelen van de oorspronkelijke class, met een aantal toevoegingen speciaal voor de nieuwe class. Als we een bankrekening zonder rente gedefinieerd hebben met een groot aantal bewerkingen, kunnen we hiervan een rekening met rente afleiden. De bewerkingen die we kunnen uitvoeren op de oorspronkelijke rekening kunnen we ook uitvoeren op de rekening met rente. Deze rekening heeft echter een paar uitbreidingen t.o.v. de oude rekening, en dat is een rentepercentage variabele, een functie om het rentepercentage op te vragen en een functie om het rentepercentage te veranderen. Ook zal er een functie moeten komen om de rente bij te boeken. De code om het saldo op te vragen en het saldo af te boeken hoeven we niet opnieuw te schrijven.Dit is een eigenschap van OO programmeren die ik nogal eens uit de hand zie lopen. Een goede class hiërarchie opbouwen is een kunst, en soms zie je een ad-hoc class hiërarchie die ondoorzichtig en niet te onderhouden is. Het werken met OO is geen garantie voor goede en goed onderhoudbare code. Een paar goede voorbeelden van een class hiërarchie zijn OWL van Inprise en MFC van Microsoft. OO werken ten opzichte van procedureel programmeren betekend vaak de je veel vrijheden die je had moet opgeven en binnen een strakkere structuur moet werken. Dit voorkomt echter heel veel basis programmeer fouten, zodat het resultaat beter, en beter onderhoudbaar is. Deze vorm van jezelf de beperkingen van een goede structuur opleggen, schrikt sommige 'C' en assembler programmeurs nog wel eens af. Een collega van mij plaagt me wel eens, als ik weer iets met de bestaande code wil doen waarin niet voorzien is, dat beperkingen opleggen geheel in de stijl van OO programmeren is. Ik probeer dan uit te leggen dat ik vanuit de bestaande code deze functionaliteit niet kan toevoegen, maar dat dit in een OO omgeving eenvoudig te doen zou zijn. Het grote voordeel van OO programmeren is dat het uitnodigt tot goed gestructureerd werken, en dat je in staat bent goede interfaces te maken. Data hiding is in mijn visie een van de beste onderdelen van OO. 6. Een artikel dat in PT Embedded Juni 1999 geplaatst is.(c) Hein Pragt 1999Elke nieuwe techniek is de moeite van het bestuderen waard. Graag reageer ik op het artikel van prof. drs. Maarten Boasson in pt Embedded Systems van Februari 1999. Hoewel ik het in sommige op zichten wel eens ben met de heer Boasson, wil ik toch een aantal opmerkingen maken over zijn artikel en de aangehaalde voorbeelden.Er wordt een voorbeeld met autorijden gebruikt dat niet correct is. Het autorijden is de laatste tien jaar sterk verbeterd doordat de autoindustrie telkens weer met verbeteringen in het ontwerp kwam en nieuwe technologie is gaan toepassen. Ook wordt in het voorbeeld popnagels gebruikt als verbindingstechniek, om lijmen te vervangen. Hier zou men dus een gloednieuw en betere verbindingsmethode zoals lijmen (zelfs vliegtuigenonderdelen worden tegenwoordig gelijmd in plaats van popnagelverbindingen) door een verouderde techniek als popnagels vervangen. Dit is dus een slecht voorbeeld. Het objectgeoriënteerde ontwerpen is een nieuwe techniek die een aanvulling moet zijn op bestaande technieken. Geen enkele techniek is dusdanig goed dat het alle voorgaande technieken volledig kan vervangen. Dit mag echter geen reden zijn om elke nieuwe techniek bij voorbaat af te wijzen als zijnde onbruikbaar. Een goed vergelijk is de elektronica-industrie. De ontwerper heeft de keuze uit een groot aantal standaardcomponenten en maakt daarmee een schakeling. Een component heeft een door de fabrikant bepaald aantal poorten en functionaliteiten, en de ontwerper moet daar in zijn ontwerp rekening mee houden. Dit betekent dat er wel eens een paar ongebruikte poorten in zijn ontwerp zitten en dat hij, als hij een poortje tekort komt, soms een tussenoplossing moet vinden want we willen (of moeten) zo weinig mogelijk componenten gebruiken. Het grote voordeel voor de ontwerper is dat de eigenschappen van de standaardcomponenten goed zijn beschreven, de componenten hun stabiliteit reeds hebben bewezen, en dat er second sources zijn. Dit leidt tot een beter en efficient ontwerpproces. In de elektronica zullen weinig mensen hun eigen componenten samenstellen, tenzij het om grote aantallen gaat. In de software-industrie wordt echter nog heel vaak voor elk nieuw probleem een nieuwe oplossing bedacht. In de ideale situatie zou het ontwerpen van software vergelijkbaar moeten zijn aan het ontwerpen van hardware. Het gebruik van standaardcomponenten (lees: objecten zou tot betere en sneller te ontwikkelen producten kunnen leiden. Dit is niet iets wat binnen een korte tijd kan worden gerealiseerd, maar door nieuwe ontwikkelingen in standaard herbruikbare componenten op te zetten zal deze (objectgeoriënteerde) ontwerpmethode langzaam zijn intrede doen. Oude en nieuwe technieken kunnen langzaam in elkaar overgaan. Het grote probleem is dat veel mensen in bestaande organisaties al jaren met een bepaalde techniek hebben gewerkt en het gevoel hebben dat ze de nieuwe ontwikkelingen niet meer kunnen bijhouden. Als resultaat hiervan wordt de nieuwe technologie vaak afgedaan als "nieuwe fratsen en geneuzel met classes" en dergelijke. Dit is vaak gebaseerd op de angst het niet allemaal meer te kunnen bijbenen, of na jaren nog een andere wijze van denken te moeten leren. Echter de ontwikkelingen in de techniek staan niet stil, en men zal steeds om nieuwe gereedschappen in de (software) gereedschapskist vragen. Dit is een natuurlijk proces dat niet te stuiten is. Mijn mening is dan ook dat elke nieuwe techniek de moeite van het bestuderen waard is, en ook al is zij niet direct toepasbaar, op een dag kan ze de oplossing van een bepaald probleem zijn. HEIN PRAGT Juni 1999
|
|
Disclaimer. |