[Alg] Defensief programmeren

Pagina: 1
Acties:
  • 622 views sinds 30-01-2008
  • Reageer

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Defensief programmeren.
Iedereen kent die term wel; op een bepaalde manier programmeren zodat fouten zoveel mogelijk vermeden worden. Fouten kunnen nl. op allerhande manieren in een programma sluipen: concentratieverlies, geen rekening houden met bepaalde condities/situaties, etc...

Wat betekent defensief programmeren voor jullie? Hoe staan jullie er tegenover en hoever gaan jullie erin?

Gaan jullie bv. altijd voor je een bepaalde bewerking uitvoert met een bepaalde variable gaan checken of die variable wel gealloceerd is?
Bouw je alle nodige controles in uw programma, ook al is de kans zeer miniem dat een bepaalde situatie zich voor doet?
Zorg je ervoor dat je alle variablen geïnitialiseerd hebt voordat je ze daadwerkelijk gebruikt en geef je je geheugen wel altijd opnieuw vrij, zodat er geen memory-leaks in uw programma sluipen?
etc...

Welke manieren hanteren jullie om fouten te voorkomen?

En, als je programma af is, hoe ga je tewerk bij het testen? Stel je een testbatterij op? Of test je helemaal niet?

* whoami is benieuwd.

https://fgheysels.github.io/


Verwijderd

Als ik zeker wil weten dat mijn programma correct werk dan schrijf voor alle classes JUnit tests. Tests die testen of alles correct werkt ook onder extreme condities ;) De echte kunst is dus vooral het bedenken van goede tests.

Als zo'n test af is echter kun je gaan prutsen aan de klasses zoveel je wilt, je kunt altijd nog controleren of ze nog correct werken met de geschreven tests. Op zich is dat een prettige gedachte. Van geheugen lekken heb je in Java/C# verder niet zo snel last, dus daar hoef ik me niet echt druk om te maken.

  • droeftoeter
  • Registratie: Mei 2002
  • Laatst online: 19-06-2025
Zelf probeer ik altijd alle mogelijke fouten af te vangen en daarvan melding te geven. Als het gaat om dynamisch gealloceerde variabelen voer ik in de functies die daarvan gebruik maken veelal een check uit op deze variabelen. Wederom met een melding als iets niet in de haak is.

Duidelijke benamingen van functies en variabelen plus het netjes resetten van variabelen bij hergebruik spreken voor zich.

Het testen doe ik altijd zelf, het programmeren van de code is immers gebaseerd op een verzameling scenarios in mijn hoofd en zal dus ook best getest worden door mijzelf.

  • Defspace
  • Registratie: Mei 2000
  • Laatst online: 17-04 23:56

Defspace

Administrator

Das een lastige.

Natuurlijk probeer ik ook zo defensief mogelijk te proggen, maar ik vang meestal alle voor de hand liggende fouten/bugs/'undocumented features ;)' meteen tijdens de eerste fase af. Later bij het testen ga ik proberen te kijken of ik nog dingen over het hoofd heb gezien. (dit is vaker het geval dan ik zou willen :+) Maar ja, gelukkig zijn het toch vaak de uitzonderingen die ik dan over het hoofd heb gezien.

Ik weet wel dat ik het iig niet voor elkaar krijg om van scratch bugloos te proggen. Ook omdat ik prioriteiten stel, en ik dus eerst wat wil hebben liggen alvorens ik dat ga optimaliseren/bijschaven.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 18-08 22:57

Gerco

Professional Newbie

Op vrijdag 05 juli 2002 10:06 schreef droeftoeter het volgende:
Het testen doe ik altijd zelf, het programmeren van de code is immers gebaseerd op een verzameling scenarios in mijn hoofd en zal dus ook best getest worden door mijzelf.
Juist niet.. bij het testen zul je waarschijnlijk waardes invullen die in je verwachtingspatroon vallen en een paar erbuiten. Geef je het programma aan een tester (lees: leek), zal die vanalles doen en ALS er een fout inzit komt 'ie naar voren.

Persoonlijk ken ik zo'n leek (die weet nog niet eens hoe MSN werkt, nou als je DAT niet kan begrijpen?) en die doet altijd de meest vreemde dingen onder de noemer van: "nou ik deed gewoon dat". Dingen waar je zelf nooit op zou komen om te testen.

Ik ben van mening dat de beste tests nog altijd NIET door de programmeur zelf gedaan moeten worden. Als je het zelf getest hebt, laat je het dus nog door iemand anders testen.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Met VB.NET kun je in princip alleen maar defensief programmeren natuurlijk kun je fouten maken die het programma niet kent, maar over het algemeen merkt vb.net alle fouten direct nadat je een enter geeft in de code

Testen:
Zodra ik een exe heb die echt fatsoenlijk is laat ik andere mensen er mee merken maar dit is nadat ik hem zelf ook heb getest.

Concentratie verlies is iets wat er altijd zal blijven dus daar kunnen wij mensen niet veel aan veranderen.....
Wij blijven tenslotte mensen en geen computers

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 10:12 schreef Gerco dat programma's beter door leken getest worden en niet door de programmeur
Ik ben hier volledig mee akkoord. Nothing to add. :)

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 10:13 schreef infinity_master het volgende:
Met VB.NET kun je in princip alleen maar defensief programmeren natuurlijk kun je fouten maken die het programma niet kent, maar over het algemeen merkt vb.net alle fouten direct nadat je een enter geeft in de code
Defensief programmeren != oo-programmeren of gestructureerd programmeren.
Defensief programmeren heeft te maken met het op een zo danige manier programmeren dat je alle mogelijke (of toch zoveel mogelijk) fouten die kunnen optreden afvangt en met alle mogelijke (of zoveel mogelijke) situaties rekening houdt.
De compiler of de IDE van VB.NET kan niet weten of er een logica-fout in een programma zit, of als er geen rekening is gehouden met een bepaalde situatie. De fouten waar jij het over hebt (die ontdekt worden bij een enter), zijn volgens mij syntax fouten, en dat heeft eigenlijk ook niets met defensief programmeren te maken.
Een compiler kan geen logica-fouten ontdekken, hij kan hoogstens aangeven dat een variable gebruikt wordt en niet geinitialiseerd is, of dat een gedeclareerde variable niet gebruikt wordt.

https://fgheysels.github.io/


  • Defspace
  • Registratie: Mei 2000
  • Laatst online: 17-04 23:56

Defspace

Administrator

Met VB.NET kun je in princip alleen maar defensief programmeren natuurlijk kun je fouten maken die het programma niet kent, maar over het algemeen merkt vb.net alle fouten direct nadat je een enter geeft in de code
Ik ken VB.net niet hoor, maar hoe doet hij dat dan ?
Hoe weet hij b.v. dat er in jouw prog (door een user) een variabele niet gezet wordt die je wel even later in je DB plompt ?
Of hoe weet hij of jij een check die je over iets wou uitvoeren vergeten bent ?
Lijkt me namelijk niet mogelijk.
Tuurlijk keiharde prog fouten haalt ie er wel uit, maar dat deed borland c++ 3.1 al als ik een ; vergeten was.

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Ligt eraan waarvoor.
Als het een Proof Of Concept is, dan doe ik het niet, dan moet het namelijk snel en het wordt toch niet gebruikt. Anders wel :)

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Deze wijzes worden door mijzelf alleen gebruikt in Java, omdat ik daar eigenlijk alleen in programmeer.

1) Controleer ALLE input
2) Declareer de belangrijkste variabelen die je voor die class /method nodig hebt op een vaste plek. De zut die in de loop gemaakt gaat worden oid, komt commentaar bij. Geef ook alles een default value
3) Laat alles verlopen via de get/set (voor alle vars!!!, vaak private set's, maar nooit direct wijzigen van vars). Dit zorgt ervoor dat ik daar een gedegen controle in kan bouwen :)
4) Maak alles final wat final kan zijn

Testen doe ik vaak niet gedegen aan. Dit omdat het voornamelijk nog hobby is enzo :) Alleen randgevallen worden dan getest dus.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 10:44 schreef Glimi het volgende:
Deze wijzes worden door mijzelf alleen gebruikt in Java, omdat ik daar eigenlijk alleen in programmeer.

1) Controleer ALLE input
Dat spreekt voorzich.
2) Declareer de belangrijkste variabelen die je voor die class /method nodig hebt op een vaste plek. De zut die in de loop gemaakt gaat worden oid, komt commentaar bij. Geef ook alles een default value
Dit doe ik ook. Alle variablen op een centrale plaats declareren (bv. aan het begin van een functie, in Delphi kan je eigenlijk niet anders). En de variablen zoveel mogelijk een initiële waarde geven.
3) Laat alles verlopen via de get/set (voor alle vars!!!, vaak private set's, maar nooit direct wijzigen van vars). Dit zorgt ervoor dat ik daar een gedegen controle in kan bouwen :)
Dit deed ik vroeger niet, maar nu wel (dankzij GoT). Er was hier al eens een discussie over en bepaalde mensen hebben mij kunnen overtuigen. (Weet niet meer welke thread het precies was).


Wat ik ook altijd doe, is tests inbouwen of er wel een bepaalde functie aan een event hangt als ik een event oproep:
Delphi code
code:
1
2
3
if Assigned (ApplyButton.OnClick) then begin
  ApplyButton.OnClick (Sender);
end;

Wat ik ook wel doe voor het casten is testen of het te casten object wel van het verwachte type is:
code:
1
2
3
if Sender is TEdit then begin
  TEdit(Sender).Text := 'blaat';
end;

Daarnaast wil het consistent toepassen van een goede coding-style ook wel helpen in het vermijden van fouten. (Maar daar is er al eens een thread over geweest, zie ook de FAQ).

https://fgheysels.github.io/


Verwijderd

Iedereen kent die term wel
:?

Wat betekent defensief programmeren voor jullie?
:? :?

Welke manieren hanteren jullie om fouten te voorkomen?
iq 8-)

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 11:19 schreef Skizmo het volgende:
Welke manieren hanteren jullie om fouten te voorkomen?
iq 8-)
Ik vind dat uw reactie niet op een hoog IQ duidt. :(

Als je niet weet wat defensief programmeren is, en je wilt het weten dan kan je toch even op google zoeken of het hier normaal vragen? Je kunt ook de thread even doorlezen en dan heb je er misschien al een idee over.

Als je niets zinnigs te zeggen hebt, zeg dan ook aub niets.

https://fgheysels.github.io/


  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 21-08 22:31
ik plaats in Java op gevoelige/kritieke punten altijd ff een System.out neer. Als ik dan de melding in mn console krijg weet ik dat ie 1) daar aankomt 2)hij het goed doet.
Verder gewoon testen en kijken of je het gewenste resultaat krijgt.

Met PHP gooi ik er soms even een echo in (di eik later weer weg haal), forms verstuur ik met GET(en later ff op POST zetten) en verder ook gewoon testen. Soms ook ff error_reporting aan :)

  • justmental
  • Registratie: April 2000
  • Niet online

justmental

my heart, the beat

Programmeren vind ik al behoorlijk saai, als het dan nog defensief moet dan verlies ik meestal de interesse ;)

Bugtracing & fixing is vaak veel leuker :)

Ik zorg wel dat het zo in elkaar steekt dat datacorruptie niet op kan treden en dat er voldoende tracingmogelijkheden en logging is.

Who is John Galt?


  • D2k
  • Registratie: Januari 2001
  • Laatst online: 09-01 11:25

D2k

Op vrijdag 05 juli 2002 11:26 schreef whoami het volgende:

[..]

Ik vind dat uw reactie niet op een hoog IQ duidt. :(

Als je niet weet wat defensief programmeren is, en je wilt het weten dan kan je toch even op google zoeken of het hier normaal vragen? Je kunt ook de thread even doorlezen en dan heb je er misschien al een idee over.

Als je niets zinnigs te zeggen hebt, zeg dan ook aub niets.
en zoiets was ik ook net aan het tikken. Eerste en laatste waarschuwing

Doet iets met Cloud (MS/IBM)


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Op vrijdag 05 juli 2002 11:19 schreef whoami het volgende:

Dit deed ik vroeger niet, maar nu wel (dankzij GoT). Er was hier al eens een discussie over en bepaalde mensen hebben mij kunnen overtuigen. (Weet niet meer welke thread het precies was).
[topic=436404/1/100]
Wat ik ook altijd doe, is tests inbouwen of er wel een bepaalde functie aan een event hangt als ik een event oproep:
Delphi code
code:
1
2
3
if Assigned (ApplyButton.OnClick) then begin
  ApplyButton.OnClick (Sender);
end;
Hmmmz hier zie ik het nut niet van in (bij Java dan). Als hij geen methode heeft, dan komt de compiler wel terug met een dikke melding :)
Wat ik ook wel doe voor het casten is testen of het te casten object wel van het verwachte type is:
code:
1
2
3
if Sender is TEdit then begin
  TEdit(Sender).Text := 'blaat';
end;
Hmmz een instanceof. Nogmaals zie ik ook hier niet het voordeel in Java. Mocht dit fout gaan, dan kunnen we die exception altijd afvangen :)
Daarnaast wil het consistent toepassen van een goede coding-style ook wel helpen in het vermijden van fouten. (Maar daar is er al eens een thread over geweest, zie ook de FAQ).
Could not agree more :)

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 11:26 schreef TheRebell het volgende:
ik plaats in Java op gevoelige/kritieke punten altijd ff een System.out neer. Als ik dan de melding in mn console krijg weet ik dat ie 1) daar aankomt 2)hij het goed doet.
Verder gewoon testen en kijken of je het gewenste resultaat krijgt.

Met PHP gooi ik er soms even een echo in (di eik later weer weg haal), forms verstuur ik met GET(en later ff op POST zetten) en verder ook gewoon testen. Soms ook ff error_reporting aan :)
Hmm. Dat heeft meer te maken met debuggen en testen dan met defensief programmeren.

Defensief programmeren kun je misschien omschrijven als:
Op een pro-actieve manier fouten vermijden
Defensief programmeren is 'er niet van uitgaan dat een bepaald statement altijd zal lukken'.

Bv:
Als je volgende code gebruikt:
code:
1
ApplyButton.OnClick(Sender);

Dan trigger je de OnClick event van die ApplyButton. Dit gaat goed zolang er een procedure aan die OnClick event gelinked is, als dat niet het geval is, dan wordt er een access violation gegeven.
Om dat te voorkomen, kun je er een test rondschrijven:
code:
1
2
3
if Assigned (ApplyButton.OnClick) then begin
  ApplyButton.OnClick (Sender);
end;

https://fgheysels.github.io/


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Op vrijdag 05 juli 2002 11:26 schreef TheRebell het volgende:
ik plaats in Java op gevoelige/kritieke punten altijd ff een System.out neer. Als ik dan de melding in mn console krijg weet ik dat ie 1) daar aankomt 2)hij het goed doet.
Verder gewoon testen en kijken of je het gewenste resultaat krijgt.
In java met System.out werken :? Hebben we daar geen debugger voor :)
Met PHP gooi ik er soms even een echo in (di eik later weer weg haal), forms verstuur ik met GET(en later ff op POST zetten) en verder ook gewoon testen. Soms ook ff error_reporting aan :)
Error_reporting ALTIJD aan zetten :)
Op vrijdag 05 juli 2002 11:27 schreef D2k het volgende:
en zoiets was ik ook net aan het tikken. Eerste en laatste waarschuwing
http://gathering.tweakers.net/forum/list_message/14077925#14077925
Tweede en laatste dus :P :+

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 11:31 schreef Glimi het volgende:


Hmmmz hier zie ik het nut niet van in (bij Java dan). Als hij geen methode heeft, dan komt de compiler wel terug met een dikke melding :)
In Delphi en in C# (ik weet niet hoe het in Java gaat), kun je at-runtime procedures/functies aan events toewijzen. Je kunt deze dan ook at-runtime op null zetten natuurlijk.

https://fgheysels.github.io/


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18-08 21:00

Creepy

Tactical Espionage Splatterer

Op vrijdag 05 juli 2002 10:12 schreef Gerco het volgende:

[..]

Juist niet.. bij het testen zul je waarschijnlijk waardes invullen die in je verwachtingspatroon vallen en een paar erbuiten. Geef je het programma aan een tester (lees: leek), zal die vanalles doen en ALS er een fout inzit komt 'ie naar voren.

Persoonlijk ken ik zo'n leek (die weet nog niet eens hoe MSN werkt, nou als je DAT niet kan begrijpen?) en die doet altijd de meest vreemde dingen onder de noemer van: "nou ik deed gewoon dat". Dingen waar je zelf nooit op zou komen om te testen.

Ik ben van mening dat de beste tests nog altijd NIET door de programmeur zelf gedaan moeten worden. Als je het zelf getest hebt, laat je het dus nog door iemand anders testen.
Hehe... gebruikers halen de gekste dingen met je programma's uit. Altijd sta ik er weer versteld van wat ze hebben uitgehaald / geprobeerd met de dingen die ik maak.

Let er wel op dat tester = leek, maar leek != tester.
Ik ken een aantal testers, die dom testen.. beetje klikken hier, beetje klikken daar, doet het wat de tester verwacht, en crasth het niet -> Programma is "goed".
En ze laten af en toe de meeste domme bugs zitten. Maar goed..

Defensief proggen... als je een "perfect" ontwerp schijft, geef je bijv. met pre- en postcondities alle voorwaarden voor functies/procedures/methods/event e.d aan. Je moet het dan wel zo maken dat aan die pre/post-condities altijd voldaan zijn.

Maar ja.. we leven niet in een ideale wereld.. perfect ontwerpen bestaan niet, en hoe vaak gebeurt het niet dat er geen (goed) ontwerp ligt, maar je toch al met de implementatie moet gaan beginnen... In dat geval bouw ik zoveel mogelijk checks in, zolang ik daar de tijd voor hebn, en ik ze kan bedenken. Maar ja... deadlines.. etc. etc... dus dan wil je wel eens wat checks "vergeten".

Ach ja... defensief programeren.. in hoeveel programma's zijn er buffer overflow's gevonden, die te triggeren zijn door ergens in een invoerveld ontzettend veel tekens in te voeren? Echt een classic voorbeeld van NIET defensief programmeren.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 21-08 22:31
Op vrijdag 05 juli 2002 11:31 schreef whoami het volgende:

[..]

Hmm. Dat heeft meer te maken met debuggen en testen dan met defensief programmeren.
..oeps..

Gewoon style-coden. Niet alles achter of in één lijn onder elkaar maar goed nesten. Commentaar erbij, geen vage namen voor classes,methods en variabelen gebruiken, enz...

Ook dingen scheiden, proberen op te delen in logische 'blokjes'(classes). Voorkomt een hoop gezoek en gescroll door je code. Declareren op logische plaatsen en dus niet 'ff tussendoor declareren'

zo dus :)

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Op vrijdag 05 juli 2002 11:36 schreef whoami het volgende:
In Delphi en in C# (ik weet niet hoe het in Java gaat), kun je at-runtime procedures/functies aan events toewijzen. Je kunt deze dan ook at-runtime op null zetten natuurlijk.
Hmmmz, dat weet ik niet helemaal maar iets zegt me dat dit met function pointers moet gebeuren, en die hebben we niet in Java. (mwoah, owkay die willen we niet gebruiken, maar reflection hebben we wel).

Kun je er anders iets meer over uitleggen, of me een urltje geven met wat info daarover :?

  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 21-08 22:31
Op vrijdag 05 juli 2002 11:33 schreef Glimi het volgende:

[..]

In java met System.out werken :? Hebben we daar geen debugger voor :)
hehe.... ja eingelijk wel maar moestr laatste wat voor school schrijven. Hadden we een dll van ze gehad die we moesten gebruiken maar dan kon je alleen niet runnen met debugger |:(

Dus vandaar... zonder debugger dus :?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik maak altijd gebruik van precondities bij methodes (altijd invoer checken en anders een exception/assert error).

Verder maak ik zo nu en dan ook gebruik van post condities. In java is een handige taal feature toegevoegd (assert) die ik hier wel eens voor gebruik. Het wordt in de debugging fase geevalueerd, en in het eind product wordt het overgeslagen. Je kan daardoor veel tijdrovende controles erin plaatsen die het programma uiteindelijk niet langzamer maken.

En zo nu en dan maak ik ook gebruik van JUnit testen. Hiermee kan je bepaalde classes door laten meten, ipv een hele applicatie op t starten om een klein stukje code te testen. Meestal controleer je dan maar een heel klein stukje omdat het zoveel werk is. Bij JUnit testen heb je hier geen last van, omdat je een soort kleine main files maakt die je objecten controleren met berekende output en verwachte uitput. En je kan ze ook met een build tool integreren (ANT) om zo iedere keer na een compilatie even die JUnit tests over al je classes uit te voeren.

Afgezien van deze technieken programmeer ik meestal vrij standaard. Altijd standaard contructies voor while en for lussen ed, zodat daar niet een nieuwe bron van fouten kan onstaan door een wisselende aanpak.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 11:39 schreef Glimi het volgende:


Hmmmz, dat weet ik niet helemaal maar iets zegt me dat dit met function pointers moet gebeuren, en die hebben we niet in Java. (mwoah, owkay die willen we niet gebruiken, maar reflection hebben we wel).
Delegates (ook wel functie-pointers op een OO manier genoemd) in C#, en functie-pointers in Delphi idd.
Kun je er anders iets meer over uitleggen, of me een urltje geven met wat info daarover :?
Ik zal ff een URL opzoeken.
http://www.c-sharpcorner.com/Code/2002/Mar/EventHandlingInNetUsingCSDD001.asp

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op vrijdag 05 juli 2002 11:39 schreef Glimi het volgende:

[..]

Hmmmz, dat weet ik niet helemaal maar iets zegt me dat dit met function pointers moet gebeuren, en die hebben we niet in Java. (mwoah, owkay die willen we niet gebruiken, maar reflection hebben we wel).

Kun je er anders iets meer over uitleggen, of me een urltje geven met wat info daarover :?
Strategy design pattern ;) Java heeft verder geen function pointers, maar daar is wel met een oo omweg aan te komen. Zie onderstaande voorbeeld (dit is strategy design pattern).
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface Function{
   public int calc(int a, int b);
}

public class Add implements Function{
   public int calc(int a, int b){
    return a+b;
   }
}

public class Mul implements Function{
   public int calc(int a, int b){
    return a*b;
   }
}

public class TwoGetallen{
   int a;
   int b;

   public int calc(Function function){
     return function.calc(a,b);
   }
}

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Op vrijdag 05 juli 2002 11:47 schreef Alarmnummer het volgende:


Strategy design pattern ;) Java heeft verder geen function pointers, maar daar is wel met een oo omweg aan te komen. Zie onderstaande voorbeeld (dit is strategy design pattern).
Hebben we hem weer met z'n patterns ;)
Echter Java heeft wel degelijk function pointers. Kijk maar eens naar de reflection classes. Je hebt hier een class function, waarin je een functie kan stoppen. Deze is later te invoken (naar ik dacht via een proxy class)
Het kan dus wel, maar het is er niet voor ontworpen, en zo moet je ze dus ook niet gebruiken.

Via het patroon wat je geeft, kun je inderdaad (naar mijn inziens netjes!) een fucntie dynamisch aanroepen. Echter deze functie is wel helemaal voor gedefinieerd naar gelang welke eigenschappen ie moet hebben dmv de interface. Hierdoor neem je imho het grootste nadeel van function pointers ook weg, niet weten wat voor een vlees je in de kuip hebt. Kan de doorgegeven functie de parameters wel aan ed. Dmv de interface heb je dit al allemaal vastgelegd :)

Thnx weer wat geleerd :P

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

[offtopic]
Het probleem zit hem in het feit dat java geen hogere orde functies heeft en daarom een functie niet mee kan nemen als argument. (Eventueel wel via de reflection api). Maar in haskell kan je bv zoiets doen.
code:
1
2
3
4
5
select::[a]->(a->Bool)->[a]
select [] _ = []
select [x:xs] f 
          | f x = [x:select xs f]
          | Otherwise = select xs f

Je kan nu aan een deze select functie een lijst van het type a mee geven en een functie die een a als argument type heeft, en een bool terug stuurt. Nu wordt op ieder element van de lijst die functie uitgevoerd en alle elementen die voldoen die staan dan in het resultaat.

In haskell zijn functies gewoon first class citizens, en je kan ze gewoon zien als een waarde (operand dus).

ps: haskell is onder voorbehoud ;)

Verwijderd

Op vrijdag 05 juli 2002 11:26 schreef whoami het volgende:
[..]
Ik vind dat uw reactie niet op een hoog IQ duidt. :(
chill . .. het is vrijdag B-)

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 13:50 schreef Skizmo het volgende:

[..]

chill . .. het is vrijdag B-)
Neen, ik chill niet. Dit is trouwens alweer een OT - reply.

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

[ontopic]
Het kan ook heel veel helpen om de juiste taal te kiezen. Als je bv java gaat vergelijken met een pointer taal zoals c of c++ dan kan je gewoon veel minder fout doen. En daarnaast is garbage collection ook uitermate handig omdat je dus niet zo snel zit met memory leaks ed.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 14:09 schreef Alarmnummer het volgende:
[ontopic]
Het kan ook heel veel helpen om de juiste taal te kiezen. Als je bv java gaat vergelijken met een pointer taal zoals c of c++ dan kan je gewoon veel minder fout doen. En daarnaast is garbage collection ook uitermate handig omdat je dus niet zo snel zit met memory leaks ed.
Daar ga ik maar gedeeltelijk mee akkoord.
Java en C# zijn natuurlijk wel talen die 'strenger' zijn dan C of C++ en daardoor kunnen er misschien wel minder snel foutjes in sluipen, maar het is toch nog steeds de taak van de programmeur om de taal goed te gebruiken/net te programmeren en op te letten zodat fouten vermeden worden.

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op vrijdag 05 juli 2002 14:16 schreef whoami het volgende:

[..]

Daar ga ik maar gedeeltelijk mee akkoord.
Java en C# zijn natuurlijk wel talen die 'strenger' zijn dan C of C++ en daardoor kunnen er misschien wel minder snel foutjes in sluipen, maar het is toch nog steeds de taak van de programmeur om de taal goed te gebruiken/net te programmeren en op te letten zodat fouten vermeden worden.
Een taal is inderdaad niets zonder een goeie programmeur, en zelfs de beste taal kan verneukt worden door een slechte programmeur. Maar uit eigen ervaring weet ik dat het schrijven van pascal/c software veel foutgevoeliger is dan dat van java. Een java programma die knalt eruit met eventueel een stack trace en een c/pascal programma die pruttelt fijn verder en misschien krijg je een vastloper, misschien ook niet.

Ik denk als je 2 programmeurs die evenveel kennis bezitten neemt. En 1 programeur die progt in zoiets al java of c# en de andere die progt in c,c++. Dat die 1e veel eerder een goed functioneerend product hebt omdat je veel sneller ziet wat er fout gaat, en omdat de talen veel strenger zijn.

Maar je hebt dus en een goeie programmeur nodig, en een goeie taal.

  • droeftoeter
  • Registratie: Mei 2002
  • Laatst online: 19-06-2025
Op vrijdag 05 juli 2002 10:12 schreef Gerco het volgende:

[..]

Juist niet.. bij het testen zul je waarschijnlijk waardes invullen die in je verwachtingspatroon vallen en een paar erbuiten. Geef je het programma aan een tester (lees: leek), zal die vanalles doen en ALS er een fout inzit komt 'ie naar voren.

Persoonlijk ken ik zo'n leek (die weet nog niet eens hoe MSN werkt, nou als je DAT niet kan begrijpen?) en die doet altijd de meest vreemde dingen onder de noemer van: "nou ik deed gewoon dat". Dingen waar je zelf nooit op zou komen om te testen.

Ik ben van mening dat de beste tests nog altijd NIET door de programmeur zelf gedaan moeten worden. Als je het zelf getest hebt, laat je het dus nog door iemand anders testen.
Klopt wat je zegt, maar in het geval van 'defensief' programmeren zorg ik ervoor dat user input gespiegeld wordt tegen geldige waardes. Valt de input hierbuiten dan zal dit worden afgevangen. Op deze manier zal ik dus zelf in staat zijn de functies te testen.

Na 'release' zal het geheel uiteraard worden getest door testers/gebruikers, ik sprak in eerste instantie over de ontwikkelingsfase van m'n 'defensieve' code.

  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

Op vrijdag 05 juli 2002 14:16 schreef whoami het volgende:

[..]

Daar ga ik maar gedeeltelijk mee akkoord.
Java en C# zijn natuurlijk wel talen die 'strenger' zijn dan C of C++ en daardoor kunnen er misschien wel minder snel foutjes in sluipen, maar het is toch nog steeds de taak van de programmeur om de taal goed te gebruiken/net te programmeren en op te letten zodat fouten vermeden worden.
Je hebt volgens mij gelijk met je stelling dat het de verantwoordelijkheid van de programmeur is om fouten te vermijden. Memory leaks in Java zijn over het algemeen wat subtieler dan de problemen die je op dat gebied tegenkomt als je C/C++ gebruikt. Automatische garbage collection is natuurlijk een mooi hulpmiddel, maar een programmeur moet er wel voor zorgen dat de GC ook de kans krijgt om z'n werk goed te doen.

Klassieke fouten zijn natuurlijk het eindeloos vasthouden van verwijzingen in een object dat bedoeld is om caching te doen. Het vervelende van dit soort fouten is meestal dat je ze niet meteen merkt, maar pas na een paar dagen draaien. Met server applicaties kan dat vervelende consequenties hebben.

Maar defensief programmeren houdt voor mij eigenlijk in dat je de buitenwereld gewoon niet mag vertrouwen. Een connectie naar een database kan het eerst wel goed doen, maar als de database onderuit gaat moet de applicatie daar wel goed mee om kunnen gaan. Dat vraagt inderdaad veel aandacht voor details.

With the light in our eyes, it's hard to see.


  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op vrijdag 05 juli 2002 15:20 schreef Bobco het volgende:

Maar defensief programmeren houdt voor mij eigenlijk in dat je de buitenwereld gewoon niet mag vertrouwen. Een connectie naar een database kan het eerst wel goed doen, maar als de database onderuit gaat moet de applicatie daar wel goed mee om kunnen gaan. Dat vraagt inderdaad veel aandacht voor details.
Dat bedoel ik. :)
En daarom de vraag, wat doe je eraan?

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op vrijdag 05 juli 2002 15:21 schreef whoami het volgende:

[..]

Dat bedoel ik. :)
En daarom de vraag, wat doe je eraan?
Voornamelijk om eerst te onderzoeken welke situaties er allemaal zijn. En dan voor iedere situatie een passende oplossing te maken. Vooral de eeste wordt vaak vergeten (en daarmee dus ook de 2e).

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op vrijdag 05 juli 2002 15:19 schreef droeftoeter het volgende:

[..]

Klopt wat je zegt, maar in het geval van 'defensief' programmeren zorg ik ervoor dat user input gespiegeld wordt tegen geldige waardes. Valt de input hierbuiten dan zal dit worden afgevangen. Op deze manier zal ik dus zelf in staat zijn de functies te testen.
Het probleem zit hem bij mij meestal in gebruikers interfaces, omdat je daar niet echt een sequentieel programma verloop hebt omdat die gekke gebruikers overal op lopen te drukken.

Verwijderd

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* ASSERT.H v1.1
 * Copyright (c) 1979 by Macrohard.
 *
 * No part of this code may be used or published in any way without proir written consent
 * from the Macrohard board of directors (Gill Bates, Gill Bates' mother and the Allmighty).
 *
 * v1.0 1979-01-08 Gill Bates  First and final version.
 * v1.1 1979-12-25 Gill Bates  User complaint: put in different assert for releases
 */

#ifndef __ASSERT_H
#define __ASSERT_H 1

#ifdef ASSERT
#undef ASSERT
#endif

#ifdef DEBUG
#define ASSERT(x) (fputs(\
  "Sucker! The best defence is a good offence!\
  Ship your code, let the user debug it!\n",\
  stderr); exit(1);)
#else
#define ASSERT(x) (if(!(x)) {\
  fputs("USER INPUT ERROR!\n", stderr);\
  exit(1); })
#endif

#endif

Verwijderd

offtopic:
Prachtig onderwerp! Helaas is mijn ervaring dat bij veel programmeurs in commerciele omgevingen dit een onbekend begrip lijkt te zijn, veelal ook omdat het simpelweg tijd kost om, als je zo werkt, een product werkend te krijgen. Als je goed bent zal je meestal weer veel tijd in de test & debug fase terugwinnen, maar toch is de druk vaak te hoog om door dat argument verleidt te worden.


Defensief programmeren is voor mij:
1) get / set methods met private variables
2) methods / functions nooit te groot / veel functionaliteit te laten bevatten
3) documentatie
4) inputwaardes controleren
5) goede foutafhandeling inbouwen
6) outputwaardes garanderen door ze te initialiseren
7) bedenken wat Murphy op zijn allerslechtste dag tot gevolgen zouden kunnen hebben (bijv. database down, maar ook connectie stuk, waardoor de database niet eens kan vertellen dat die down is.
8) randvoorwaardes checken
9) goede code layout
etc.

Eerlijk gezegd neem ik ook weleens shortcuts, maar commerciele afwegingen zijn vaak een factor daarin, die ik niet waardeer maar wel respecteer.

Overigens werd er een discussie gevoerd over testen, waar ik nog iets aan wil toevoegen.

Er is een verschil technisch testen (kijken of iets werkt) en functioneel testen (kijken of de functionaliteit naar verwachtig is). Bij technisch testen zullen de programmeurs het zelf kunnen doen, hoewel het ook zinvol is om een collega ernaar te laten kijken (code review) en ook om hem/haar uit te dagen fouten te ontdekken (mijn opmerking: "En probeer daar maar eens wat gaten in te schieten!").

Ook moet de gedachte dat testen de manier is om de kwaliteit te bereiken is in de vuilnisbak gegooid worden. Als namelijk in die fase nog veel fouten worden gevonden, technisch danwel functioneel, dan kan ik je verzekeren dat het project mislukt is. Helaas zijn er bij veel niet-technische mensen in de commerciele wereld nog grote misvattingen over.

  • Sponge
  • Registratie: Januari 2002
  • Laatst online: 15-08 11:47

Sponge

Serious Game Developer

Na aanleiding van die VB thread over 3 clients, hier toch maar even gekomen :)

Al mijn programma's zijn meestal erg defensief gemaakt... Vooral als het om Quadrant Wars gaat, wil ik zeker zijn dat alles goed loopt, want spelers zijn toch niet zo tolerant als het om bugs gaat. Er zijn echter altijd wel dingen die je uiteindelijk vergeet... en die een gebruiker maar al te snel wel vindt :)

Maar er zijn altijd dingen die niet van te voren "defensief" te programmeren zijn, door ontwetendheid. Zelf heb ik eens iets meegemaakt met komma's en punten als decimaal scheidings teken (100,000.000 of 100.000,000").. |:( en daar gaat mijn code dan wel eens de mist in. Maar gelukkig heb ik niet veel van deze dingenmeegemaakt :)


Defensief programmeren is een manier om bugs/problemen te voorkomen.. en daarom ben ik er ook een voorstander van


(voorkomen is beter dan genezen! :Y))

Verwijderd

2) methods / functions nooit te groot / veel functionaliteit te laten bevatten
Dat is sowiezo een goede. Ik zie wel eens mensen een functie/procedure/whatever schrijven van ettelijke pagina's lang (op A4 uitgeprint). Volgens mij ben je dan verkeerd bezig.
3) documentatie
Wordt vaak onderschat. Is natuurlijk ook strontvervelend om te doen (coden is leuker) maar het kan je later erg veel tijd besparen..
9) goede code layout
Is ook zo'n punt. Identatie van code zuigt bv. vaak. Meestal programmeer ik in delphi, soms kom ik dan dit soort code tegen:
code:
1
2
if bla then blabla else if bla then bla2 
else bla;

Ook leuk zijn lui die lopen te fucken met begin/end constructies:
code:
1
2
3
4
if bla then begin bla2;bla3 end
else begin
bla3
end

Oftewel totaal onleesbaar. Ikzelf identeer veel en zet altijd de begin op dezelfde plek als de end, zodat je door vanaf de end omhoog te gaan vanzelf bij de bijbehorende begin uitkomt. Voorbeeldje:
code:
1
2
3
4
5
if bla then
  begin
    DoThis;
    DoThat;
  end;

of bij een if-then-else constructie:
code:
1
2
3
4
5
6
7
8
9
10
11
12
if bla then
    begin
    DoThis;
    DoThat;
    end
  else
    begin
    DoSomethingElse;
    If bla2 then
      DoDatOokMaar;
    end;    
DoDitNogeven;

Is een stuk leesbaarder imo, en maakt de kans op fouten doordat je een end op de verkeerde plek hebt staan ofzo.

Zelfde geld voor foutafhandeling. Ik zie heel vaak zaken als:
code:
1
2
3
4
5
Try
  Database1.Connect;
Except
  on E:Exception do ShowMessage('kan niet inloggen');
end;

oid. Ik persoonlijk vind dat echt ENORM zuigen. De eingebruiker krijgt op deze manier altijd dezelfde foutmelding terwijl de oorzaak van de fout anders kan zijn. De clou is dat je de volledige foutmelding, inclusief alle beschikbare info moet geven.

Wat betreft testen.. eerst kijken of je applicatie voldoet aan het functioneel ontwerp, daarna een testplan opstellen waarbij je definieert wat je gaat doen. Welke input gebruik je, wat verwacht je aan output. Dan testen en de eventuele verschillen noteren.

En natuurlijk de aap-test, 'what does this button do?'. bv. je PC gewoon uitzetten midden in een omvangrijke database-transactie (helft vd. records verwerkt bv) en dan kijken of e.e.a. nog werkt. Soms kan het handig zijn alle muterende queries via een queue af te handelen, of te loggen. Dan kun je nog iets als het misgaat.

Als laatste krijg je dan de gebruikers-acceptatie testen. Kijken wat ze er van vinden.

Goed testen is een van de belangrijkste zaken imho

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op zaterdag 06 juli 2002 22:07 schreef hezik het volgende:


Dat is sowiezo een goede. Ik zie wel eens mensen een functie/procedure/whatever schrijven van ettelijke pagina's lang (op A4 uitgeprint). Volgens mij ben je dan verkeerd bezig.
In een functie of een procedure groepeer je statements die logisch bij elkaar horen. Als dat dan een lange functie wordt, dan is het zo...
Je gaat toch niet op basis van lengte uw source gaan onderverdelen in functies/procedures?

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 07 juli 2002 09:30 schreef whoami het volgende:

[..]

In een functie of een procedure groepeer je statements die logisch bij elkaar horen. Als dat dan een lange functie wordt, dan is het zo...
Je gaat toch niet op basis van lengte uw source gaan onderverdelen in functies/procedures?
Als een procedure/methode mij te lang wordt, dan ga ik er wel kleinere methodes van maken. Dit gaat met java vrij eenvoudig als je de juiste IDE daar voor hebt, dmv van de ingebouwde refactor optie:'extract method'. Het gebeurd niet vaak, dat ik een procedure hebt van langer dan een pagina, de meeste procedures zijn max 20 regels denk ik.

Verwijderd

Op vrijdag 05 juli 2002 11:47 schreef Alarmnummer het volgende:
Strategy design pattern ;) Java heeft verder geen function pointers, maar daar is wel met een oo omweg aan te komen. Zie onderstaande voorbeeld (dit is strategy design pattern).
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface Function{
   public int calc(int a, int b);
}

public class Add implements Function{
   public int calc(int a, int b){
    return a+b;
   }
}

public class Mul implements Function{
   public int calc(int a, int b){
    return a*b;
   }
}

public class TwoGetallen{
   int a;
   int b;

   public int calc(Function function){
     return function.calc(a,b);
   }
}
Ik vind dit een zeer weirde taalconstructie. Delegates vind ik ook niet echt fraai op zich, maar daar valt nog iets voor te zeggen, dit vind ik echter vrij weird. Kan komen omdat het zondagochtend is, maar toch...

Oh, en 'TwoGetallen' hehe :) Doet me denken aan dat hybride commentaar dat ik nog wel eens plag te tikken: "Here we store the Debiteuren" hehe

Verwijderd

Op zondag 07 juli 2002 09:30 schreef whoami het volgende:
Je gaat toch niet op basis van lengte uw source gaan onderverdelen in functies/procedures?
Het record dat ik zelf ben tegengekomen (gelukkig niet door mij gemaakt :) ) is ruim 5 A4'tjes... Dat is dus één functie!
Dit is natuurlijk extreem, maar door het onderverdelen van code in functies, wordt je code overzichtelijker en beheersbaarder. Samen met een goede foutafhandeling, kunnen bugs zo sneller worden opgespoord. Dat is dus voor mij defensief programmeren.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 07 juli 2002 11:27 schreef Otis het volgende:

[..]

Ik vind dit een zeer weirde taalconstructie. Delegates vind ik ook niet echt fraai op zich, maar daar valt nog iets voor te zeggen, dit vind ik echter vrij weird. Kan komen omdat het zondagochtend is, maar toch...

Oh, en 'TwoGetallen' hehe :) Doet me denken aan dat hybride commentaar dat ik nog wel eens plag te tikken: "Here we store the Debiteuren" hehe
Ik vind het wel een aardige contructie. Aangezien je in java geen functie pointers hebt (je kan in ieder geval geen functie meegeven als argument) is dit toch een hele fijne oplossing. Ik gebruik trouwens behoorlijk veel het visitor design pattern, wat inwezen weer een uitbreiding is van de strategy design pattern. Het voordeel aan de visitor design pattern is dat je heel makkelijk nieuwe functionaliteit kan toevoegen aan een classe hierarchie.

Hierdoor blijven je classes veel schonen (ze bevatten alleen de logica om zich consistent te houden, en verder kunnen ze niets) en voor ieder stuk functionaliteit maak je er dus een visitor bij, waarin in 1 source file, alle logica voor dat stuk functionaliteit geplaatst is.

Verwijderd

Defensief programmeren is IMHO verder een zeer vage term. Dit komt omdat er bv geen consensus is wat beter is voor de kwaliteit van de programmatuur, bv de discussie omtrent 1 exit point vs multi exitpoints, wel/geen GC, wel/geen pointers, wel/geen exteme programming, wel/geen E/R Model maar abstractere datamodellering enz.

Ik ben bv een falikant tegenstander van de one-exitpoint regel, anderen vinden dat DE manier om kwaliteit te waarborgen in hun code. (ik test bv eerst input, klopt die niet of falen de tests door een andere reden, dan hoor je niet in de functie te zijn dus exit de functie).

Op een hoger niveau, dus niet echt implementatie-technisch, zijn er ook veel bugs te vermijden door:
1) een goed functioneel ontwerp ZONDER technische details of gebaseerd op technische aannames
2) een goed technisch ontwerp dat volledig verwoord: alle ontwerpbeslissingen die genomen zijn omtrent de implementatie van een subset van 1)
3) toetsing van DELEN van de implementatie (bv functies of componenten) aan de hand van 2) en daarna toetsend of 1) gehaald wordt met de technische implementatie van 2).

Veel code is nl. niet gebouwd met het implementeren van een afgebakend stukje functionaliteit in het achterhoofd, maar men bouwt vaak OF te veel 'want dat is wellicht later nuttig' (terwijl het uitgebreide functionele ontwerp dat niet voorziet, dus de functionaliteit die buiten de subset val van 2) is niet functionaliteit die dat soort implementaties rechtvaardigd) en dus meer kans op fouten, OF men houdt weer te weinig rekening met de functionaliteit die niet is verwoord in 2) maar wel in 1). Ik hoorde laatst het spreekwoord "Als je gevraagd wordt een Opel te bouwen, moet je geen Ferrari leveren". Waarheid als een koe: veelal is de capaciteit/kennis/ervaring/kunde toereikend voor een Opel maar niet voor een Ferrari.

Verwijderd

Op zondag 07 juli 2002 11:40 schreef Alarmnummer het volgende:
[..]
Ik vind het wel een aardige contructie. Aangezien je in java geen functie pointers hebt (je kan in ieder geval geen functie meegeven als argument) is dit toch een hele fijne oplossing.
Het weirde eraan vind ik dat je een class moet creeeren voor 1 method, ik werk met OO heel erg data-gericht, dus data met daarop methods, en daarnaast inheritance voor het verkleinen van de hoeveelheid code door aan elkaar gerelateerde data in een hierarchie te plaatsen (en dus de methods). Het is dan voor mij een beetje een rare constructie dat je om functies te gebruiken aparte classes moet aanmaken :)
Ik gebruik trouwens behoorlijk veel het visitor design pattern, wat inwezen weer een uitbreiding is van de strategy design pattern. Het voordeel aan de visitor design pattern is dat je heel makkelijk nieuwe functionaliteit kan toevoegen aan een classe hierarchie.

Hierdoor blijven je classes veel schonen (ze bevatten alleen de logica om zich consistent te houden, en verder kunnen ze niets) en voor ieder stuk functionaliteit maak je er dus een visitor bij, waarin in 1 source file, alle logica voor dat stuk functionaliteit geplaatst is.
Ik kende die namen van de design patterns niet dus heb ik ze maar even opgezocht:
Strategy design pattern:
http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/StrategyPattern.htm
Iets wat ik dus niet zal gebruiken, omdat inheritance voor mij semantisch gezien de beste manier is voor het implementeren van programmatuur dat aangrijpt op meerdere classes die aan elkaar gerelateerd zijn omdat de data in die classes aan elkaar gerelateerd is (dus de is-a methodiek)

Visitor design pattern:
http://exciton.cs.oberlin.edu/javaresources/DesignPatterns/VisitorPattern.htm
Ik moest hier echt een paar keer naar kijken, maar het is inderdaad vrij slim gedaan.

Allebei wel zaken waar ik niet 1 2 3 aan zou denken eerlijk gezegd, maar in sommige gevallen wel handig. Het bezwaar dat ik er tegen heb, en wat de 'static' inheritance methode wel levert, is de leesbaarheid van de code (als ik het goed begrijp, en na een aantal keren met mn duffe hoofd de tekstoverlezende kan ik wel indenken dat je er solide software mee kunt bouwen). De lezer, dus de mens, moet onthouden welk algo gepassed wordt naar het object, dus tijdens het lezen, en bv het nakijken van de code, kun je dus de bugs over het hoofd zien dat je het verkeerde algo passed. Maar een geoefende programmeur zal dit ongetwijfeld wel correct doen, het lijkt mij alleen een stukje complexer worden tijdens het lezen van de sourcecode (en IMHO dan foutgevoeliger juist). Generics maken IMHO het visitor design pattern voor een deel overbodig, heb ik dat goed?

In .NET heb je delegates en ze zorgen voor de implementatie van, als ik het goed kan beoordelen, het strategic design pattern. Delegates vind ik ook een weirde taalconstructie, daar het imho 'procedureel oriented' programming mogelijk maakt in een 'data oriented' programming paradigma, maar dan op een imho gekunstelde wijze: de C/C++ hybride is dan IMHO te prefereren, omdat de code er simpeler van wordt, iets wat een vereiste is IMHO voor een solide stuk code dat 1) makkelijk aantoonbaar correct is en 2) correct te houden is ivm toekomstige uitbreidingen.

(alhoewel in dat laatste geval je mbv dat visitor design pattern een heel eind komt, maar je ipv het visitor design pattern ook kunt kiezen voor een baseclass met alle common code en daarvandaan je classes deriven (is niet in alle gevallen toereikend maar wel in vele))

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 07 juli 2002 12:03 schreef Otis het volgende:

[..]

Het weirde eraan vind ik dat je een class moet creeeren voor 1 method, ik werk met OO heel erg data-gericht, dus data met daarop methods, en daarnaast inheritance voor het verkleinen van de hoeveelheid code door aan elkaar gerelateerde data in een hierarchie te plaatsen (en dus de methods). Het is dan voor mij een beetje een rare constructie dat je om functies te gebruiken aparte classes moet aanmaken :)
Eigelijk voelt het heel natuurlijk aan, alhoewel het in het begin inderdaad vreemd is. Maar ik beschouw mijn hierarchie nu als een data dragen geheel, en het heeft zelf geen functionaliteit meer in zich (afgezien van consistent houden). Hierdoor blijven mijn classes veel schoner, en alle functionaliteit bv: bepaal totaal lengte hout, kan mbv een visitor worden bepaald.

Doordat je gebruikt maakt van zo`n visitor heb je niet bij ieder object een 'calcTotaalHoeveelheidHout' staan en later: 'calcTotaalOpp' 'calcInhoud' 'calcGewicht' etc methodes. Vooral als er meer functionaliteit in moet, dan kan zo`n hierarchie echt een drama worden. Ik heb vorig jaar een stuk software geschreven voor een timmerfabriek en ik heb het op de ouderwetse manier gehaad. Op den duur zie je door het bomen het bos niet meer, maar ik ga hem deze week even te grazen nemen.

Het visitor design pattern wordt geintroduceerd, en ik ga nu gebruik maken van hele simpele model objecten (string, ing, bool etc) met ingebouwde controllers (en verhindering van memory leaks door een speciale constructie!!!) en events om standaard gui objecten (labels,textfields ed) daarop aan te sluiten. (ben op dit moment nog aan het experimenteren ermee, dus wat hieronder staat is alleen een probeersel).
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Persoon{
    
    private StringModel<Persoon> _voornaamM = new StringModel<Persoon>(this);
    private StringModel<Persoon> _achternaamM = new StringModel<Persoon>(this);
    private StringModel<Persoon> _woonPlaatsM = new StringModel<Persoon>(this);
    
    public Persoon(String voornaam,String achternaam,String woonplaats){
        _voornaamM.setValue(voornaam);
        _achternaamM.setValue(achternaam);
        _woonPlaatsM.setValue(woonplaats);
    }
        
    public StringModel<Persoon> getAchternaamM(){
        return _achternaamM;
    }
    
    public StringModel<Persoon> getVoornaamM(){
        return _voornaamM;
    }
    
    public StringModel<Persoon> getWoonplaatsM(){
        return _woonPlaatsM;
    }
}

aansluiten:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestPanel extends JPanel
{
    private Persoon _persoon = new Persoon("jan","bakker","slochter");
    
    public TestPanel(){
        super(new BorderLayout());
        
        add(new StringLabel(_persoon.getVoornaamM()),BorderLayout.NORTH);
        add(new StringTextField(_persoon.getAchternaamM()),BorderLayout.CENTER);
        add(new StringLabel(_persoon.getAchternaamM()),BorderLayout.SOUTH);
    }
    
    public static void main(String[] args){
        JFrame frame = new JFrame();
        frame.setContentPane(new TestPanel());
        frame.setSize(300,300);
        frame.setVisible(true);
    }
}

Hierdoor hoef ik geen gui code meer aan te sluiten op een controller, en kan dus dus veel handiger werken.
Visitor design pattern:
http://exciton.cs.oberlin.edu/javaresources/DesignPatterns/VisitorPattern.htm
Ik moest hier echt een paar keer naar kijken, maar het is inderdaad vrij slim gedaan.

Allebei wel zaken waar ik niet 1 2 3 aan zou denken eerlijk gezegd, maar in sommige gevallen wel handig. Het bezwaar dat ik er tegen heb, en wat de 'static' inheritance methode wel levert, is de leesbaarheid van de code (als ik het goed begrijp, en na een aantal keren met mn duffe hoofd de tekstoverlezende kan ik wel indenken dat je er solide software mee kunt bouwen). De lezer, dus de mens, moet onthouden welk algo gepassed wordt naar het object, dus tijdens het lezen, en bv het nakijken van de code, kun je dus de bugs over het hoofd zien dat je het verkeerde algo passed. Maar een geoefende programmeur zal dit ongetwijfeld wel correct doen, het lijkt mij alleen een stukje complexer worden tijdens het lezen van de sourcecode (en IMHO dan foutgevoeliger juist).
De source code wordt juist niet foutgevoeliger. Je moet bij iedere class in je hierarchie maar 1 methode schrijven:
code:
1
2
3
4
5
6
public void accepts(FruitVisitor visitor){
    if(visitor == null){
     ... foutmelding
    }
    visitor.visitPeer(this);
}

Dit kan je eigelijk niet fout doen, verder kun je nu al je handige functies uit de hierarchie gaan verwijderen. (Die hierarchie moet echt behoorlijk dom worden). De hierarchie is nu geschikt gemaakt voor het ontvangen van een visitor.

implementatie van een visitor
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class FruitOpeter implements FruitVisitor{
    public void visitBanaan(Banaan fruit){
      fruit.haalBanaaneSchilEraf();
    fruit.eet();
    }

    public void visitPeer(Peer fruit){
    fruit.eet();
    }

    public void visitSinasAppel(SinasAppel fruit){
    fruit.schilSinasappel();
    fruit.eet();
    }
}

Nu heb je dus in 1 bestand alle functionaliteit mbt het eten van fruit, ipv dat het over een hele hierarchie ligt verspreid. Eigelijk kan je dit wel een beetje onder de noemer AOP (Aspect Oriented Programming) gooien, omdat je iedere keer een bepaald aspect van het probleem gaat behandelen.
Generics maken IMHO het visitor design pattern voor een deel overbodig, heb ik dat goed?
Je kan met het visitor design pattern nog veel meer doen. De kracht van het visitor design pattern is dat je achteraf functionaliteit kan toevoegen aan een bepaalde object hierarchie, maar ook dat je dus allerlei traversal strategieen erop kan uitvoeren. Je hoeft dus zelf niet meer door een object hierarchie te gaan wandelen, vb: stel dat ik een expressie wil afdrukken, dan zou ik deze visitor kunnen maken.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PrintVisitor extends ExprVisitor{
    public void visitVariable(Variable var){
        System.out.prinltn(var.getName());
    }

    public void visitInteger(Integer integer){
        System.out.println(integer.getValue());
    }

    public void visitAdd(AddOperator addOperator){
        System.out.println("+");
    }

    public void visitSub(SubOperator subOperator){
        System.out.println("-");
    }
}

En ik zou hem als volgt kunnen afdrukken.

expression.accepts(new InfixVisitor(new PrintVisitor());
expression.accepts(new PostFixVisitor(new PrintVisitor());
expression.accepts(new PreFixVisitor(new PrintVisitor());

Je ziet nu dat je ook een bepaalde classes hebt die verantwoordelijk is voor het bewandelen van die hierarchie, namelijk Infix,Prefix en PostFix visitor. Deze 'guides' kan je iedere keer hergebruiken, en dat maakt je code ook een stug bugvrijer.

Het visitor design pattern is eerlijk gezegd de beste design pattern die ik ben tegen gekomen, maar uit de voorbeelden in de boeken komt hij totaal niet tot zijn recht. Je kan er zoveel mee doen. Er is ook een generieke traversal library JJTraveler waarmee je zelfs die guides niet meer hoeft te maken.

Verwijderd

Ik ga niet geheel op je uitstekende verhaal in, dat zou teveel OT voeren, ik wil wel op een klein dingetje reageren:
Op zondag 07 juli 2002 12:43 schreef Alarmnummer het volgende:
[uitstekende uitleg]
De source code wordt juist niet foutgevoeliger. Je moet bij iedere class in je hierarchie maar 1 methode schrijven:
code:
1
2
3
4
5
6
public void accepts(FruitVisitor visitor){
    if(visitor == null){
     ... foutmelding
    }
    visitor.visitPeer(this);
}

Dit kan je eigelijk niet fout doen, verder kun je nu al je handige functies uit de hierarchie gaan verwijderen. (Die hierarchie moet echt behoorlijk dom worden). De hierarchie is nu geschikt gemaakt voor het ontvangen van een visitor.

implementatie van een visitor
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class FruitOpeter implements FruitVisitor{
    public void visitBanaan(Banaan fruit){
      fruit.haalBanaaneSchilEraf();
    fruit.eet();
    }

    public void visitPeer(Peer fruit){
    fruit.eet();
    }

    public void visitSinasAppel(SinasAppel fruit){
    fruit.schilSinasappel();
    fruit.eet();
    }
}

Nu heb je dus in 1 bestand alle functionaliteit mbt het eten van fruit, ipv dat het over een hele hierarchie ligt verspreid. Eigelijk kan je dit wel een beetje onder de noemer AOP (Aspect Oriented Programming) gooien, omdat je iedere keer een bepaald aspect van het probleem gaat behandelen.
Maar, wat is het voordeel van al deze functionaliteit in 1 file te stoppen tov al deze functionaliteit in de baseclass te stoppen? IMHO maakt het niet zoveel uit, behalve wellicht dat je de functionaliteit ook op een andere objecthierarchie kunt toepassen, maar dan praat je IMHO niet meer over het data-oriented + gerelateerde methods paradigma, maar over een toch meer procedural oriented methode, denk ik.
Je kan met het visitor design pattern nog veel meer doen. De kracht van het visitor design pattern is dat je achteraf functionaliteit kan toevoegen aan een bepaalde object hierarchie, maar ook dat je dus allerlei traversal strategieen erop kan uitvoeren. Je hoeft dus zelf niet meer door een object hierarchie te gaan wandelen.
Misschien te symplistisch gedacht hoor, maar door common functionaliteit in een baseclass te stoppen krijg jetoch hetzelfde, of is dat not-done?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op zondag 07 juli 2002 13:19 schreef Otis het volgende:
Ik ga niet geheel op je uitstekende verhaal in, dat zou teveel OT voeren, ik wil wel op een klein dingetje reageren:
[..]

Maar, wat is het voordeel van al deze functionaliteit in 1 file te stoppen tov al deze functionaliteit in de baseclass te stoppen?
Veel objecten die hebben hun eigen implementatie van een methode, de 'calcVolume' bij een 3d figuren hierarchie. Hierdoor kan je niet meer alle functionaliteit in de bass class stopen. Je kan alleen een abstracte methode maken in de base class 'getVolume' en die in ieder element van die hierarchie gaan implementeren. En nu heb je dus getVolumne in kubus, nog een in bol, nog een in balk, nog een in pyramide. Dus alle volume afhandelingen liggen verspreid over die hierarchie. Als je maar een paar methodes hebt, dan valt dit nog wel mee, maar naarmate er meer methodes inkomen, gaat dit echt een drama worden. Vandaar dat de visitor uitkomst bied. Alle functionaliteit mbv tot volume bepaling zit in 1 bestand:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class VolumeVisitor implements 3DVisitor{
    private double _volume;

    public void visitKubus(Kubus kubus){
        _volume = kubus.lengte*kubus*breedte*kubus*h;
    }

    public void visitBol(Bol bol){
        _volume = 3/4*pi*bol.straal^3;
    }

    public visitPyramide(Pyramide pyramide){
        _volume = 1/3*pyramide.lengte*pyramide*breedte*pyramide.hoofte;
    }
}
IMHO maakt het niet zoveel uit, behalve wellicht dat je de functionaliteit ook op een andere objecthierarchie kunt toepassen, maar dan praat je IMHO niet meer over het data-oriented + gerelateerde methods paradigma, maar over een toch meer procedural oriented methode, denk ik.
Eigelijk is dit het functionele paradigma. Je voert namelijk een functie uit op een bepaalde object (hierarchie).
Misschien te symplistisch gedacht hoor, maar door common functionaliteit in een baseclass te stoppen krijg jetoch hetzelfde, of is dat not-done?
Je verzuipt op den duur in de handige methodes en je verliest het overzicht omdat functionaliteit ligt verspreid over een hele hierarchie van objecten en daar kan je mbv het visitor design pattern vanaf komen. Ik werk er nu een tijdje mee (dik half jaar) en zou niet meer zonder willen en kunnen. Ik denk als je er even mee bezig gaat dat je er zelf ook stapelverliefd op wordt. Zie signature ;) Verder komt de visitor het beste tot zijn recht als je ook weer objecten heb die bestaan uit andere objecten.

Verwijderd

In een functie of een procedure groepeer je statements die logisch bij elkaar horen. Als dat dan een lange functie wordt, dan is het zo...
Je gaat toch niet op basis van lengte uw source gaan onderverdelen in functies/procedures?
Niet pur sang, uiteraard. Echter is het praktisch altijd zo dat als je op een functie/procedure/whatever uitkomt die ERG groot is dat je het zaakje verkeerd hebt opgezet OF dat je teveel 'randfuncties' overgelaten hebt.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het hooffdoel van het Strategy pattern is dat je een klein deel van de functionaliteit van en klasse kunt varieren. Dit varieren gebeurt door middel van de strategie die je meegeeft aan de klasse. Omdat dit de specialisatie is van een stukje functionaliteit van de klasse, komt het vaak een beetje functioneel over, maar een strategie implementatie kan ook best instantie variabelen hebben en deze gebruiken bij een aanroep.

Het Strategy pattern is eigenlijk het typische voorbeeld waar je moet uitkijken met inheritance. Het Strategy pattern lost de specialisatie en variatie van een stukje functionaliteit namelijk op door middel van delegatie: de taak wordt gedelegeerd naar de strategie. Deze specialisatie had ook opgelost kunnen worden door middel van inheritance, maar dit kan grote problemen opleveren: je specialiseert een klein stukje functionaliteit en misschien niet de hoofdrol van de klasse. Hierdoor kan je conflicten krijgen tussen verschillende subklasse en in het slechtste geval zorgt dit voor een heel woud aan specialisatisch van functionaliteit. Bij een toepassing van het Strategy pattern begin je een nieuwe hierarchie, speciaal voor dit stukje functionaliteit. Dit stukje funcionaliteit kan je eventueel goed specialiseren of aanpassen dmv inheritance.

Je kan een Strategy eigenlijk ook zien als een soort configuratie. Met het meegeven van een strategy kan je een klasse configureren met een stukje funcionaliteit. Je komt weleens situaties voor waarin een klassen eigenlijk 2 of 3 algoritmen of aanpakken gebruikt. Deze kan je dan bijvoorbeeld afwisselen met if-condities. Door deze aanpakken om te zetten in een toepassing van het Strategy pattern wordt je code van de hoofdklasse duidelijker en kan je ook makkelijk een andere aanpak gebruiken.

Waarom dan geen delegates? (er even vanuit gaande dat de host-taal delegates/functie-pointers kent). Een Strategy vervult een duidelijker rol. De optelling is natuurlijk maar een heel simpel voorbeeld. In het algemeen kan een strategy klasse veel groter zijn en bijvoorbeeld zelfs werken met instantie-variabelen. Omdat de strategy een duidelijk eigen rol heeft in de applicatie, vind ik dat je er het beste een aparte klasse van kunt maken. Het grote voordeel van deze aanpak is dat je ook nog met inheritance kan werken om gemeenschappelijke functionaliteit over een paar strategien in 1 superklasse te stoppen en om strategien te specialiseren door subklassen te maken.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

bravenboer / alarmnummer: ik snap wat jullie bedoelen, en als iemand die afkomstig is uit de C / procedurele hoek kan ik me het wel voorstellen dat het nuttig kan zijn. Wat ik me alleen wel afvraag is of je omwille van deze designpatterns niet beter toch multiple inheritance zou willen. (de nadelen ervan even daargelaten). Het geheel is dan weer direct in de class ingebed ipv dat het at runtime doorgegeven wordt.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

het verschil in mening zit hem in het feit dat martin en ik het wel oke vinden om niet alle functionaliteit van 1 object in 1 source file te plaatsten en jij vind dit niet oke, omdat je bang bent de interactie tussen objecten niet meer te overzien.

Toevallig kan dit design pattern ons daarmee helpen (scheiding aanbrengen op basis van functionaliteit), maar als je met een ander paradigma bezig gaat zoals AOP dan is dit eigelijk ook standaard gang van zaken (hier kan mbv taalconstructies achteraf functionaleit worden toegevoegd). Hierdoor blijft je source code zelf eenvoudiger, want ieder object behandeld maar 1 aspect van het geheel, alhoewel de totale complexiteit wel toeneemt.

Trouwens is het eigelijk ook object georienteerd programmeren, want je bundelt niet zozeer je data in 1 object, maar je bundelt een stuk gedrag in 1 object. Het is dus een andere manier om er tegen aan te kijken.
Guideline 2. See objects as bundles of behavior, not bundles of data

Ik denk dat je het gewoon eens moet proberen, en vooral bij classes met veel hulp methodes (allerlei calculaties methodes bv) zul je zien dat je op deze manier een stuk fijner kan werken. Ik stond er in het begin ook heel raar tegenaan te kijken, maar dit is voor mij nu eigelijk wel standaard gang van zaken en vind het fijner dan op de klassieke 'alles in 1 object proppen' werkwijze.

Verwijderd

Ik heb zo'n vermoeden dat het 'visitors' verhaaltje in Delphi een hels karwij met interfaces e.d. gaat worden.

De techniek an sich klinkt heel interessant, maar volgens mij voor het gros der projecten niet bruikbaar. Het wordt pas nuttig naarmate je meerdere - en complexere - objecten gebruikt, iets wat voor de meeste simpele applicaties niet nodig is.

Dat is nl. ook defensief programmeren, niet toepassen vanwege het toepassen (of omdat je het leuk vind), maar omdat het nuttig is.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op maandag 08 juli 2002 00:49 schreef hezik het volgende:
Ik heb zo'n vermoeden dat het 'visitors' verhaaltje in Delphi een hels karwij met interfaces e.d. gaat worden.
Ten eerst kan je van die visitor wel een ook wel een class maken als je geen interfaces wilt. En dat kan toch ook niet zo`n groot probleem zijn. En verder moet een object dat overerft van een ander object ook niet zo`n probleem zijn. Jij kan mij niet wijsmaken dat dit veel moeilijkheden op gaat leveren voor een ervaren delphi programmeur.

[verbaasd]
En hoe kun je eigelijk in godsnaam oo programmeren zonder interfaces en overerving?
[/verbaasd]
De techniek an sich klinkt heel interessant, maar volgens mij voor het gros der projecten niet bruikbaar. Het wordt pas nuttig naarmate je meerdere - en complexere - objecten gebruikt, iets wat voor de meeste simpele applicaties niet nodig is.
De techniek is inderdaad super interessant, en ik maak nu altijd gebruik van visitors als ik bepaalde functionaliteit wil toevoegen aan een object hierarchie. En zo gauw je eigelijk gebruik gaat maken van overerving en objecten die weer andere objecten in zich hebben, dan begint het visitor design pattern echt razend interessant te worden.

En dit verkomt ook dat je sourcefiles van meer dan 1000 regels krijgt zoals je bij veel delphi code ziet ;)
Dat is nl. ook defensief programmeren, niet toepassen vanwege het toepassen (of omdat je het leuk vind), maar omdat het nuttig is.
hehe ;) Het visitor design pattern is vast onderdeel in zo`n beetje iedere object hierarchie die ik heb. Je krijgt een uitstekend overzicht van een bepaald stuk functionaliteit ipv dat het verspreid ligt over een lading source files.

Verwijderd

Ten eerst kan je van die visitor wel een ook wel een class maken als je geen interfaces wilt. En dat kan toch ook niet zo`n groot probleem zijn.
Bij nader inzien (het was het einde van een brak weekend gisteren) heb je daarin gelijk :)
[verbaasd]
En hoe kun je eigelijk in godsnaam oo programmeren zonder interfaces en overerving?
[/verbaasd]
Het zal je verbazen hoeveel mensen in delphi bezig zijn zonder zelf specifiek aan OO te doen. Ja natuurlijk, de omgeving is OO en als jij de caption van een labeltje verandert ben je al 'oo-bezig' :)
De techniek is inderdaad super interessant, en ik maak nu altijd gebruik van visitors als ik bepaalde functionaliteit wil toevoegen aan een object hierarchie. En zo gauw je eigelijk gebruik gaat maken van overerving en objecten die weer andere objecten in zich hebben, dan begint het visitor design pattern echt razend interessant te worden.
En dit verkomt ook dat je sourcefiles van meer dan 1000 regels krijgt zoals je bij veel delphi code ziet ;)
Volgens mij heeft dat meer te maken met het feit dat Delphi een heerlijke 'instap-taal' is. Geen verzameling leestekens, maar leesbare code :)

Ik denk dat zuiver het gebruik van OO al veel Delphi code zou kunnen helpen. Overigens zie ik niet in hoe visitors het aantal regels code terugbrengen, immers je moet de betreffende functie nog steeds per class definieren, toch?
hehe ;) Het visitor design pattern is vast onderdeel in zo`n beetje iedere object hierarchie die ik heb. Je krijgt een uitstekend overzicht van een bepaald stuk functionaliteit ipv dat het verspreid ligt over een lading source files.
Tsja, het is maar hoe je er tegenaan kijkt. Als 1 van de voordelen van OO werd altijd genoemd dat je een complete set van gegevens met de bij die gegevens behorende bewerkingen in 1 object hebt zitten (encapsulation). 'vanuit de gegevens bekeken' lijkt het visitors concept mij dan ook vloeken in de kerk, immers je gaat de nadruk meer leggen op functionaliteit, en haalt de functionaliteit juist _weg_ bij de gegevens.

Zoals het op mij overkomt is het meer een manier van rangschikken van je code. De code zelf verandert er niet of nauwelijks door.. maar nu ga je me ongetwijfeld vertellen dat ik het mis heb :)

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Op maandag 08 juli 2002 10:24 schreef hezik het volgende:


Zoals het op mij overkomt is het meer een manier van rangschikken van je code. De code zelf verandert er niet of nauwelijks door.. maar nu ga je me ongetwijfeld vertellen dat ik het mis heb :)
Hmm, daar ga ik ook niet echt mee akkoord. OO is eerder een manier van denken.
Je 'rangschikt' je code wel in logische units zoals jij het zegt, maar het vergt toch een heel andere denkwijze.

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op maandag 08 juli 2002 10:24 schreef hezik het volgende:

Volgens mij heeft dat meer te maken met het feit dat Delphi een heerlijke 'instap-taal' is. Geen verzameling leestekens, maar leesbare code :)
Ik heb een tijdje in delphi moeten proggen en ik ben vroeger lang geprogrammeerd in tp. De syntax van pascal is heel aardig (voor een systeem waar we nu mee bezig zijn is er ook een taal ontwikkeld die veel elementen van pascal heeft, dus begin,end ipv { }. Maar voor mezelf heb ik toch liever een abstractere syntax zoals die van java. Ik zal er maar geen c of c++ bij zetten wat dat me toch een potje onleesbaar zijn :) (ligt trouwens ok heel erg aan de programmeur).
Ik denk dat zuiver het gebruik van OO al veel Delphi code zou kunnen helpen. Overigens zie ik niet in hoe visitors het aantal regels code terugbrengen, immers je moet de betreffende functie nog steeds per class definieren, toch?
De complexiteit van je code begint af te nemen door:
-geen verspreiding meer van een bepaald stuk functionaliteit. Stel dat je een auto hebt, die weer bestaat uit onderdelen (en die kunnen op hun beurt ook weer uit onderdelen bestaan). Dan komt niet bij ieder onderdeel te staan de methode: getAllBolts (als he het op een oo manier zou aanpakken).

-als je door die auto heen zou moeten lopen (dus de hele boom bijlangs), dan zal je ieder onderdeel, bij iedere functie zelf moeten iterateren (while of for lusjes). En naarmate je meer onderdelen krijgt, krijg je zoveel hulp methodes, waarin iedere keer een herhaling staat van je iteratie:

vb:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public void Car{
   List deurList = new LinkedList();
   
   public List getAllBolts(){
      List list = new LinkedList();
      for(int k=0;k<dearList.size();k++){
         list.add(deurList.get(k).getAllBolts());
      }
      return list;
   }

   public List getAllNails(){
      List list = new LinkedList();
      for(int k=0;k<dearList.size();k++){
         list.add(deurList.get(k).getAllNails());
      }
      return list;   
   }

    public List getAllScrews(){
      List list = new LinkedList();
      for(int k=0;k<dearList.size();k++){
         list.add(deurList.get(k).getAllScrews());
      }
      return list;   
   }
}

Ik zal je nu laten zien hoe je een visitor kan toepassen bij een auto om alle bolts op te halen en hoe je een iteratie kan hergebruiken.
code:
1
2
3
4
5
6
7
8
9
10
11
12
class BoltCollector extends CarPartVisitor{
   
   private List _boltList = new LinkedList();
   
   public void visit(Bolt bolt){
     _boltList.add(bolt); 
   }
   
   public List getResult(){ 
     return _boltList;
   }
}

en dit moet je aanroepen met:
BoltCollector boltCollector = new BoltCollector();
car.accepts(new DepthFirstGuide(boltCollector));
en nu staan in boltCollector alle schroeven van de auto.

Je zit dat ik verder geen nieuwe methode bij alle onderdelen hoefde te maken om die bolts op te halen. Met de visitor kan je dus een bepaalde functie loslaten op een boom(netwerk kan ook) structuur, waarbij je alleen een inhaakpunt bij die onderdelen hoeft te maken voor die visitor. Maar dit is een eenmalige actie. En verder maak je eenmalig een depthfirstguide aan, en dan ben je ook van je herhaling van iteratie af. Je kan nu voor screws het volgende doen:
ScrewCollector screwCollector = new ScrewCollector();
car.accepts(new DepthFirstGuide(screwCollector());
Tsja, het is maar hoe je er tegenaan kijkt. Als 1 van de voordelen van OO werd altijd genoemd dat je een complete set van gegevens met de bij die gegevens behorende bewerkingen in 1 object hebt zitten (encapsulation). 'vanuit de gegevens bekeken' lijkt het visitors concept mij dan ook vloeken in de kerk, immers je gaat de nadruk meer leggen op functionaliteit, en haalt de functionaliteit juist _weg_ bij de gegevens.
Dat is inderdaad het 1e wat je verteld wordt, maar dit is zeker geen oo programmeren. Je moet niet altijd je data bij elkaar houden, maar je kan ook in gaan delen op functionaliteit. Dat doe je inwezen al met een model, een controller en een view. Je had dit volgens echte oo regels maar bij elkaar in moeten stoppen, maar zie jij dat gebeuren?
Zoals het op mij overkomt is het meer een manier van rangschikken van je code. De code zelf verandert er niet of nauwelijks door.. maar nu ga je me ongetwijfeld vertellen dat ik het mis heb :)
Helemaal :) Ik prog nu al een tijdje oo en na een tijdje zie je allerlei tekort komingen erin. Ik ben nu een aantal design patterns boeken aan het doorlezen en daarin leer je op een hele fijne manier om anders tegen oo aan te kijken. En de visitor is wel het meest fijne dat ik de afgelopen jaar heb gezien.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
Een rotschop van m'n eigen topic.

Dit is wellicht nog interessant leesvoer:
klik

https://fgheysels.github.io/


  • klinz
  • Registratie: Maart 2002
  • Laatst online: 10-08 15:44

klinz

weet van NIETS

Eén van mijn gouden stelregels: elke if heeft een else.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21-08 22:54
klinz schreef op 19 August 2003 @ 22:42:
Eén van mijn gouden stelregels: elke if heeft een else.
Daar ben ik het niet mee eens.

Je kan perfect een voorwaarde hebben om iets te doen, en het is ook perfect mogelijk dat er niets anders moet gebeuren als die voorwaarde niet voldaan is.

Simpel voorbeeld:
als een klant 10 of meer producten heeft besteld, dan krijgt hij 10 euro korting, anders niet.

code:
1
2
3
4
if( _numProdOrdered >= 10 )
{
    _amountToPay -= 10;
}

Het zou toch onzinnig zijn om hier nog een else aan toe te voegen?

https://fgheysels.github.io/


  • klinz
  • Registratie: Maart 2002
  • Laatst online: 10-08 15:44

klinz

weet van NIETS

Ja, het was ook een beetje overdreven.

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 07:56

alienfruit

the alien you never expected

Voor mij staat defensief programmeren het registeren van bekende problemen die eerder zijn onstaan en/of beperkingen van de taal waarin je programmeert en hier een knowledge base op na slaat die later weer kunt raadplegen. Zelf genereer behoorlijk wat stukken code dmv. XML met XSLT transform naar Delphi en/of Java. Tot heden werkt dit prima, en om deze manier sluipen er niet veel problemen in de code. (of de transform moet een fout hebben) Tot heden werkt dit prima, verder behoort een goede QA en een goede basis en regels tot hoe verre men gaat met uitbreiden van de functie omschrijving (features die grote wijzigen in de basis betrefd worden vaak vermeden, en verplaatst naar een nieuwe versie).

Iedereen zal me hier vast voor gek verklaren, maar tot heden werkt deze combinatie prima.

Ik zie niet in waarom het probleem is om die Visitor pattern in Delphi te programmeren. Naar mijn kun je prima programmeren in Delphi kun je net zulke programma's maken als in Java. Gezien de onderliggende structuur van .NET ben ik als Delphi-programmeur (maar ook Java) meer geneigd om naar het .NET platform over te stappen dan door te gaan met Java. Omdat .NET een stuk makkelijker is, overigens vind ik dat je als Delphi programmeur zelfs een voorsprong heb tot andere programmeurs, omdat er een hele ideën die al in Delphi bestonden hier in terug komen. (naar mijn mening)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Alarmnummer schreef op 08 July 2002 @ 11:08:
[...]
Helemaal :) Ik prog nu al een tijdje oo en na een tijdje zie je allerlei tekort komingen erin. Ik ben nu een aantal design patterns boeken aan het doorlezen en daarin leer je op een hele fijne manier om anders tegen oo aan te kijken. En de visitor is wel het meest fijne dat ik de afgelopen jaar heb gezien.
Intussen vind ik de visitor eigelijk een stuk minder waard. Als je een functie mbv een visitor gaat dispatchen over de types in de hierarchie, dan zit je volledig vast aan de signature van de visit methode. Uiteindelijk schrijf ik dan een extra statische functie, die de signature heeft die ik graag wil, en die vertaal ik dan van en naar de visitor zijn signature. En checked exceptions zijn dan ook zo heerlijk om dan door te geven (catchen, opslaan en later weer throwen).

Ik moet me hier nog in verdiepen, hopen dat dit eenvoudig te gebruiken is en de performance acceptabel.

[ Voor 8% gewijzigd door Alarmnummer op 20-08-2003 10:26 ]

Pagina: 1