Safe & secure programming

Pagina: 1 2 Laatste
Acties:
  • 694 views sinds 30-01-2008
  • Reageer

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoi hamsteggot, het is handig als je dit vantevoren eerst even met de mods bespreekt. Nu lopen er namelijk 2 discussies door elkaar, terwijl de eerste het makkelijkst gewoon afgesplitsts had kunnen worden. Deze gaat even dicht

(oh, en als je een topiclink neerzet doe dat dan zonder de url tag, dan maakt de forumsoftware er zelf een mooi linkje van ;))

.edit: ziezo.

[ Voor 3% gewijzigd door .oisyn op 29-05-2006 21:41 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
Trouwens, voor iemand die zo idealistisch bezig is vraag ik me af waarom je überhaupt in C programmeert
Idealen op dit gebied heb ik al lang niet meer, eerder des-illusies :'(
Het nadeel van C is ook zijn kracht. De eenvoud maakt het makkelijk om relatief snelle code te maken die op embedded systemen goed en snel functioneert. Probeer dat maar eens met een 4de genratie taal. PHP biedt vanuit die optiek enorm veel verbeteringen ten opzicht van C maar wordt als compiler niet ondersteunt voor de verschillende hardware platformen. De gegeven lijst was bedoeld als voorbeeld maar wordt nu gebruik om mij af te maken. Als iedereen zich zou houden aan zijn eigen uitspraken zouden er nooit programmmeerfouten bestaan ... maare waarom gaat er dan zoveel fout?

Zoals je het hier neerlegd, heb je gelijk. Maar zoals ik al eerder heb aangegeven probeer ik te kijken wat voor ons als thuis-programmeurs een must is. Jouw voorbeeld kan ik ook counteren met iets wat ik gisteren ook nog weer zag. Gisteren heb ik nog de volgende soort code gezien voor het tonen van een aantal strings en daarbij wat speciale acties, voor de eenvoud heb hier als voorbeeld hex codes gebruikt:
C:
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
30
31
void print_hex_waarde(int waarde)
{
  if( waarde == 0 )
    if( true == bScreen )
      printf("1");
    else
      beep(0+1);
    return;
  if( waarde == 1 )
    if( true == bScreen )
      printf("1");
    else
      beep(1+1);
    return;
  ...
  if( waarde == 15 )
    if( true == bScreen )
      printf("F");
    else
      beep(15+1);
    return;
}

void mijn_hex_print(int waarde)
{
  char Hex[HexMaxNumbers]  = { '1', '2', ...'F' }; 
  if( true == bScreen )
    printf("%c", Hex[waarde]);
  else
    beep( waarde + 1);
}

Loop ik nog even voorbij aan het controleren van 'waarde'. Het lijkt heel simpel maar als de lijst met mogelijkheden langzaam groeit (en niet beperkt blijft tot 16), zie je het niet zo duidelijk meer. Veel return statements zijn vaak een teken dat de code inefficient is, er zijn altijd uitzonderingen.

:o Had net geleerd dat een topic nooit zomaar dicht gaat, vond dit wel een sjieke oplossing omdat de titel al lang niet meer de lading dekte ... zal volgende keer lief zijn.

[ Voor 41% gewijzigd door hamsteg op 29-05-2006 22:19 ]

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

hamsteggot schreef op maandag 29 mei 2006 @ 21:53:
Het nadeel van C is ook zijn kracht. De eenvoud maakt het makkelijk om relatief snelle code te maken die op embedded systemen goed en snel functioneert. Probeer dat maar eens met een 4de genratie taal.
Sure, C heeft z'n voordelen, maar die vallen vaak in het niet bij de toegevoegde features van C++. En die werkt ook prima op embedded systemen, hoewel je wellicht wilt compileren met exceptions uitgeschakeld (de meeste compilers hebben hier wel functionaliteit voor). En comeau kan je C++ code mooi omzetten naar C code zodat je het ook kunt gebruiken met de meest exotische C compilers :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
Het belangrijkste nadeel van 4de generatie talen is de onmogelijkheid om het gedrag van het systeem te voorspellen aan de hand van de code. De uitgebreide, onder water, functionaliteit maken voorspelbaarheid van executie een echte crime, gewoonweg onmogelijk. Een simpel voorbeeld is garbage collection, een machtig feature, maar ook een die willekeurig toeslaat. Oh, en ik weet dat je garbage collection kunt uitschakelen maar dat betekent ook dat je de programmeurs moet opdragen hun geheugen expliciet vrij te maken, weg mooi feature. Constructoren en destructoren, ze lijken simpel en werken goed maar als het op voorspelbaarheid van executie van code aankomt ... wordt het toch al minder.

Wat we tegenwoordig veel doen en ook zien is dat op de systeemkritische elementen plat C draait en de toepassingslagen Java/C++. Het goede van elk gebruiken :> . Maar juist bij gebruik van 2 (of meerdere!) talen wordt een eenduidige overkoepelende stuctuur heel belangrijk, ook in coding conventions.

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

C++ kent geen garbage collection ;) (en ik zou het ook nauwelijks een 4e generatie taal willen noemen). En het is ook niet zo dat C++ standaard onvoorspelbaar is, het mooie ervan is nou juist dat je het kunt gebruiken zoals je zelf wilt. En zeker als je safe code wilt schrijven (waar deze hele topic over gaat) zou ik C++ boven C verkiezen, omdat je er dan voor kunt zorgen dat je a) geen leaks hebt, b) kunt zorgen dat je nooit buiten je buffers schrijft, en c) alle resources gewoon opgeruimd worden door destructors (resource acquisition is initialization). Bovendien heb je het nu wel heel erg over theoretische gevallen die maar een fractie zijn van de totale softwaredevelopment, en dus nauwelijks interessant in een discussie imho :)

[ Voor 86% gewijzigd door .oisyn op 29-05-2006 22:55 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

• Single point of exit (dus maar 1 return statement)
Dit doe ik wel vaak, bij sommige functies gebruik ik er meerdere, maar probeer het te voorkomen. Ik maak altijd netjes een $ret aan, waar mijn return waarde in zit.
• Altijd booleans checken tegen hun waarde (a==true)
Eens
• Altijd nieuwe context in {} zetten, ook bij 1 statement
Opzich heb je wel gelijk, maar als een functie slechts 4 of 5 regels bevat dan doe ik dit niet. Bij grotere functies doe ik dit weer wel ivm duidelijkheid en overzicht.
• Nooit meerder statements op 1 regel (for loop is uitzondering, ++=1 statement)
Eens
• Functies nooit aanroepen met berekeningen in de parameter list (drukaf(2*b+1);)
Over het algemeen los ik dit op een andere manier op, het kost me weer geheugen om een string op te slaan.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
functie a($b)
{
  //meer code hierzo, blaat.....
  //asdasdasdad

  return blaat( //--------START-C
        (4*8), //commentje
        asc($b), //meer comments blaat
        anderfunctie( //en nou nog dit berekenen
                8*2, //dit is voor de 1e dinges
                2*2 //en dit de 2e
        )
  );//-----END-C
}

Dit scheelt echt bergen zooi die je anders weer moet opruimen. Gezien ik veel met PHP-CLI doe moet ik dit wel doen (PHP Daemons, etc ;) ). Ik kan niet continu alles in de gaten houden qua netheid en opruiming.

• else...if constructies die meer als twee keer genest zijn, verbieden.
Why dat?
• enterance/exit tracing van een functie
Opzich wel handig, maar dat doe ik zelf wel even schrijven dmv een enkele echo (als er iets op z'n bek gaat). Om nou te zeggen dat ik me hier ooit mee bezig houd, nee dat niet. Maar dat kan liggen omdat ik een hobby programmeur ben.
Janoz schreef op maandag 29 mei 2006 @ 14:59:
De snelheid vind ik persoonlijk een beetje een non argument. Zeker als het enkel om fixed aantal checks gaat. Dit soort micro optimalisaties zie je alleen bij embedded en game programming.
/me jaagt Janoz het bos in, kst!

Hoe goed kon jij werken op een 386? Alles werkte toch perfect? Nou worden de computers steeds sneller en sneller, maar qua werktijd/opstarttijd word het er nogsteeds niet beter op. Zoek het verschil tussen een 386 (25MHz) met DOS 6.22 en een P4 alla 3GHz met Windows XP / Vista. De 386 start nog sneller op dan de Windows bak. En nee, dat ligt niet aan Windows, want een gemiddelde Linux Desktop variant is ook tergend traag (dan kijk ik even niet naar de extra functies alla GUI enzo). Programmeurs worden LUI onder Windows, vroeger HAD je maar 640KB ruimte ter beschikking, en was je dus genoodzaakt om je code zo netjes mogelijk te houden. Programma's worden vaak niet goed geoptimaliseerd waardoor ze rete traag worden, ook worden er veel features ingebouwd die nergens goed voor zijn (en niet eens uit te schakelen zijn).

Als ik script in PHP dan probeer ik er voor te zorgen dat de totale runtime van het script zo LAAG mogelijk blijft, dit optimailiseer ik tot de laatste microseconde. Leuk als een gemiddelde pagina 1 seconden kost om te genereren, dan mag je dus maximaal 60 requests per minute hebben, en 3600 per uur. Draait je script door wat optimalisatie op bv 0.05s dan kan je al 1200 request per minut kwijt, en 72000 per uur (hoop dat mn berekening klopt, maargoed, het maakt zeker verschil).

Als ik kan zorgen dat een script van de 0.005 naar 0.004 seconden (gemiddeld) te tunen is dan ben ik al zeer blij, iedere optimailisatie is er weer een extra. Meer vrije CPU tijd, dus weer meer bezoekers/berekeningen die je kan doen.

Doe je dit niet dan krijg je Fok! software (dikke servers, kut software) >:) .

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

KingOfDos: je draait de zaken een beetje om. Natuurlijk is efficentie tegenwoordig stuk minder belangrijk, maar goed ontworpen programma's juist destemeer. Het is echt onzin dat je elke laatste cycle eruit hoeft te kramen, die tijd zijn we gelukkig lang en breed voorbij (en dat zeg ik als een gamedeveloper). Waar het tegenwoordig om draait is dat code goed is opgezet en makkelijk programmeert. De lezer kan beter zien wat er staat en de developer kan later z'n applicatie makkelijker uitbreiden met andere features. En pas daarna ga je aan de slag met optimaliseren waar nodig.

En leuk, dat voorbeeld van de 386, maar je loopt daar even aan het feit voorbij dat de gemiddelde applicatie van toen slechts een fractie van de hoeveelheid code waren van de applicaties van nu. Grote applicaties op de manier van toen ontwerpen is een crime en de development-tijd zal vele malen langer zijn.

En als snelheid écht zo belangrijk is moet je ook geen PHP gebruiken :)

[ Voor 34% gewijzigd door .oisyn op 29-05-2006 23:37 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
bartje321 schreef op maandag 29 mei 2006 @ 19:33:
je kunt natuurlijk ook valsspelen :)

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char functie(int parameter){
    if(parameter == 1){
        return 'a';
    }else if(parameter == 2){
        return 'b';     
    }else if(parameter == 3){
        return 'c';     
    }
    return 'd';         
}

char prefunctie(int parameter){
    char result = functie(parameter);
    //whie, single exit point
    return result;
}
Zonder aan leesbaarheid of functionaliteit in te boeten kan die onderste functie ook als volgt:
Java:
1
2
3
char prefunctie(int parameter){
    return functie(parameter);
}
En dan valt hopelijk op hoe onzinnig het is.
Als je puur een bepaald coding style principe na wilt leven en dan wel op zo'n manier vals speelt heb je last van cognitieve dissonantie. :Y)
edit:
Anders kijk ik ff over pagina 2 heen :X

[ Voor 43% gewijzigd door Voutloos op 29-05-2006 23:27 ]

{signature}


  • XWB
  • Registratie: Januari 2002
  • Niet online

XWB

Devver
Hoewel optimaliseren altijd uitdagend is vraag ik me soms af of het wel rendabel is om een app 10x te checken waar het sneller kan. Natuurlijk leer je er wel van, en dat wat je eruit leert neem je in een volgende app gewoonweg mee :)

[ Voor 27% gewijzigd door XWB op 29-05-2006 23:28 ]

March of the Eagles


Verwijderd

.oisyn schreef op maandag 29 mei 2006 @ 23:21:
KingOfDos: je draait de zaken een beetje om. Natuurlijk is efficentie tegenwoordig stuk minder belangrijk, maar goed ontworpen programma's juist destemeer. Het is echt onzin dat je elke laatste cycle eruit hoeft te kramen, die tijd zijn we gelukkig lang en breed voorbij (en dat zeg ik als een gamedeveloper).
Daar heb je zeker gelijk in, het gaat mij er om dat er soms zulke ranzige constructies gebruikt worden waardoor het gewoon trager dan nodig gaat.
En als snelheid écht zo belangrijk is moet je ook geen PHP gebruiken :)
Snelheid is in zoverre belangrijk dat de gebruiker geen 3 seconden hoeft te wachten op een internetpagina. Dat word door de gebruiker als "zeer frustrerend" ervaren, en daardoor word oa een website sneller afgesloten (of tenzij je weet dat er op die trage site zinnige content staat, die je echt nodig hebt). Ik ga ook niet voor de 0.000001 seconden die ik kan optimaliseren, maar als er 0.005 vanaf kan dmv een simpele optimalisatie, dan doe ik dat zeker.

Misschien ligt het aan mij, omdat ik gewoon "willekeurig" begin te ontwikkelen (oké ik schrijf wel iets uit, meer een eisenpakket dan een PSD (of hoe heet zo'n diagram?)). Ik heb wel in veel "basis" functies een timer draaien om te kijken waar veel tijd in gaat zitten (denk aan de volgende counters: db, template, main, userauthenticatie, etc).

"Persoonlijk" geef ik webapplicaties meer toekomst dan lokale. Ik denk dat het "mainframe" idee wel weer terug gaat komen voor bepaalde soort apps, dit oa ivm de stijgende energiekosten (1 dikke server en 100 thin clients/SSF's (linux+browser) gebruiken minder stroom dan 100 desktops met lokale apps), en een beetje hippy gevoel: Goed voor de natuur ;) :9
Maargoed ik wil geen topic-hijack doen over het energieverbruik, dat is lichtelijk offtopic.

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 20-02 15:44
Beperkt de scope even tot mijn (en de meeste) bekende ervaring: PHP voor websites .e.d. De vertraging zit niet in het ene loopje meer, die paar functieaanroepen extra of wat dan ook. Dit zit in het wachten op de database, het resizen van afbeeldingen enzovoorts. Pas bij tig-duizend loops (wat meestal een development fout is uitgezonderd enkele programma's) worden dat soort optimalisaties een puntje.

Wat betreft het "safe & secure": Heel simpel gesteld: In de PHP scripts die ik heb gezien, ook redelijk nette etcetera, is het volgens mij maar beter dat je gewoon stopt als er functie niet meer verder kan. Je weet dan 100% zeker dat er in geval van bugjes: Toch een query uitvoeren met de ongeldige waarde omdat de variablenaam er op lijkt enzovoorts je blij bent dat dit return de code gewoon stopt, iets wat ook logisch is eigenlijk?

Als we het dus over scripts hebben e.d. en dus niet over de high-end applicaties waar teams van tig man aan werken denk ik niet dat je een punt hebt. Dat je op jouw vakgebied gelijk hebt is begrijpelijk maar praktisch gezien niet voor de meesten hier.

Verwijderd

Zomaar eens een vraagje want ik gebruik namelijk een nogal andere coding style als de meesten (als voorbeeld):

PHP:
1
2
3
4
5
6
7
8
9
10
<?php
if($a == true)
{
     echo "Test 1";
}
else
{
     echo "Test 2";
}
?>


In plaats van
PHP:
1
2
3
4
5
6
7
<?php
if($a == true){
     echo "Test 1";
}else{
     echo "Test 2";
}
?>


Omdat ik het eerste voorbeeld veel overzichtelijker vind dan het tweede, maar is dit nu volgens de richtlijnen ook een goede manier of is de tweede manier nu beter volgens de richtlijnen?

[ Voor 29% gewijzigd door Verwijderd op 30-05-2006 08:50 ]


  • 12_0_13
  • Registratie: April 2004
  • Laatst online: 12-02 13:19
Ik vind het de grootste onzin om een boolean te checken tegen true (of false), en snap ook niet dat jullie daaraan meewerken.

Gebruik een fatsonelijke naam voor je variabele, en je kan de code gewoon lezen. Dus niet:

C++:
1
if (a==true) {}


maar

C++:
1
if (isLimited) {}


booleans beginnen met is.... en has.... en lezen vanzelf. Wil je de negatie checken, gebruik dan de not operator. Hiermee voorkom je allerlei fouten als het per ongeluk assignen (= ipv ==) en je code wordt leesbaarder en makkelijker onderhoudbaar.

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 03:57
Verwijderd schreef op dinsdag 30 mei 2006 @ 08:49:
Omdat ik het eerste voorbeeld veel overzichtelijker vind dan het tweede, maar is dit nu volgens de richtlijnen ook een goede manier of is de tweede manier nu beter volgens de richtlijnen?
Wat mij betreft is dit een geval van persoonlijke voorkeur (thuis) of afhankelijk van de afgesproken coding guidelines (op het werk).
12_0_13 schreef op dinsdag 30 mei 2006 @ 09:03:
Ik vind het de grootste onzin om een boolean te checken tegen true (of false), en snap ook niet dat jullie daaraan meewerken.

Gebruik een fatsonelijke naam voor je variabele, en je kan de code gewoon lezen. Dus niet:

C++:
1
if (a==true) {}


maar

C++:
1
if (isLimited) {}


booleans beginnen met is.... en has.... en lezen vanzelf. Wil je de negatie checken, gebruik dan de not operator. Hiermee voorkom je allerlei fouten als het per ongeluk assignen (= ipv ==) en je code wordt leesbaarder en makkelijker onderhoudbaar.
Hulde! Helemaal mee eens!

Roomba E5 te koop


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 20-02 14:32
Als je het mij vraagt doen alle genoemde zaken in dit topic er niet toe wat betreft fout preventie in code. Wat er werkelijk toe doet is dat er in een uniforme stijl geprogrammeerd wordt. Want wanneer sluipen fouten in code, als er meer mensen aan gewerkt hebben.

Tevens is code stijl van ondergeschikt belang aan de kwaliteit van de controles op pre en postcondities van een verwerking. Dus wat je doet als je een functie/method binnenkomt en weer uitgaat.

Persoonlijk geef ik een voorkeur aan een single point of return, behalve voor error/pre conditie controles. Bij een error/preconditie controle geef ik graag op de plek zelf terug dat er een probleem is. En dan maakt het niet uit of ik rapporteer middels een exception of een magic value.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
public int stukjeOnzin() {
    if(erIsStrontAanDeKnikker()) {
        return -1;
    }

    int result = 0

    ikDoeMijnDing();
    ikOok();
    result = enIkWeetHetResultaat();

    if(maarAlsIkHetVindKrijgenWeIetsAnders()) {
        result = ikMaakErLekkerGehaktVan();
    }

    return result;
}
...


Overigens is het bij single point of return proggen aan te raden om een vaste variabele naam te gebruiken voor je resultaat. Bijvoorbeeld result. Deze variabele kun je dan eventueel opnemen in de highlighting regels van je IDE/Editor. Zodat ie lekker makkelijk te vinden is.

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 20-02 09:23

LauPro

Prof Mierenneuke®

Verwijderd schreef op dinsdag 30 mei 2006 @ 08:49:
Zomaar eens een vraagje want ik gebruik namelijk een nogal andere coding style als de meesten (als voorbeeld):
Dit is een hele gevaarlijke discussie :o deze is 20 jaar geleden begonnen en daar zijn inmiddels al bijna doden bij gevallen ;) . Persoonlijk ben ik aanhangen van de Kernighan & Ritchie-stijl. Zie o.a.: http://www.cs.usyd.edu.au/~scilect/tpop/handouts/Style.htm. Daarnaast gebruik ik altijd tabs in plaats van spaties! Dit is ook een heel gevoelig punt. De stijl die ik handhaaf:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace foospace {
class Bar {
public:
    int foo();
private:
    int m_foo;
};

int Bar::foo() {
    switch (x) {
    case 1:
        break;
    default:
        break;
    }
    if (isBar) {
        bar();
        return m_foo+1;
    }else{
        return 0;
    }
}
}


Wat er alleen af wijkt van de K&R-methode zijn de extra accolades bij het laatste else-statement. En ik zet de punt ter afsluiting van een klasse-definitie direct achter een accolade ipv op een nieuwe regel.

GNU heeft ook een style waarbij men gebruik maakt twee spaties om in te springen, dit vind ik een beetje kortzichtig. Bij de Linux-style zie ik een inconsequentie waarbij accolades bij namespaces/klassen/functies op een aparte regel moeten maar bij if, switch, etc statements niet.

Bij ANSI komt alles op een nieuwe regel, dat vind ik de code nodeloos lang en complex maken. Hiermee kan je je code veel moeilijker overzien of je moet enorm grote schermen hebben.

[ Voor 22% gewijzigd door LauPro op 30-05-2006 09:48 ]

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
@olger1024
Ook ik verkies de eerste methode, maar dat komt ook omdat ik graag kommentaar voor een block zet:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
/* testen op aanwezigheid van .... */
if($a == true)
/*                                                                                      */
/* Het is aanwezig. De volgende volgorde is belangrijk a, b, c, omdat ... blabla        */
{
     echo "Test 1";
}
else
/*                                                                                      */
/* Het is niet aanwezig, opruimen in de volgende volgorde is belangrijk want ... blabla */
{
     echo "Test 2";
}
?>

Ik kan de reacties al weer voorstellen ... kies dan goede variabelen en niet $a. Dat doe ik zeker, maar bepaalde gedachtenkronkels om een bepaalde sequence te volgen schrijf ik ook op zodat ik na een jaar mijn eigen code ook nog weer kan lezen.

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


Verwijderd

hamsteggot schreef op dinsdag 30 mei 2006 @ 09:47:
@olger1024
Ook ik verkies de eerste methode, maar dat komt ook omdat ik graag kommentaar voor een block zet:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
/* testen op aanwezigheid van .... */
if($a == true)
/*                                                                                      */
/* Het is aanwezig. De volgende volgorde is belangrijk a, b, c, omdat ... blabla        */
{
     echo "Test 1";
}
else
/*                                                                                      */
/* Het is niet aanwezig, opruimen in de volgende volgorde is belangrijk want ... blabla */
{
     echo "Test 2";
}
?>

Ik kan de reacties al weer voorstellen ... kies dan goede variabelen en niet $a. Dat doe ik zeker, maar bepaalde gedachtenkronkels om een bepaalde sequence te volgen schrijf ik ook op zodat ik na een jaar mijn eigen code ook nog weer kan lezen.
Daar ben ik dus ook mee eens maar ik wees alleen $a maar even aan als voorbeeld :) ik zal er de volgende keer $voorbeeld van maken :P

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik weet het, het is een nutteloze discussie, maar
LauPro schreef op dinsdag 30 mei 2006 @ 09:45:
Bij ANSI komt alles op een nieuwe regel, dat vind ik de code nodeloos lang en complex maken. Hiermee kan je je code veel moeilijker overzien of je moet enorm grote schermen hebben.
Correctie, hiermee kan jij je code moeilijker overzien. Ik vind het juist prettiger leesbaar, vooral als de conditie in een if bijvoorbeeld meerdere regels beslaat.
C++:
1
2
3
4
5
6
if ((conditie1 && conditie2) ||
    (conditie3 && conditie4) ||
    (conditie5 && conditie6))
{
    // .. code
}


Ook is het handig omdat je dan de if kunt uitcommenten zonder dat je code breekt (handig tijdens het debuggen), en de condities en de compounds apart van elkaar kunt copypasten. Om nog maar niet te spreken over conditional code in C/C++, waar je met portable code al snel mee te maken hebt:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
#if BUILD_WINDOWS
if (Renderer::NextGenRendering())
#endif
{
    // doe next-gen stuff voor pc, xbox360, ps3
}
#if BUILD_WINDOWS
else
{
    // doe prev-gen stuff voor pc
}
#endif


En grote schermen zijn sowieso een pre bij development, ik heb hier op m'n werk een 22" @ 1920x1440 en een 19" @ 1600x1200, en ik vind het :9

[ Voor 26% gewijzigd door .oisyn op 30-05-2006 11:20 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 20-02 09:23

LauPro

Prof Mierenneuke®

.oisyn schreef op dinsdag 30 mei 2006 @ 11:14:
Correctie, hiermee kan jij je code moeilijker overzien. Ik vind het juist prettiger leesbaar, vooral als de conditie in een if bijvoorbeeld meerdere regels beslaat.
Het is geen gevoel, het is een gegeven. Feitenlijk is het zo dat wanneer je meer linebreaks in je code stopt dat de code moeilijker te overzien wordt, ergo er passen namelijk minder regels op je scherm (bij hetzelfde lettertype/resolutie). Dus per saldo zal je een kleine scope van je code op het scherm kunnen vertonen. Dat het hierdoor wellicht leesbaarder wordt is een heel ander verhaal.
Ook is het handig omdat je dan de if kunt uitcommenten zonder dat je code breekt (handig tijdens het debuggen), en de condities en de compounds apart van elkaar kunt copypasten. Om nog maar niet te spreken over conditional code in C/C++, waar je met portable code al snel mee te maken hebt:
Hoe bedoel je dit? Wanneer je alleen regel met if uitcomment met // dan krijg je in dat geval gewoon dikke parse error. Dan moet je dus werken met /* */. Of bedoel je het individueel uitcommenten van parameters/vergelijkingen? Dit lijkt me een zeer gevaarlijke activiteit. Voordat je het weet geeft je hierdoor parameters verkeerde waardes mee of verbouw je je statement er zo mee dat er een lek ontstaat. Sowieso moet je naar mijn idee niet inline gaan commenten (dus in de conditieclausule bij een if, for etc.).

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

The nice thing about standards is that there are so many to choose from.
;)

Puur ter illustratie: het single return-principe en het guard clause-principe. Beiden door guru's verdedigd, beiden hebben hun nadelen. Verzamel je eigen argumenten, belicht alleen de zwakheden van de andere optie .. tada!

Het denken in absoluutheden vind ik zeer achterhaald. Ik geloof daar niet zo in. Het mooiste van Applying UML and Patterns vind ik dat er nergens wordt gesproken over good/bad, maar over better/worse. Het zijn namelijk vrijwel altijd afwegingen die je maakt.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 00:09

Janoz

Moderator Devschuur®

!litemod

Een groter scherm is voor mij nog geen reden om mijn code ook maar breder te maken. Ik probeer zoveel mogelijk max 80 aan te houden. Wanneer het te breed wordt lees het lastig. Wanneer je aan het einde van een regel bent is het begin van de volgende regel soms lastig te vinden omdat het relatief ver weg is.

@hamsteggot
Ik heb het idee dat veel van je stellingen zijn gebaseerd op C.

--Single point of exit (dus maar 1 return statement)
Ben ik eerder al op in gegaan. Meest valide argument hiertegen vind ik het volgende. Zoals al veel voorgesteld als alternatief wordt er in de hele functie een waarde bijgehouden die aan het eind wordt gereturned. Voor een compiler (of profiler desnoods) zijn de toekennen aan deze variable een stuk lastiger bij te houden. Een vergeten return is makkelijker te detecteren dan een vergeten toekenning.

--Altijd booleans checken tegen hun waarde (a==true)
Dit lijkt me een door het gebruik van C ingegeven eis. In een stronge typed taal waarin wel een native boolean zit heb je het probleem niet.

--Altijd nieuwe context in {} zetten, ook bij 1 statement
Eens

--Nooit meerder statements op 1 regel (for loop is uitzondering, ++=1 statement)
Eens

--Functies nooit aanroepen met berekeningen in de parameter list (drukaf(2*b+1);)
Ook dit lijkt me een door het gerbuik van C ingegeven eis. Dit levert problemen op wanneer je by ref door gaat geven. Wanneer het de duidelijkheid niet aantast zet ik ze toch liever zo erin. Ik hou er niet van om de scope te vervuilen met allemaal variabelen die je maar twee regels gebruikt. Zeker bij C zou dit een enorme waslijst geven aan het begin van je functie.

De enige reden die ik in het voordeel van deze stelling vind spreekt is (debug)logging. Als jje de berekende waarde toekent aan een tijdelijke variabele kun je makkelijke een log("blaat : "+tmp) er tussen zetten.

--else...if constructies die meer als twee keer genest zijn, verbieden.
Dat vind ik persoonlijk aan de gewenste functionaliteit liggen. Sowieso wil ik het niet te ver in laten springen. Meer dan 3 a 4 niveaus diep wil ik niet gaan. Als je echter else if gebruikt (dus zonder een { ) spring je niet verder in. Case gebruik ik eigenlijk alleen als de check een primitive gebruikt, of als er meerdere cases meerdere acties nodig hebben (ie het hier en daar weglaten van een break). De reden waarom ik nog veel else if gebruik ipv case is meer door java ingegeven omdat je daar voor een case enkel primitiven kunt gebruiken.

--(enterance/exit tracing van een functie)
Als log informatie? Ja, dat doe ik ook nog wel, maar ik vind het geen vereiste.


@KingOfDos
Daar heb je zeker gelijk in, het gaat mij er om dat er soms zulke ranzige constructies gebruikt worden waardoor het gewoon trager dan nodig gaat.
Het zijn juist van die micro optimalisaties waar ik in mijn post op doel die voor ranzige constructies zorgt. Ik raad je daarom ook aan om vooral ook de tweede allinea van die post door te nemen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

LauPro schreef op dinsdag 30 mei 2006 @ 11:33:
[...]
Het is geen gevoel, het is een gegeven. Feitenlijk is het zo dat wanneer je meer linebreaks in je code stopt dat de code moeilijker te overzien wordt, ergo er passen namelijk minder regels op je scherm (bij hetzelfde lettertype/resolutie). Dus per saldo zal je een kleine scope van je code op het scherm kunnen vertonen. Dat het hierdoor wellicht leesbaarder wordt is een heel ander verhaal.
Euh, overzichtelijkheid heeft ook een groot deel met leesbaarheid te maken, dus hier spreek je jezelf een beetje tegen. Door alle lege regels uit m'n code weg te halen en alle accolades op dezelfde regel te laten beginnen wordt het echt niet overzichtelijker. Net als een boek niet overzichtelijker wordt als hij zonder alinea's geschreven wordt, terwijl er toch echt minder informatie op een pagina past.
Hoe bedoel je dit? Wanneer je alleen regel met if uitcomment met // dan krijg je in dat geval gewoon dikke parse error.
C++:
1
2
3
4
// if (conditie)
{
    // code
}

Dat werkt niet als de { op dezelfde regel als de if() staat.

Overigens is dit ook wel te bereiken door true || vooraan de conditie toe te voegen als ie altijd uitgevoerd moet worden, of false && als ie nooit uitgevoerd moet worden

[ Voor 8% gewijzigd door .oisyn op 30-05-2006 12:04 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Janoz schreef op dinsdag 30 mei 2006 @ 11:36:
Dit lijkt me een door het gebruik van C ingegeven eis. In een stronge typed taal waarin wel een native boolean zit heb je het probleem niet.
C99 heeft een native _Bool, maar helaas geen values voor true en false ;) (je zal met 0 en 1 moeten werken)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

ik gebruik ook de stijl die .oisyn aangeeft. Ik vind ze ook veel beter te overzien.
Op school worden we verplicht van
C++:
1
2
3
4
5
6
7
8
if (isOnzin) {
  printf("Wat een dikke onzin!");
  return onzinnig_getal;
}
else {
  printf("I.Q. += 10");
  return zinnig_getal;
}

Ik vind dit onoverzichtelijk aangezien ik bij een } altijd verticaal omhoog ga tot de vorige { om
de volledige block te identificeren. Als die weg is, durf ik soms een heel stuk hoger uitkomen.

algemene regel:
als een functie niet op 1 scherm past is ze te lang. Maak deelfuncties die bepaalde
functionaliteit overnemen. Een mens kan maar een bepaalde hoeveelheid informatie tegelijk overzien.

Wat alle andere statements betreft:
common sense.

Als ik een bedrijfskritische app schrijf dan schrijf ik codeer ik enkel de logica. Optimalisaties heb je'n compiler voor. Schrijf je'n performance critical app, dan pas kun je je eens bezig gaan houden met globale optimalisatie.

Verder maak je gewoon dat je functie doet wat ie doet, nix meer nix minder.
Als je dan debugmogelijkheden hebt haal je de foute functie er in de meeste gevallen behoorlijk snel uit.

ASSUME makes an ASS out of U and ME


  • EXX
  • Registratie: Juni 2001
  • Laatst online: 19-02 16:54

EXX

EXtended eXchange

Wat ik hier in deze hele discussie mis is 1 ding: goede documentatie.

Je kan je code nog zo netjes maken, als de code niet goed gedocumenteerd is blijft het een hele klus voor de programmeur die de code moet onderhouden.

Veel commentaar in je code schrijven is geen leuk klusje, maar een absolute must.

For it is the doom of men that they forget...           Huidige en vroegere hardware specs         The Z80 is still alive!


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

En dan is nog de vraag wat voor commentaar.
C#:
1
i++; // verhoog i
Geen geintje :X

Uitleggen waarom je iets doet is m.i. een goede richtlijn. Dat is ook nog eens onafhankelijk van de implementatie.
Als je uitlegt wat je doet, is of je code onduidelijk, of heeft de lezer gewoon een goed boek nodig.
Als je uitlegt hoe je iets doet, loop je het risico dat de code out of sync raakt met het commentaar.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • EXX
  • Registratie: Juni 2001
  • Laatst online: 19-02 16:54

EXX

EXtended eXchange

Precies.

Waar we iig niet op moeten bouwen is zgn. 'self-explaining code'. Dat is een illusie.

For it is the doom of men that they forget...           Huidige en vroegere hardware specs         The Z80 is still alive!


  • zeroxcool
  • Registratie: Januari 2001
  • Laatst online: 20-02 14:43
hamsteggot, ik ben eerlijk gezegd wel benieuwd naar wat voor een software jij ontwikkelt. Als ik het zo hoor is het behoorlijk mission-critical, kun je daar misschien iets over kwijt?

zeroxcool.net - curity.eu


  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

bartje321 schreef op maandag 29 mei 2006 @ 17:07:
@hamsteggot: wedden dat je ook tegen goto''s bent :) (en ik geef je groot gelijk)
goto's kunnen spaghetti en dubbele code voorkomen :

C:
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
30
31
32
struct blaat {
     char *x;
     char *y;
};

struct blaat * a(void)
{
   struct blaat *x;

   a = malloc(sizeof(struct blaat));
   if (a == NULL)
      goto errout;
   a->x = malloc(sizeof(char) * 10);
   if (a->x == NULL)
      goto errout;

   a->y = malloc(sizeof(char) * 10);
   if (a->y == NULL)
      goto errout;

   return a;

errout:
   if (a->x)
     free(a->x);
   if (a->y)
     free(a->y);
   if (a)
     free(a);

   return NULL;
}


vs

C:
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
30
struct blaat {
     char *x;
     char *y;
};

struct blaat * a(void)
{
   struct blaat *x;

   a = malloc(sizeof(struct blaat));
   if (a == NULL) {
      return NULL;
   }

   a->x = malloc(sizeof(char) * 10);
   if (a->x == NULL) {
       free(a);
       return NULL);
   }

   a->y = malloc(sizeof(char) * 10);
   if (a->y == NULL) {
     if (a->x)
         free(a->x);
     free(a);
     return NULL;
   }

   return a;
}


't voorbeeld is wat simpel, maar de strekking is denk ik duidelijk. Ik heb zelf wat macro's in elkaar gezet die bv destruct aanroepen, en meteen de pointer op NULL zetten. Verder gebruik ik vrij veel assert's in de code, ik heb teveel gezien dat om echte problemen wordt heen gecode ipv ze structureel te verhelpen.

[ Voor 24% gewijzigd door igmar op 30-05-2006 12:22 ]


  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

Een korte opmerking rond single point of return : wat doe je dan met yield statements ? moet je daarbij dan ook weer zo'n if/else constructie gaan opzetten ? Het lijkt me dat je dan net aan het gemak van yields voorbijgaat ?

Een concept dat ik iets interssanter vind, is dat rond de try/catch en errorhandlers : gebruiken jullie overal dezelfde errorhandlers?
Gebruiken jullie de standaard exceptions of gaan jullie zelf de exceptions gaan definiëren. Mag je exceptions uberhaupt gebruiken om je flow te bepalen, of moet dit echt een geval van uitzondering zijn ? (o.a. om performance-redenen)
Worden de standaard exceptions afgehandeld door steeds dezelfde exception handler of niet ? Is er een apart behandeling voor niet-standaard exceptions...

Quick & Dirty :
C#:
1
2
3
public string StringFromFile(string fn) {
  return File.OpenText(fn).ReadToEnd();
}


Iets uitgebreider (zonder exceptions):
C#:
1
2
3
4
5
6
public string StringFromFile(string fn) {
  // check filename, if not exists log error and return null
  // open file , if failed log error and return null
  // lees file etc...
  return s;
}
igmar schreef op dinsdag 30 mei 2006 @ 12:21:
[...]


goto's kunnen spaghetti en dubbele code voorkomen :

't voorbeeld is wat simpel, maar de strekking is denk ik duidelijk. Ik heb zelf wat macro's in elkaar gezet die bv destruct aanroepen, en meteen de pointer op NULL zetten. Verder gebruik ik vrij veel assert's in de code, ik heb teveel gezien dat om echte problemen wordt heen gecode ipv ze structureel te verhelpen.
Mijn oplossing zou zijn :
C:
1
2
3
4
5
6
7
8
void blaat_destruct(blaat *a) {
   if (a->x)
     free(a->x);
   if (a->y)
     free(a->y);
   if (a)
     free(a);
}


Want waarschijnlijk moet je die destructor nog wel meer aanroepen ? Goto's zouden echt wel enkel in extreme gevallen mogen gebruikt worden, en dan nog...

offtopic:
in je voorbeeld bedoel je trouwens waarschijnlijk :
[code]
struct blaat * a(void)
{
struct blaat *a; //a ipv x, anders kloppen je assignments niet meer

a = malloc(sizeof(struct blaat));
if (a == NULL) {
...
[/code]

[ Voor 35% gewijzigd door D4Skunk op 30-05-2006 12:35 ]


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

Alarmnummer

-= Tja =-

Verwijderd schreef op maandag 29 mei 2006 @ 22:59:
• Single point of exit (dus maar 1 return statement)
Dit doe ik wel vaak, bij sommige functies gebruik ik er meerdere, maar probeer het te voorkomen. Ik maak altijd netjes een $ret aan, waar mijn return waarde in zit.
Ik escape uit een functie zo snel ik er niets meer te zoeken heb (anders krijg je van die onnodig geneste structuren). Verder horen functies niet complex te zijn (in de meeste gevallen) dus je moet de flow met beide aanpakken nog steeds goed kunnen zien.
• Altijd booleans checken tegen hun waarde (a==true)
Het heeft geen toegevoegde waarde: alleen maar meer code om te lezen. Je moet een goeie naam bedenken voor je conditie en dan ben je die == true niet nodig. Als ik complexe expressies heb, dan breek ik de expressie wel op in een aantal kleine subexpressies en geef ik daar een naam aan en plaats die in de conditie. Dan kan je tenminste zien wat je aan het doen bent.
• Altijd nieuwe context in {} zetten, ook bij 1 statement
Sinds we code beautifiers hebben heeft volgens mij nog nooit iemand een fout gemaakt zoals de volgende:

code:
1
2
3
if(a > 20 )
     System.out.println("foo");
     System.out.println("bar");


Dus waarom beschermen tegen iets dat fout gaat. En verder pas ik me hierin gewoon netjes bij de bedrijfsstijl aan, dus als het daar moet dan heb ik er niet veel problemen mee. In mijn eigen code doe ik het niet.
• Nooit meerder statements op 1 regel (for loop is uitzondering, ++=1 statement)
True..
• Functies nooit aanroepen met berekeningen in de parameter list (drukaf(2*b+1);)
Geen problemen mee mits de berekening niet te complex is. Als de berekening complex is dan maak ik liever een aantal variabelen aan en bereken daarin de waarden en plaats die erin. Dan kun je in een ook opslag zien wat de bedoeling is.
• else...if constructies die meer als twee keer genest zijn, verbieden.
In principe geen problemen mee. Maar als ik 3 of meer nestings zien dan vind ik dat meestal een beetje fishy en breek het op tot losse methodes waarin meteen duidelijk is wat de bedoeling is.


[edit]
Ik denk dat 'veilig' werken op een hoger nivo hier totaal genegeerd wordt. Er zijn veel belangrijkere issues dan dit soort details: oa structuur binnen een applicatie. Dat zijn de dingen waar echt op gehamerd moet worden. Je moet je dus niet blind staren op dit soort low level details.

[ Voor 7% gewijzigd door Alarmnummer op 30-05-2006 13:00 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

igmar schreef op dinsdag 30 mei 2006 @ 12:21:
[...]


goto's kunnen spaghetti en dubbele code voorkomen :

C:
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
30
31
32
struct blaat {
     char *x;
     char *y;
};

struct blaat * a(void)
{
   struct blaat *x;

   a = malloc(sizeof(struct blaat));
   if (a == NULL)
      goto errout;
   a->x = malloc(sizeof(char) * 10);
   if (a->x == NULL)
      goto errout;

   a->y = malloc(sizeof(char) * 10);
   if (a->y == NULL)
      goto errout;

   return a;

errout:
   if (a->x)
     free(a->x);
   if (a->y)
     free(a->y);
   if (a)
     free(a);

   return NULL;
}
Tja...
C++:
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
30
31
32
33
34
35
36
struct blaat
{
    char * x, * y;
};

blaat * a()
{
    try
    {
        std::auto_ptr<blaat> b (new blaat);
        auto_array<char> x(10), y(10);
        b->x = x.release();
        b->y = y.release();
        return b.release();
    }
    catch(...)
    {
        return 0;
    }
}

// of beter:

struct blaat
{
    blaat() : x(10), y(10)
    {
    }

    std::vector<char> x, y;
};

blaat * a()
{
    return new blaat();
}

Wat mijn eerdere punt weer bewijst :)

[ Voor 6% gewijzigd door .oisyn op 30-05-2006 12:41 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
@LauPro
Het is geen gevoel, het is een gegeven.
Dat is dan jouw gegeven want ik ben het compleet met je oneens (en een antal guru's ook, Les Hatton voorop). De code zoals geschreven door .oisyn verdient mijn absolute voorkeur. Als je een regel code moet verdelen over meerdere regels (>5) moet je jezelf so-wie-zo de vraag stellen of dat wat je schrijft wel goed is.

Wat wel een gegeven is, is dat 80 characters eigenlijk al te breed is voor het menselijke brein. Kranten maken heel bewust gebruik van colommen omdat de lezer anders niet in staat is zijn aandacht vast te houden. Onderzoeken op web-pagina's geven heel duidelijk aan dat gemiddeld genomen rechts boven het meest gelezen stukje is ('F' patroon), je hebt het dan over 3,4 regels met maximaal 40 characters.

Dat jij in staat bent lange regels te lezen komt omdat je de regels zelf hebt geschreven en de context erachter snapt. Een ander zal niet zo gemakkelijk jouw lange regels snappen. Vaak is het uitgangspunt van code schrijven om het zo te schrijven dat anderen het ook kunnen lezen (en als je je eigen code na een jaar terug ziet voel je je ook een vreemde).

Voor het antwoord op je tweede vraag zou ik maar eens gaan kijken bij het hoofdstuk pre-compiler directives. Als je multi platform ontwikkeld zijn dit noodzakelijke constructies, mooi of niet.

@Janoz
veel gebaseerd op C
Heb ik nooit ontkent, 90% van de low level embedded wereld is C of een afgeleide daarvan. Het begint wel langzaam te verschuiven. Gelukkig ben ik ook op de hoogte van C++ (iets stricter als C, maar OO deel vind ik niet goed), Java (mooie abstractie concepten, een aantal heb ik in C omgezet) en PHP (helaas geen compiler, heft veel beperkingen van C op en OO is op de goede weg). Expliciete boolean checking is inderdaad hoofdzakelijk een C beperkiing, later programmeertalen hebben hier een strong type voor gefinieerd (C++ volgens mij ook niet, kunt vergelijken met integer).


Weet je, het gaat er niet om welke keuzes je maakt, Kenneth, zei ook al wat van die strekking. Het gaat er wel om dat je afgewogen keuzes maakt die het mogelijk maken om bepaalde fouten, die veel voorkomen voor de gekozen taal, te voorkomen. Een (true==false) constructie verdient geen schoonheidsprijs maar voorkomt wel een aantal veel voorkomende fouten. Evenzo is een bumper op een auto is een noodzakelij kwaad, er zijn genoeg auto's waar het weglaten van die bumper tot een veel kleinere en efficientere auto zou leiden (whow, hoe klein worden die Ka-tjes dan ?).

Te veel mensen reageren vanuit het gevoel of onzin-die-fout-maak-ik-niet. Het niet erkennen van de beperkingen van een programmeertaal of van jezelf als programmeur is het grootste probleem van de programmeerwereld in het algemeen. Het is niet voor niets dat in de afgelopen 20 jaar het aantal fouten per 1000 regels code nog steeds rond de 6 ligt. Ergens zijn wij zelfs slechter geworden want veel van die code wordt door SDE met standaard templates en standaad code generatie, automatisch uitvullen ook nog eens voor ons gemaakt. Waar andere vakgebieden leren van fouten, zijn wij vrij hardnekkig. Een nieuwe taal wordt altijd als een hype ontvangen om later met dezelfde soort problemen naast de andere talen te worden gezet. Ons eigen gedrag zetten we niet onder de loep.

Ik had gehoopt dat vanuit de studies/bedrijven wat meer aandacht besteed werd aan de beperking van talen en programmeurs... maar ben teleurgesteld. Is er niets positiefs te melden? Ja, de mods vallen positief op, hebben kennis van zaken (ondanks dat ze het op punten oneens zijn met mij, maar daarvoor is dit forum :D ).

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wheehehe, C++ OO vind je niet goed maar PHP OO is op de goede weg? :D
Iets zegt me dat je toch niet zo heel erg op de hoogte bent van C++. Zie m'n code hierboven, het is niet alleen een toegevoegde OO, het is een heel ander (en veilig) paradigima waar je in programmeert (kunt programmeren eigenlijk).

[ Voor 67% gewijzigd door .oisyn op 30-05-2006 12:51 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

kenneth schreef op dinsdag 30 mei 2006 @ 12:06:
En dan is nog de vraag wat voor commentaar.
C#:
1
i++; // verhoog i
Geen geintje :X

Uitleggen waarom je iets doet is m.i. een goede richtlijn. Dat is ook nog eens onafhankelijk van de implementatie.
Niet helemaal mee eens. Het moet redelijk logisch blijken 'waarom' je dingen doet. Anders krijg je dit soort nutteloosheden:
C++:
1
2
3
4
5
f::~f()
{
  // Close file handle because else we leak resources
  if (m_hFile != INVALID_HANDLE_VALUE) ::CloseHandle(m_hFile);
}

Lijkt me redelijk obvious waarom je files sluit in een destructor van een class. Wel verdient het een commentaar als je bepaalde dingen doet die niet logisch zijn, zoals bijvoorbeeld het open laten van de file. Vaak voorzie ik zo'n situatie ook nog van een commentaar waar die file dan nog verder gebruikt wordt en waar het closen wel plaats vindt, zodat iemand anders dat ook weer terug kan vinden.
Als je uitlegt wat je doet, is of je code onduidelijk, of heeft de lezer gewoon een goed boek nodig.
Ook niet helemaal mee eens. Je moet er van uit kunnen gaan dat de persoon die je code leest de taal machtig is, dus dat hoef je niet uit te leggen. Maar als commentaar in een functie even uitleggen wat je aan het doen bent kan geen kwaad.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int f::longandcomplex()
{
  // Gather resources
  .
  .
  .

  // Process data we loaded, sort it and remove duplicates. Then update
  // indexes in the second array
  .
  .
  .

  // Calculate the result
  .
  . 
  .
  return nRes;
}

Natuurlijk moet je niet uitleggen wat je individuele instructies doen. In het voorbeeld wat je geeft is inderdaad het commentaar onzinnig, maar zoals hierboven vertellen wat stukken functie doen is imo absoluut zinnig.
Als je uitlegt hoe je iets doet, loop je het risico dat de code out of sync raakt met het commentaar.
Dat ligt er een beetje aan. Ik heb ooit een stukje code geschreven wat uit een bos met triangles (miljoenen) een setje meshes maakt met ongeveer 1000 driehoeken per mesh. Daar voor moet er redelijk wat gezocht worden in de grote buffer, en het eindresultaat moet weer geoptimaliseerd worden naar een set met vertices en een index buffertje. Het heeft dan wel zin om niet alleen per functie te beschrijven wat hij doet, maar om ook de uitleg in grote lijnen ergens in de code op te nemen...
hamsteggot schreef op maandag 29 mei 2006 @ 10:49:
• Single point of exit (dus maar 1 return statement)
Niet mee eens... maar ik hanteer zelf de strategie zoals eerder ook al genoemd in dit topic:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool f::f(int a, int b, int c)
{
  // Do we have to calculate?
  if (a < b && c > a) return false;

  bool bRes = false;
  . 
  .
  .
  // calculate
  .
  .
  .
  return bRes;
}

Dus exit points aan het begin en aan het eind, maar over het algemeen niet ergens in het midden.
• Altijd booleans checken tegen hun waarde (a==true)
Nee. Het logisch naamgeven van booleans maakt dit overbodig imo.
• Altijd nieuwe context in {} zetten, ook bij 1 statement
Ook mee oneens. Behalve als het de leesbaarheid van een stuk code heel erg bevordert (met een aantal geneste ifs bijv).
• Nooit meerder statements op 1 regel (for loop is uitzondering, ++=1 statement)
Ook oneens.
C++:
1
2
3
4
5
6
7
8
  // Liever dit...
  while (m_pListHead) DeleteNode();

  // Dan
  while (m_pListHead != NULL)
  {
    DeleteFirstNode();
  }
• Functies nooit aanroepen met berekeningen in de parameter list (drukaf(2*b+1);)
Ook niet mee eens. Tenzij het enorme lijsten met berekeningen zijn of dingen met bij-effecten. Jouw voorbeeld vind ik dus prima, maar iets als:
C++:
1
2
  v = Functie(i++, ++j, DeleteHeadNode() 
         ? CreateList() : SomethingElse());

Dat weer liever niet :)
• else...if constructies die meer als twee keer genest zijn, verbieden.
Enigszins mee eens. Het is vaak beter nog eens naar dat soort code te kijken, aangezien het meestal veel simpeler en leesbaarder op te schrijven is.

  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

.oisyn schreef op dinsdag 30 mei 2006 @ 12:39:
[...]

Tja...
<snip c++ code>
Wat mijn eerdere punt weer bewijst :)
Mijn C++ is zo roestig als de Titanic, maar het idee is hetzelfde zover ik kan zien :) Ik vind reperterende code voor error-afhandeling gewoonweg vreselijk, en als je vervolgens dingen in de struct aanpast moet je alle condities weer af. Dit is wat mij betreft ook meteen de enige correcte toepassing van een goto.

  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

hamsteggot schreef op maandag 29 mei 2006 @ 10:49:
• Functies nooit aanroepen met berekeningen in de parameter list (drukaf(2*b+1);)
Dit heeft er meer mee te maken dat in C je geen waarde van een object meer dan 1 keer mag veranderen zonder sequence point :

C:
1
a[i] = i++;


geeft dus undefined behaviour. Een ander issue waarom dat wel eens wordt gezegd is dat als er macro's worden gebruikt die het gedrag van een een programma kunnen veranderen afhankelijk van defines. Verder hou ik als regel aan : als het leesbaar is is het acceptabel.

  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

hamsteggot schreef op maandag 29 mei 2006 @ 20:59:
in c voorkomt dit grove fouten. Een goede compiler geeft different types als dit bij een assignment of conditie wordt gebruikt. Nog mooier is het om de constante voor de variabele te zetten; true == a. Als er een '=' vergeten wordt zal de compiler klagen over constant can not be assigned a value.
Een kwestie van warnings aanzetten, en het liefs elke warning een error laten zijn. Ik compile standaard alle mijn code op die manier.
Na 15 jaar professioneel programmeren ben ik ook hier niet meer mee eens. In den beginne riep ik dit ook test suites kunnen alles ... dacht ik. Maar als je ziet in de statistieken waar de grootste hoeveelheid niet functionele fouten direct te vinden is, is dat in de stijl van programmeren. Bij duizenden regels code, kun je niet alles meer testen. Code reviews worden voor mij een steeds zwaarder punt om de echte winst te pakken op niet functionele fouten en een duidelijke stijl is dan nodig om met elkaar 1 soort code op te leveren.
Gedeeltelijk. Functies moeten simpel zijn en een ding doen. Als je iets doet op een socket, en die moet connected zijn, check daar dan ook, en assert() of abort() als dat niet het geval is. Vervolgens in dezelfde functie een connectie opbouwen is echt not-done wat mij betreft.

Mijn code staat vol met assert()'s, en verder is valgrind echt een uitkomst : Het spaart echt uren zoekwerk naar obscure bugs.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

igmar schreef op dinsdag 30 mei 2006 @ 13:29:

Mijn C++ is zo roestig als de Titanic, maar het idee is hetzelfde zover ik kan zien :) Ik vind reperterende code voor error-afhandeling gewoonweg vreselijk, en als je vervolgens dingen in de struct aanpast moet je alle condities weer af. Dit is wat mij betreft ook meteen de enige correcte toepassing van een goto.
Mijn punt was juist dat je die goto's niet nodig hebt in modernere talen met destructors of iets aanverwants :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
.oisyn schreef op dinsdag 30 mei 2006 @ 12:47:
Wheehehe, C++ OO vind je niet goed maar PHP OO is op de goede weg? :D
Iets zegt me dat je toch niet zo heel erg op de hoogte bent van C++. Zie m'n code hierboven, het is niet alleen een toegevoegde OO, het is een heel ander (en veilig) paradigima waar je in programmeert (kunt programmeren eigenlijk).
Je geeft je eigen antwoord al: ...kunt... met C++ kun je op eenzelfde gestructureerde manier programmeren als Java en daar zit een enorme kracht, de structuren zijn echter zo loose dat je er net zo makkelijk kunt mixen met native (> kans op fouten). Het statement: de beste subset van C++ is C is provocerend maar bevat een kern van waarheid. Op dat punt hinkt PHP op dit moment ook nog (en is dus nu niet beter als C++, vanuit functionaliteit bekeken) maar de discussies die gevoerd worden bij de doorontwikkeling van deze taal gaan de goede kant op (vind ik, mag ik me ook eens positief opstellen ;) ).

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • Mithrandir
  • Registratie: Januari 2001
  • Laatst online: 17-02 18:22
Ik heb geen idee waarom je denkt dat PHP een taal is die ook maar enigszins geschikt is voor bedrijfscritische toepassingen. Als je Java loose vindt, het C++ al te veel 'makkelijke features' vindt hebben, denk ik dat je PHP totaal niet kent.

Je hebt een goede programmeer nodig om ervoor te zorgen dat je code duidelijk en leesbaar in elkaar zit. Ook is de OO nog lang niet waar ik het graag heen zou zien gaan. En dan hebben we het nog niet over loose typing.

[ Voor 13% gewijzigd door Mithrandir op 30-05-2006 14:12 ]

Verbouwing


  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

.oisyn schreef op dinsdag 30 mei 2006 @ 13:50:
Mijn punt was juist dat je die goto's niet nodig hebt in modernere talen met destructors of iets aanverwants :)
Inderdaad. In niet zulke moderne talen is mijn constructie denk ik het beste alternatief :) In C++ heb ik het eigenlijk ook altijd op een soortgelijke manier als jouw voorbeeld gedaan.

  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
Mithrandir schreef op dinsdag 30 mei 2006 @ 14:11:
Ik heb geen idee waarom je denkt dat PHP een taal is die ook maar enigszins geschikt is voor bedrijfscritische toepassingen. Als je Java loose vindt, het C++ al te veel 'makkelijke features' vindt hebben, denk ik dat je PHP totaal niet kent.

Je hebt een goede programmeer nodig om ervoor te zorgen dat je code duidelijk en leesbaar in elkaar zit. Ook is de OO nog lang niet waar ik het graag heen zou zien gaan. En dan hebben we het nog niet over loose typing.
Dat zijn een berg aannames zeg.
1. Java is niet loose, een van de zuiverste talen die ik ken (op een paar logische programmeertalen na). Herlees de zin even want zo als jij het schrijft staat het er niet. Java is echter te traag voor critische toepassingen en interfacing met hardware is moeilijk.
2. Tja, mijn kennis over PHP ... ik zal nooit beweren dat ik een taal ken maar geloof wel dat ik mijn weg weet in PHP. Het gemak waarmee bij PHP native en objecten door elkaar kunnen lopen (zie ook C++) is zeker geen plus maar er zijn stromingen die daar aan werken ... dat ze het probleem onderkennen vind ik een grote plus. Wat er uitkomt dat weet ik ook niet en kan wel de grootste bagger in jaren zijn.
3. PHP voor bedrijfscritische toepassingen ... heb ik nergens beweerd ... en hangt er vanaf. Ik werk op dit moment aan een totaal oplossingen voor web-based projectmanagement in een project team en geloof er wel in. Een heel critisch proces met veel database interacties en pittige berekeningen; Basis is PHP, en ook JS en Java lopen vrolijk door elkaar. Wat is critisch? Voor het maken van programma's voor hardware kan PHP niet wat er bestaat geen PHP (cross)compiler. PHP voor embedded toepassingen... dat zou leuk zijn :Y) .

Het is mijn ervaring dat een programmeertaal geschikt is voor een bepaald toepassingsgebied. De talen onderling bekijkend zijn ze geen van allen perfect ... ik heb ook geen voorkeur voor een taal. Je moet kijken naar je doel en daar de juiste taal bij pakken.

Critisch zijn over een taal vind ik wel heel belangrijk, voor- maar ook nadelen kennen. Goede coding conventions hebben voorkomen bepaalde programmeer fouten en daar gaat dit topic over.

[ Voor 3% gewijzigd door hamsteg op 30-05-2006 14:46 ]

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 20-02 23:20
hamsteggot schreef op dinsdag 30 mei 2006 @ 14:44:
[...]
Java is echter te traag voor critische toepassingen
Dan ben ik benieuwd naar jouw definitie van kritische toepassingen, want voor de ontwikkeling van enterprise software is Java toch een van de populairste platformen.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 00:09

Janoz

Moderator Devschuur®

!litemod

Ik denk dat hamsteggot met kritisch hier meer embedded en realtime applicaties bedoeldt.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Mithrandir
  • Registratie: Januari 2001
  • Laatst online: 17-02 18:22
hamsteggot:

Okee, daar heb je wel een aantal punten waarin ik je gelijk moet geven. Sommige aannames van mij waren inderdaad een beetje uit de lucht gegrepen.

Bij punt 1 heb ik je dan inderdaad verkeerd begrepen over Java.
2: De mensen die achter PHP zitten vind ik niet bepaald de goede weg in gaan. Sommige dingen pakken ze wel redelijk goed aan, zoals het verbeteren van het belachelijke OO-design van PHP4, maar in mijn ogen blijven ze teveel backwards compatible (maar niet helemaal, dus je code breekt met nieuwe versies toch nog).
3: Als je een goed team hebt kun je wel op PHP vertrouwen, dat geloof ik zeker. Een van de grootste problemen van PHP is natuurlijk de enorme userbase met prutsers, waardoor er enorm veel code te vinden is die totaal niet safe of secure is. En dat haalt de taal als geheel toch ook naar beneden.

Over iets heel anders:
Ik snap nog steeds niet waarom je het volgende checkt:
code:
1
2
if(true == isValid) { //doe iets
}


In plaats van gewoon
code:
1
2
if(isValid) { // doe iets
}


Wat is het voordeel? Leesbaarder wordt het er niet van, minder gevaarlijk? Ik weet geen voorbeeld waarbij het beter werkt dan als je het vergelijkt met true.
Nu zal dit misschien per taal verschillen, maar ik zou graag een voorbeeld zien :)

Verbouwing


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Och, zolang de PHP-devs aan het overwegen zijn om namespaces in te voeren, blijft PHP m.i. gewoon een Q&D-platform. Dat, en andere redenen.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 00:09

Janoz

Moderator Devschuur®

!litemod

Enige echte voordeel is dat je een foutmelding krijgt wanneer je een enkele = gebruikt ipv een ==. Bij een enkele = probeer je iets aan een constante toe te kennen en dat wil niet.

Ikzelf gebruik het niet zo. Een andere variant hierop echter wel:

code:
1
2
3
if ("constantewaarde".equals(var)){ 
  //code
}

Door juist de equal methode van de constante aan te roepen is gegarandeerd dat deze niet null is en dus geen nullpointer op kan gooien.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
Volledig uitgewerkt voor Mithrandir:
C kent geen type boolean. Vaak is het een typedef / enum (=integer).
C:
1
2
3
4
if (true == isValid) 
{ 
  //doe iets 
}

De controle is expliciet nodig omdat in een integer range meer getallen vallen dan 0 en 1. Bij getallen geldt verder dat if( 0 ) --> foute conditie, if( elk-ander-getal ) --> goede conditie. Toch geven functies vaak precies het omgekeerde terug 0 = geen fout en elk ander getal geeft een error code terug. Dit wordt vaak door elkaar gehaald. Je moet gewoon testen op je enum types (nadeel van C).

Voor de C taal is het volgende allemaal goed
if ( var )
if ( var=int )
if ( var==int )
if ( !var )
if ( !int)
if ( var=!int )
Met name de tweede en de zesde regel zijn vaak type-fouten (een assignment in een if is echt dirty programmeren). door een integer voorop te zetten:
if ( int = var )
if ( int = !var )
Zal de compiler klagen over: (const) int value can not be assigned a value. Een truukje om type fouten te voorkomen.

[ Voor 8% gewijzigd door hamsteg op 30-05-2006 16:35 ]

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 20-02 09:23

LauPro

Prof Mierenneuke®

.oisyn schreef op dinsdag 30 mei 2006 @ 11:49:
Euh, overzichtelijkheid heeft ook een groot deel met leesbaarheid te maken, dus hier spreek je jezelf een beetje tegen. Door alle lege regels uit m'n code weg te halen en alle accolades op dezelfde regel te laten beginnen wordt het echt niet overzichtelijker. Net als een boek niet overzichtelijker wordt als hij zonder alinea's geschreven wordt, terwijl er toch echt minder informatie op een pagina past.
Laat ik het zo uitleggen: ik ben vang mening dat je uiteraard indien mogelijk je regels zo kort mogelijk moet houden, maar er moet geen absoluut zijn (zoals bijv. 80 karakters op 1 regel). En beetje editor line-wrapt alle regels die te lang zijn voor je viewport. In mijn geval stel ik bijvoorbeeld in dat wanneer een regel langer is dan 80% van de viewport, dat deze gewrapped wordt (en dit is ook duidelijk visueel aangegeven). (Ook @hamsteggot overigens.)
C++:
1
2
3
4
// if (conditie)
{
    // code
}

Dat werkt niet als de { op dezelfde regel als de if() staat.
Klopt, maar waarom zou je dit willen? Ik zie hier aantal hele grote gevaren. Door juist die accolades op dezelfde regel te plaatsen voorkom je dat blokken worden uitgevoerd welke niet uitgevoerd zouden moeten mogen.
Overigens is dit ook wel te bereiken door true || vooraan de conditie toe te voegen als ie altijd uitgevoerd moet worden, of false && als ie nooit uitgevoerd moet worden
Dit is in mijn ogen al een wat elegantere methode, al hoewel het het beste is om gewoon even het hele blok te commenten imo.

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

hamsteggot: Fijn dat je nu wat punten herhaalt die al 34x eerder in de topic zijn genoemd ;)
LauPro schreef op dinsdag 30 mei 2006 @ 16:32:
Klopt, maar waarom zou je dit willen? Ik zie hier aantal hele grote gevaren. Door juist die accolades op dezelfde regel te plaatsen voorkom je dat blokken worden uitgevoerd welke niet uitgevoerd zouden moeten mogen.
Tja, dan kan ik alleen maar vermoeden dat je nooit echt heel erg veel met debugging bezig bent geweest. Soms wil je namelijk juist even dat code altijd wordt uitgevoerd. Accolades op de volgende regel faciliteren dat mooi. Eveneens voor de andere punten die in aandroeg, namelijk het rondkopiëren van blokken code (komt bij refactoring nogal eens voor is mijn ervaring). Maar goed, ieder z'n meug, uiteindelijk is het niets meer dan personal preference :)

[ Voor 101% gewijzigd door .oisyn op 30-05-2006 16:36 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

hamsteggot schreef op dinsdag 30 mei 2006 @ 16:25:
Zal de compiler klagen over: (const) int value can not be assigned a value. Een truukje om type fouten te voorkomen.
Totaal een non-argument als je het mij vraagt : een assignment levert altijd true op, en een beetje compiler geeft daar gewoon een warning op in combinatie met een if(). Verder is een enum gebruikt als boolean een cosmetisch iets : true is alles ongelijk aan 0.

  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
ZeRoXcOoL schreef op dinsdag 30 mei 2006 @ 12:14:
hamsteggot, ik ben eerlijk gezegd wel benieuwd naar wat voor een software jij ontwikkelt. Als ik het zo hoor is het behoorlijk mission-critical, kun je daar misschien iets over kwijt?
Het is apparatuur die je niet zomaar even open kunt halen om een stukje hardware weer in de regeling te leggen. Rontgen zou een voorbeeld kunnen zijn, dat is meer human-critical :)

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

igmar schreef op dinsdag 30 mei 2006 @ 16:38:
een assignment levert altijd true op
Nee hoor, een assignment levert de geassignde variabele op. Als je dus 0/false/NULL aan iets assignt zal dat dus ook het resultaat zijn van de conditie.
C:
1
2
3
4
if (a = 0)
{
   // deze code wordt nooit uitgevoerd
}


Overigens vind ik het niet zo heel vreemd om een assignment én een check in een if te zetten
C++:
1
2
3
4
5
6
7
void foo(Base * b)
{
    if (Derived * d = dynamic_cast<Derived*>(b))
    {
        // Het is een Derived, doe er iets mee
    }
}

Handig voor een operator==() implementatie. Als je de definitie van d buiten de if zou plaatsen clutter je de omliggende scope alleen maar met onzinnige variabelen. Daarnaast heb je geen keuze als het runnen van de destructor van d (hier niet relevant omdat het een pointer betreft) essentieel is voor er verder gegaan wordt met de code na de if.

[ Voor 51% gewijzigd door .oisyn op 30-05-2006 16:59 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
igmar schreef op dinsdag 30 mei 2006 @ 16:38:
[...]Totaal een non-argument als je het mij vraagt : een assignment levert altijd true op, en een beetje compiler geeft daar gewoon een warning op in combinatie met een if(). Verder is een enum gebruikt als boolean een cosmetisch iets : true is alles ongelijk aan 0.
Wat jij wil ... ik heb het niet verzonnen maar sta er wel achter. Als je bij gebrek aan een boolean type zelf een boolean creert moet je hem ook altijd als zodanig behandelen en niet stiekum toch als integer. Dit is gewoon een belangrijk gebrek geweest in de C standaard.

@.oisyn, grr je weet ook altijd de goede uitzondering te pakken :) Er zijn wel meer goede mogelijkheden, maar over het algemeen ....

[ Voor 10% gewijzigd door hamsteg op 30-05-2006 16:54 ]

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • Ivo
  • Registratie: Juni 2001
  • Laatst online: 14-01-2025

Ivo

Waarom zijn goto's achterhaald? Even een Delphi-voorbeeld analoog aan wat ik vandaag nodig had.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
for i := 0 to List.Count - 1 do
begin
  if (P(List[i]) then
  begin
    val := i;
    goto out
  end
end;
Assert(False,'we didnt find an item in List satisfying P');
out:
//Do some other stuff


Dit is de reden waarom in Python de for-else constructie is ingevoerd.
Python:
1
2
3
4
5
6
for i in range(0,list.length):
  if p(list[i]):
    val = i
    break
else:
  Assert(false)

[ Voor 10% gewijzigd door Ivo op 30-05-2006 19:14 ]


  • Mithrandir
  • Registratie: Januari 2001
  • Laatst online: 17-02 18:22
Ivo schreef op dinsdag 30 mei 2006 @ 19:12:
Waarom zijn goto's achterhaald? Even een Delphi-voorbeeld analoog aan wat ik vandaag nodig had.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
for i := 0 to List.Count - 1 do
begin
  if (P(List[i]) then
  begin
    val := i;
    goto out
  end
end;
Assert(False,'we didnt find an item in List satisfying P');
out:
//Do some other stuff


Dit is de reden waarom in Python de for-else constructie is ingevoerd.
Python:
1
2
3
4
5
6
for i in range(0,list.length):
  if p(list[i]):
    val = i
    break
else:
  Assert(false)
Het probleem is dat je 'spaghetticode' krijgt als je niet oppast; je moet heel erg goed opletten waar je heen gaat bij bepaalde waardes, dus het wordt een soort van spoorzoeken. Dat is het nadeel. Ook ga ik er van uit dat de normale flow van je programma je 'alles gaat goed' scenario is. In dit geval zie ik een fout-assertion, die ik eigenlijk niet zou verwachten; alles ging toch goed? Dan lees ik nog eens terug en zie dat er gesprongen wordt naar buiten de loop. Maar zulke dingen kunnen ook een kwestie van gewenning zijn.

Hamsteggot:
Ik snap het, maar nog steeds snap ik niet waarom je de hele == true waarde erbij haalt. Bij een taal die booleans ondersteunt, en een functie die altijd een boolean returnt of een variabele die een boolean is, is het checken van de waarde in mijn ogen totale onzin en leidt het tot minder goed leesbare code. Voor C kan ik het nu begrijpen, maar dat is in mijn ogen een speciaal geval (dwz: geldt voor C, maar niet algemeen voor alle talen)

[ Voor 13% gewijzigd door Mithrandir op 30-05-2006 20:09 ]

Verbouwing


Verwijderd

Ivo, dat lijkt me een vrij zinloos gebruik van een goto... Wat is er mis met:
Delphi:
1
2
3
4
5
6
7
8
9
val := -1;
for i := 0 to List.Count - 1 do begin
  if (P(List[i]) then begin
    val := i;
    break;
  end
end;
Assert((val > -1), 'we didnt find an item in List satisfying P');
// Do some other stuff

Dan gebruik je Assert() ook nog waar 't voor bedoeld is: checken of iets mag, en zo nee een exception raisen.

[ Voor 5% gewijzigd door Verwijderd op 30-05-2006 20:46 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ivo schreef op dinsdag 30 mei 2006 @ 19:12:
Waarom zijn goto's achterhaald? Even een Delphi-voorbeeld analoog aan wat ik vandaag nodig had.
Dan had je even wat harder na moeten denken.
Delphi:
1
2
3
4
5
6
7
8
for i := 0 to List.Count - 1 do
begin
  if (P(List[i]) then
  begin
     //Do some other stuff
  end
end;
Assert(False,'we didnt find an item in List satisfying P');

Of nog beter, de conditie checken in je assert zelf.
Dit is de reden waarom in Python de for-else constructie is ingevoerd.
Geldt dat niet alleen als die range leeg is (of in het algemeen: als de for geen enkele iteratie doorloopt). Als er een range bestaat doorloopt ie weldegelijk iteraties, waarvan de meeste gecanceled worden in de eerstvolgende if. Lijkt me stug dat die else wordt uitgevoerd zodra alle condities in die eerste if false opleveren.

.edit: ah, heb het even opgezocht, de else wordt altijd uitgevoerd, tenzij je uit de lus breakt. Best handig :)

[ Voor 10% gewijzigd door .oisyn op 30-05-2006 20:51 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.Oisyn, dan zul toch na die "//Do some otther stuff" uit de for-lus moeten springen en die Assert() ontwijken. :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ja, met een return bijvoorbeeld :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Ivo
  • Registratie: Juni 2001
  • Laatst online: 14-01-2025

Ivo

Ja, in dit pseudocode geval kon het makkelijk anders, maar de do_some_oher_stuff was erg groot in dit geval en die heb je liever niet zo diep geindenteerd.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20-02 23:46

Creepy

Tactical Espionage Splatterer

De grootte van een stuk code maakt het ok om een goto te gebruiken op een plek waar deze totaal niet nodig is? Vaak kan je door slim je code op te splitsen en het weer in te delen in kleinere (logische) delen je code een stuk beter leesbaar maken in vergelijking met die lap code en een goto :)
En met een indeling in iets meer functies heb je ook meteen het probleem van (te) diepe nesting al deels opgelost. Dit is ook een reden waarom er bedrijven zijn die als onderdeel van een coding standaard hebben opgenomen dat een functie/method niet langer mag zijn dan x regels bijv. Zo wordt je gedwongen om je code logisch in te delen i.p.v. er 1 lange lap van te maken.

"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


  • Ivo
  • Registratie: Juni 2001
  • Laatst online: 14-01-2025

Ivo

Als ik het stuk bewuste code opzoek dan had het inderdaad gekund, zoals AfterLife zei, maar de goto is daar in principe op zijn plaats.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        for i := 0 to Length(Adjs) - 1 do
        begin
          for j := 0 to Length(Adjs[i]) - 1 do
          begin
            ID := Adjs[i][j];
            for h := 0 to Areas.Count - 1 do
            begin
              if ((Areas.Items[h] as TArea).FID = ID) then
              begin
                  a := h;
                    goto out_here;
              end
            end;
            Assert(False);
          out_here:
            (Areas.Items[i] as TArea).FAdjacentAreas.Add(Areas.Items[a]);
          end;
        end;

In principe wil je een `break 2' uitvoeren, maar dat gaat in Delphi niet zover ik weet.

[ Voor 7% gewijzigd door Ivo op 30-05-2006 23:53 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ivo schreef op dinsdag 30 mei 2006 @ 23:08:
Ja, in dit pseudocode geval kon het makkelijk anders, maar de do_some_oher_stuff was erg groot in dit geval en die heb je liever niet zo diep geindenteerd.
Een perfecte kandidaat voor een functie dus? Daarnaast zei kwam Afterlife met een voorbeeld dat ik ook aankaartte: checken op val==-1 in de Assert. Een assert heeft niet voor niets een dergelijke constructie :)

Daarnaast kun je ook vaak gewoon variabelen gebruiken om uit meerdere nesten diep te springen (mocht de taal daar niet in voorzien muv goto):
C++:
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
void foo()
{
    bool found = false;

    for (int i = 0; !found && i < x; i++)
    {
        for (int j = 0; !found && j < y; j++)
        {
            for (int k = 0; k < z; k++)
            {
                if (condition(i, j, k))
                {
                    found = true;
                    break;
                }
            }
        }
    }

    if (!found)
    {
        error();
        return;
    }

    // do some stuff
}

Efficientie is geen issue, een goede C++ compiler zal hier handelen alsof je gewoon een goto hebt gebruikt.

goto is maar voor één ding echt bruikbaar, en dat is voor gegenereerde code (bijv. compilers die script code omzetten naar C of C++ code). De overige gevallen dat je ze nodig hebt zijn echt extreem zeldzaam (ik geloof dat ik 'm in de afgelopen 10 jaar 1x heb gebruikt, en zelfs toen was het twijfelachtig). Sommige talen kennen zelfs geeneens een goto, Java bijvoorbeeld.

[ Voor 15% gewijzigd door .oisyn op 30-05-2006 23:59 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 10:19
Ik ben het met .oisyn eens moet ik zeggen. Mijn indenting ziet er meestal zo uit:

PHP:
1
2
3
4
5
6
7
8
if($drink->type == beer)
{ // Zuip je klem
  zuip($drink);
}
else
{ // iets anders 
  ...etc
}


Ivm debugging is het heel fijn, en ik heb meteen een goed plekkie in de code voor wat commentaar.

Overigens, over dat breaken uit code-blokken. Ikzelf doe het ook regelmatig in mijn php code, omdat ik het wel makkelijk vind. Maar als je het echt netjes wilt doen dan zet je een boolean in je guard erbij natuurlijk.

[ Voor 27% gewijzigd door Grijze Vos op 30-05-2006 23:59 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
igmar schreef op dinsdag 30 mei 2006 @ 13:37:
[...]
[Functies nooit aanroepen met berekeningen in de parameter list (drukaf(2*b+1);)]

Dit heeft er meer mee te maken dat in C je geen waarde van een object meer dan 1 keer mag veranderen zonder sequence point :

C:
1
a[i] = i++;

geeft dus undefined behaviour.
Staat volledig los van elkaar. In C heb je een sequence point bij de aanroep van een functie, nadat alle parameters zijn geevalueerd en voordat het eerste statement in de functie wordt uitgevoerd. In jouw voorbeeld wordt er geen functie aangeroepen. Bovendien leveren pure berekeningen als (2*b+1) geen sideeffects op, en staan ze dus sowieso los van sequence points.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

MSalters schreef op woensdag 31 mei 2006 @ 00:35:
[...]

Staat volledig los van elkaar. In C heb je een sequence point bij de aanroep van een functie, nadat alle parameters zijn geevalueerd en voordat het eerste statement in de functie wordt uitgevoerd. In jouw voorbeeld wordt er geen functie aangeroepen.
Hoezo is dat relevant ? In mijn voorbeeld modificeer je nog steeds 2 keer dezelfde variabele zonder een sequence point, die pas eindigd na de ; Da's undefined behaviour, da's mijn punt, en dat ben ik wel eens tegengekomen in functieaanroepen.

Goed, ik deel het standpunt niet dat je geen berekeing in je argumenten moet doen, maar mijn voorbeeld heb ik soortgelijk wel eens in code gezien. Een groter gevaar is macro's in argumenten als je het mij vraagt.


Bovendien leveren pure berekeningen als (2*b+1) geen sideeffects op, en staan ze dus sowieso los van sequence points.[/quote]

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 20-02 14:32
Janoz schreef op dinsdag 30 mei 2006 @ 15:54:
Ik denk dat hamsteggot met kritisch hier meer embedded en realtime applicaties bedoeldt.
Toch wel grappig wanneer je bedenkt dat Java oorspronkelijk ontwikkeld is als oplossing voor embedded en realtime toepassingen.

He wat? Ja serieus, daar is Java oorspronkelijk voor ontwikkeld.

Voorbeelden embedded: Mobiele telefoons, Java is de grootste speler op die markt.
Voorbeelden realtime: ben er niet zo in thuis, maar er zijn vast uitstekende realtime Java oplossingen te vinden waarin je meer controlle hebt over scheduling gerelateerde zaken. Om nog maar niet te beginnen over semi realtime systemen.

Overigens is de snelheid van Java niet een discussie waar ik aan wil beginnen. Persoonlijk heb ik absoluut geen problemen mee. Want ik bouw geen systemen waarin ik die absolute controle nodig heb. Er zijn denk ik extreem weinig toepassingen te bedenken die echt keiharde realtime restricties hebben. In de meeste gevallen zal een verwerking binnen een miniem kleine tijdspanne al voldoende zijn en maakt het niet uit of dit een milliseconde eerder of later is, als het maar binnen x milliseconden gebeurt.

Edit: Of begin ik nu toch een discussie. In dat geval: never mind, terug on-topic.

[ Voor 4% gewijzigd door The - DDD op 31-05-2006 10:49 ]


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 20-02 14:32
igmar schreef op woensdag 31 mei 2006 @ 08:39:
[...]


... Een groter gevaar is macro's in argumenten als je het mij vraagt.
...
Dus een kwestie van clean macro's definiëren. Als in (veel (haakjes (gebruiken))).

offtopic:
Hehe, eindelijk snap ik weer hoe ik moet posten :+

[ Voor 30% gewijzigd door The - DDD op 31-05-2006 10:54 ]


  • Exirion
  • Registratie: Februari 2000
  • Nu online

Exirion

Gadgetfetisjist

.oisyn schreef op maandag 29 mei 2006 @ 23:21:
En leuk, dat voorbeeld van de 386, maar je loopt daar even aan het feit voorbij dat de gemiddelde applicatie van toen slechts een fractie van de hoeveelheid code waren van de applicaties van nu.
Nou en? Zijn statement/mening blijft daarmee nogsteeds overeind. Hij zegt precies wat jij ook zegt: de verhouding tussen code size/complexity en processing speed loopt scheef. Aan die size/complexity kun je zeker wat doen, maar onderhand is iedereen het er ook wel overeens dat veel software net zo goed qua performance slecht in elkaar steekt.

Jij maakt je met het verdedigende argument 'jah, maar vroeger was alles ook veel korter en simpeler' net zo schuldig aan performance-verloedering als veel hedendaagse ontwikkelaars. Ik erger me vaak aan mensen, ook collega's, die maar blijven roepen dat computer snel zat zijn dus dat het niet boeit. Onzin! Feit is en blijft dat, ondanks de enorm toegenomen mogelijkheden, veel mensen zich eraan erger dat alles op die oude DOS PC toch sneller ging dan met de moderne PC met x GHz, x GB RAM en een paar honderd GB aan harddisks. Daar kun je moeilijk je ogen voor sluiten.

Ik vind dat teveel ontwikkelaars vanuit hun eigen perspectief naar software kijken en niet door de ogen van de gebruiker.

"Logica brengt je van A naar B, verbeelding brengt je overal." - Albert Einstein


  • Ivo
  • Registratie: Juni 2001
  • Laatst online: 14-01-2025

Ivo

igmar schreef op woensdag 31 mei 2006 @ 08:39:
[...]


Hoezo is dat relevant ? In mijn voorbeeld modificeer je nog steeds 2 keer dezelfde variabele zonder een sequence point, die pas eindigd na de ; Da's undefined behaviour, da's mijn punt, en dat ben ik wel eens tegengekomen in functieaanroepen.

Goed, ik deel het standpunt niet dat je geen berekeing in je argumenten moet doen, maar mijn voorbeeld heb ik soortgelijk wel eens in code gezien. Een groter gevaar is macro's in argumenten als je het mij vraagt.


Bovendien leveren pure berekeningen als (2*b+1) geen sideeffects op, en staan ze dus sowieso los van sequence points.
code:
1
a[i] = i++;

Dit levert helemaal geen ongedefinieerd gedrag op. Dit is equivalent aan:
code:
1
a[i] = i; i++;

[ Voor 4% gewijzigd door Ivo op 31-05-2006 11:11 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Exirion schreef op woensdag 31 mei 2006 @ 11:04:
Jij maakt je met het verdedigende argument 'jah, maar vroeger was alles ook veel korter en simpeler' net zo schuldig aan performance-verloedering als veel hedendaagse ontwikkelaars.
Toch beter lezen dan. Ik stel dat onderhoudbaarheid en ease of use van code en libraries met grote projecten belangrijker is dan bij kleine projecten. In dat opzicht lever je wat voor performance in, maar win je tegelijkertijd met development-tijd en onderhoud. Dat er ondertussen applicaties worden ontwikkeld die "ranzig traag" zijn (maar niet zo ervaren worden omdat CPU's toch snel genoeg zijn) omdat er geen aandacht is besteed aan het schrijven van degelijke code ontken ik helemaal niet; die applicaties zijn er wel degelijk, en daar zijn er waarschijnlijk ook teveel van. Die wil ik helemaal niet verdedigen, het ging mij slechts om de eerste paar regels van dit relaas.

[ Voor 14% gewijzigd door .oisyn op 31-05-2006 11:14 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 00:09

Janoz

Moderator Devschuur®

!litemod

The - DDD schreef op woensdag 31 mei 2006 @ 10:48:
Toch wel grappig wanneer je bedenkt dat Java oorspronkelijk ontwikkeld is als oplossing voor embedded en realtime toepassingen.

He wat? Ja serieus, daar is Java oorspronkelijk voor ontwikkeld.
StarSeven ;)
Voorbeelden embedded: Mobiele telefoons, Java is de grootste speler op die markt.
Bij embedded moet je meer denken aan de firmware van een mobiele telefoon, niet aan de applicaties die je er op draait. Hiervoor wordt java nog niet tot nauwelijks gebruikt.
Voorbeelden realtime: ben er niet zo in thuis, maar er zijn vast uitstekende realtime Java oplossingen te vinden waarin je meer controlle hebt over scheduling gerelateerde zaken. Om nog maar niet te beginnen over semi realtime systemen.
Bij realtime is het van belang dat je exacte garanties kunt geven wanneer iets gebeurt en wanneer wordt aangegeven dat dit niet gaat lukken. De specificaties van de VM staan dit niet toe. Er zijn wel wegen omheen (door een nieuwe VM te schrijven die extra garanties biedt), maar dan blijft nog wel staan dat java niet de geschikte taal is voor realtime toepassingen.
Overigens is de snelheid van Java niet een discussie waar ik aan wil beginnen. Persoonlijk heb ik absoluut geen problemen mee.
Dat is ook 1 van de grote it mythen en enkel veroorzaakt door de applets eind vorige eeuw. In principe zegt het al genoeg dat MS voor .net eenzelfde executie structuur heeft gekozen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Exirion
  • Registratie: Februari 2000
  • Nu online

Exirion

Gadgetfetisjist

.oisyn schreef op woensdag 31 mei 2006 @ 11:11:
Toch beter lezen dan. Ik stel dat onderhoudbaarheid en ease of use van code en libraries met grote projecten belangrijker is dan bij kleine projecten. In dat opzicht lever je wat voor performance in, maar win je tegelijkertijd met development-tijd en onderhoud. Dat er ondertussen applicaties worden ontwikkeld die "ranzig traag" zijn (maar niet zo ervaren worden omdat CPU's toch snel genoeg zijn) omdat er geen aandacht is besteed aan het schrijven van degelijke code ontken ik helemaal niet; die applicaties zijn er wel degelijk, en daar zijn er waarschijnlijk ook teveel van. Die wil ik helemaal niet verdedigen, het ging mij slechts om de eerste paar regels van dit relaas.
Ok, dan snap ik je. Blijkbaar plaatste ik je uitspraak in een te ruime context :)

"Logica brengt je van A naar B, verbeelding brengt je overal." - Albert Einstein


Verwijderd

.oisyn schreef op dinsdag 30 mei 2006 @ 23:56:
Daarnaast kun je ook vaak gewoon variabelen gebruiken om uit meerdere nesten diep te springen (mocht de taal daar niet in voorzien muv goto):
C++:
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
void foo()
{
    bool found = false;

    for (int i = 0; !found && i < x; i++)
    {
        for (int j = 0; !found && j < y; j++)
        {
            for (int k = 0; k < z; k++)
            {
                if (condition(i, j, k))
                {
                    found = true;
                    break;
                }
            }
        }
    }

    if (!found)
    {
        error();
        return;
    }

    // do some stuff
}
Delphi for-loops ondersteunen zo'n "!found &&" constructie niet, maar met een while-loop is 't ook wel elegant op te lossen:
Delphi:
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
procedure Foo
var
  i, j, k: integer;
  Found: boolean;
begin
  i := -1;
  j := -1;
  k := -1;
  Found := False;
  while ((not Found) and (i < x-1)) do begin
    inc(i);
    while ((not Found) and (j < y-1)) do begin
      inc(j);
      while ((not Found) and (k < z-1)) do begin
        inc(k);
        Found := Condition(i, j, k);
      end;
    end;
  end;
  if not Found then begin
    Error;
    Exit;
  end;
  // do some stuff using the values of i, j and/or k
end;

Geen break nodig, maar je moet wel zorgen dat je i, j en k steeds op 1 waarde lager begint dan je eigenlijk wilt, en dan als eerste binnen de while-loop die waarde ophoogt. Anders worden i, j en k alsnog 1 hoger dan je eigenlijk wilt. Maar al met al een vrij elegante oplossing IMO. :)

[ Voor 3% gewijzigd door Verwijderd op 31-05-2006 22:37 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
igmar schreef op woensdag 31 mei 2006 @ 08:39:
[...]
Hoezo is dat relevant ? In mijn voorbeeld modificeer je nog steeds 2 keer dezelfde variabele zonder een sequence point, die pas eindigd na de ; Da's undefined behaviour, da's mijn punt, en dat ben ik wel eens tegengekomen in functieaanroepen.
...
Bovendien leveren pure berekeningen als (2*b+1) geen sideeffects op, en staan ze dus sowieso los van sequence points.
ik geloof dat we 't met elkaar eens zijn. Ik dacht dat je probeerde uit te leggen waar de "regel" vandaan kwam die drukaf(2*b+1) afkeurde, maar we zijn het dus eens dat dat niets met sequence points te maken heeft.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
Ivo schreef op woensdag 31 mei 2006 @ 11:11:
[...]
code:
1
a[i] = i++;

Dit levert helemaal geen ongedefinieerd gedrag op. Dit is equivalent aan:
code:
1
a[i] = i; i++;
In Java wel, maar niet in C. D'r is ergens een code=c tag weggevallen, maar het stond wel expliciet in de uitleg erbij dat het om C ging.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Ivo
  • Registratie: Juni 2001
  • Laatst online: 14-01-2025

Ivo

Ik dacht dat dit in C ook zo was. Blijkbaar is dit niet zo.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik denk dat dat komt omdat er het idee te ronde gaat dat de post-fix increment (en decrement) betekent dat hij uitgevoerd wordt na het huidige statement. Dat is niet zo. i++ betekent: verhoog i, maar retourneer de vorige waarde. In C++ zou de functie-implementatie er zo uitzien:
C++:
1
2
3
4
5
6
int increment(int & var)
{
    int oldValue = var;
    var += 1;
    return oldValue;
}


De statement a[i] = i++ kun je dan zo lezen:
C++:
1
a[i] = increment(i);

De vraag is dan of de increment functie wordt uitgevoerd vóórdat a[i] wordt geevalueerd. En dat is nou juist niet gedefinieerd in C en C++ (maar wel in Java en C#. In PHP vast ook niet maar daar is het waarschijnlijk ook niet gedefinieerd dat het ongedefinieerd is, if you catch my drift ;))

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

hamsteggot schreef op maandag 29 mei 2006 @ 10:49:
Wat is in jullie ogen een goede balans tussen goede code schrijven en het voor de hobby ook nog een beetje snel afhebben?
Een goede belans is goede code, punt. Zonder compromis. Die is immers sneller af doordat je minder tijd kwijt bent met achteraf fouten opsporen en verbeteren. Het is bekend dat bugs oplossen achteraf (vrijwel) altijd duurder is, dan in een eerder stadium beter werk afleveren. Investeer dus wat tijd om goede code te schrijven. Hoe minder tijd er is om iets te maken, hoe belangrijker dat is!
Belangrijke beperking in deze discussie is wel dat het een consequente keuze moet zijn
Kan misschien niet als je het als eis stelt voor deze discussie ;) maar daar ben ik het niet mee eens. Er zijn alleen maar guidelines en geen regels. Er is bijna altijd wel een uitzondering te verzinnen waarin het alternatief beter werkt. Tuurlijk, als je twijfelt, houdt je dan aan de guidelines want er is natuurlijk wel een reden voor dat die bestaan.

Mijn enige 'regel' is dat je altijd je gezonde verstand moet blijven gebruiken. Helaas lijkt het er op dat er veel mensen zijn die dat niet (of te weinig) hebben :/

Een heel andere manier om goede code af te leveren (thinking out of the box) kan bijvoorbeeld ook iets als Pair Programming zijn. Je zit dan met zijn tweeen achter een machine en schrijft samen de code. De praktijk wijst uit dat dit in veel gevallen heel goed werkt om de kwaliteit van code te verbeteren zonder dat het veel tijd kost (en door de betere kwaliteit dus juist veel tijd bespaart!)

Het is eigenlijk een vorm van continu code reviewen. En waar je normaal met 1 persoon een fout maakt als je even niet oplet, is er bij Pair Programming vrijwel altijd die ander die dan wel zit op te letten. Bovendien leer je van elkaar en vul je elkaar's kennis aan.

Ik heb op eigen initiatief een korte tijd kennis kunnen maken met Pair Programming, maar 'helaas' zit ik nu bij een heel leuk maar kleiner bedrijf waar ik (niet lang meer) de enige echte software developer ben en ik mis af en toe de feedback wel (ondanks dat ik natuurlijk een geweldig programmeur ben ;) )

Silver bullets bestaan niet, maar helaas geloven veel mensen daar wel in - wat blijkt uit iedere nieuwe taal die weer gehyped wordt, en niet waar maakt wat er van verwacht wordt. (Pair Programming is dus ook geen Silver bullet, maar het kan wel helpen)

En probeer af en toe ook een beetje defensief te programmeren. Denk niet te snel dat je bepaalde 'trucs' door-en-door kent en dus altijd foutloos gebruikt. En probeer vooral in de code niet te laten zien hoe slim je bent, dat levert waarschijnlijk de ergste code op...

offtopic:
Mijn 'record' is een stuk C code van ongeveer 1000 regels terug te brengen tot minder dan de helft waarbij de leesbaarheid flink toenam, de executietijd minstens een factor 100 lager was (~ 1 minuut naar <1 seconde) - en het ergste was dat volgens de requirements dat stuk code 'geoptimaliseerd' had moeten zijn omdat de executietijd toch wel belangrijk was. Waarom was die code zo slecht? Omdat iemand zich strikt aan een set coding conventies / regels gehouden had die (vooral voor deze context) slecht gekozen waren.

  • ronaldmathies
  • Registratie: Juni 2001
  • Niet online
Janoz schreef op woensdag 31 mei 2006 @ 11:14:
Bij realtime is het van belang dat je exacte garanties kunt geven wanneer iets gebeurt en wanneer wordt aangegeven dat dit niet gaat lukken. De specificaties van de VM staan dit niet toe. Er zijn wel wegen omheen (door een nieuwe VM te schrijven die extra garanties biedt), maar dan blijft nog wel staan dat java niet de geschikte taal is voor realtime toepassingen.
Even tussendoor, hiervoor is de Java Realtime Specification opgesteld, waarin het wel toegelaten wordt om realtime te kunnen werken.:

http://www.onjava.com/pub...me-java-introduction.html

3015 Wp-z 5360 Wp-nno op 2 x SMA-SB3600 TL-21, Warmtepomp: ERSC-VM2CR2 / PUHZ-SHW140 YHA, WTW Q350, EV Kia Ev6 GT-Line


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

.oisyn schreef op woensdag 31 mei 2006 @ 23:13:
[...]
De vraag is dan of de increment functie wordt uitgevoerd vóórdat a[i] wordt geevalueerd. En dat is nou juist niet gedefinieerd in C en C++ (maar wel in Java en C#. In PHP vast ook niet maar daar is het waarschijnlijk ook niet gedefinieerd dat het ongedefinieerd is, if you catch my drift ;))
In PHP is gedefinieerd dat assignments right to left geevalueerd worden; dus in een geval als:
PHP:
1
$foo = increment($bar);

wordt eerst de functie uitgevoerd en de returnvalue toegekent aan $foo ;)

Intentionally left blank


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Euh, bij je voorbeeld doet de order van evaluation er juist niet toe. Bovendien doet PHP helemaal niet wat jij zegt:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
function increment(&$var)
{
    $old = $var;
    ++$var;
    return $old;
}

$a = array(-1, -1, -1);
$i = 0;
$a[$i] = increment($i);

print_r($a);


output: array(0, -1, -1).
Als increment werd aangeroepen vóórdat $a[$i] geevalueerd werd, zou hij schrijven naar element 1. Hij schrijft echter naar element 0, omdat hij $a[$i] al evalueerd voordat hij increment aanroept. (PHP 4.4.2)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

hmmz, my bad; ik dacht dat het betekende dat increment($i) eerst geeavuleerd zou worden, vervolgens $a[$i] en dat dan pas de assignment plaats zou vinden; het lijkt echter andersom te zijn...

Intentionally left blank


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nou ja dat zou het idd moeten betekenen, maar blijkbaar is het dus niet zo ;)

.edit: heb het even opgezocht, de order van evaluatie staat niet expliciet in de documentatie. Dit wel:
Left associativity means that the expression is evaluated from left to right, right associativity means the opposite.
Maar dat heeft met assocativiteit te maken, niet met evaluatie van de expressies. Right-associative wil zeggen dat a = b = c wordt geparsed als a = (b = c). Parse order staat los van de volgorde van evaluaties (in C# en Java is de = uiteraard ook right-associative, maar beide talen evalueren altijd van links naar rechts - zal me niets verbazen als dat in PHP ook zo is, maar het is gewoon niet gedefinieerd dus daar kun je imho ook niet op vertrouwen)

[ Voor 99% gewijzigd door .oisyn op 01-06-2006 13:17 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

crisp schreef op donderdag 01 juni 2006 @ 12:56:
hmmz, my bad; ik dacht dat het betekende dat increment($i) eerst geeavuleerd zou worden, vervolgens $a[$i] en dat dan pas de assignment plaats zou vinden; het lijkt echter andersom te zijn...
Door defensief te programmeren vermijdt je dit soort constructies omdat het niet impliciet duidelijk is wat er gebeurt (en niet zozeer omdat een coding standard je vertelt dat het niet mag). En als je denkt te weten wat er gebeurt, dan komt er een andere taal die er op lijkt maar het toch weer anders doet. Of er komt een andere programmeur die het niet weet en een bug veroorzaakt door wat hij denkt dat een bug is te verhelpen waardoor het daarna fout gaat :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Niemand beweert het tegendeel, het ging er gewoon even om of PHP het idd definieerde of niet. :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
.oisyn schreef op woensdag 31 mei 2006 @ 23:13:

C++:
1
2
3
4
5
6
int increment(int & var)
{
    int oldValue = var;
    var += 1;
    return oldValue;
}


De statement a[i] = i++ kun je dan zo lezen:
C++:
1
a[i] = increment(i);

De vraag is dan of de increment functie wordt uitgevoerd vóórdat a[i] wordt geevalueerd.
Erger. De opties zijn niet alleen vóór of na, maar ook tegelijkertijd (kan op Itanium e.d.), helemaal niet, onvoorspelbaar (cache race conditie), of nog vreemder gedrag.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
Verwijderd schreef op woensdag 31 mei 2006 @ 23:33:
Mijn enige 'regel' is dat je altijd je gezonde verstand moet blijven gebruiken. Helaas lijkt het er op dat er veel mensen zijn die dat niet (of te weinig) hebben :/

Een heel andere manier om goede code af te leveren (thinking out of the box) kan bijvoorbeeld ook iets als Pair Programming zijn. Je zit dan met zijn tweeen achter een machine en schrijft samen de code.
Deze regel geldt boven alles. Wij programmeren altijd met de guidlines in de hand maar als we daarop afwijken zetten we het er gewoon in commentaar bij ;-) Zolang je maar bewust bent dat je afwijkt is het ok.

Pair programming, of extremer: dual programming. Twee teams werken onafhankelijk van elkaar en schrijven dezelfde code. Als de twee programma's lopen zou je verwachten dat ze niet dezelfde fout maken ... not. Boeing heeft dit ooit eens geprobeerd met twee backup systemen in hun vliegtuigen. Achteraf gezien bleken dezelfde functionele fouten in alle drie de systemen te zitten. De manier van denken blijkt zo in ons geprent te zitten dat we dezelfde fouten maken :(

Reviews hebben wat mij betreft een absolute waarde. De hele dag bij elkaar op schoot zitten heeft minder zin omdat je elkaar dan ook mee neemt in foute denkpatronen. Elkaars code grondig reviewen is zeer effectief! Veel programmeerfouten en een setje aan functionele fouten worden er dan uitgehaald.

offtopic:
Schroeven vastdraaien met een hamer is mij ook nog nooit gelukt ;) Juiste guidlines voor de juiste toepassing is zeer belangrijk.

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


Verwijderd

hamsteggot schreef op vrijdag 02 juni 2006 @ 20:46:
Boeing heeft dit ooit eens geprobeerd met twee backup systemen in hun vliegtuigen. Achteraf gezien bleken dezelfde functionele fouten in alle drie de systemen te zitten. De manier van denken blijkt zo in ons geprent te zitten dat we dezelfde fouten maken :(
Volgens mij wordt deze strategie nog steeds toegepast bij Airbus, waarbij twee onafhankelijke systemen elkaar controleren en instructies pas worden doorgegeven als beide systemen hetzelfde resultaat geven. De ene draait dan op Intel en de andere op Motorola om zodoende eventuele fouten in de processor af te vangen. Dus het is een soort PC/Mac battle maar dan in de lucht :) Weet niet of ze dit nog zo doen, het artikel is jaren oud.

Verwijderd

Tja, pair programming...
Mijn ervaring is dat dat prima werkt wanneer je nieuwe dingen ontwerpt, 2 personen kunnen dan meer bedenken (en van elkaar controleren) dan 1 persoon kan codekloppen.
Maar bij de normale dingen (bestaande code aanpassen of op punten uitbreiden) is m.i. een goede peer review een stuk zinvoller en efficienter.

Neemt niet weg dat ik als programmeur pair programming erg prettig vind om te doen, omdat de uitwisseling van ideeen dan veel directer is dan bij een peer review achteraf.

Verwijderd

hamsteggot schreef op vrijdag 02 juni 2006 @ 20:46:
Pair programming, of extremer: dual programming. [...]
Maar dual programming zoals je het noemt zal in de praktijk als normaal ontwikkelwerk door individuen gedaan worden. Plus natuurlijk dat beide teams afhankelijk zijn van dezelfde (al dan niet) vage requirements van buitenaf waardoor ze dezelfde fouten maken. Dat zal niet veranderen welke manier van werken je ook kiest. Pair Programming is echt iets heel anders dan dual programming.

Alhoewel het misschien contra-intuitief lijkt, is er genoeg materiaal te vinden wat laat zien dat Pair Programming echt werkt* (natuurlijk niet in alle gevallen, maar wel veel en mits het goed opgezet is). Natuurlijk kunnen twee mensen samen tegelijk dezelfde fout maken, maar het is veel minder waarschijnlijk dan dat twee mensen los van elkaar ieder een eigen fout maken. Je kunt het een beetje als een AND-functie zien :) Als een programmeur wel of geen fout kan maken, krijg je de volgende waarheidstabel (P1 en P2 zijn twee programmeurs, Pair is de 'and' functie voor Pair Programming):

P1P2Pair
geen foutgeen foutgeen fout
geen foutwel foutgeen fout
wel foutgeen foutgeen fout
wel foutwel foutwel fout

Als de programmeurs los van elkaar werken en P1 module 1 schrijft en P2 module 2, heb je totaal 4 fouten in de code zitten. Als je echter met Pair Programming werkt, zullen de programmeurs bij rij twee en drie elkaars fouten zien, en dus direct oplossen. Er wordt dan dus maar 1 fout gemaakt bij het schrijven van module 1, en weer 1 bij het schrijven van module 2. Het totaal aantal fouten is dus gehalveerd**.
Reviews hebben wat mij betreft een absolute waarde.
Het nadeel van traditioneel code reviewen is dat dit achteraf pas gebeurt. De programmeur zal dan (vaak) zijn harde werk willen verdedigen en niet geneigd zijn snel iets aan te passen. Bovendien is er tegen die tijd vaak al (deels) getest en wordt het aanpassen van de code in dat stadium als risico (en zinloos extra werk) beschouwd waardoor er weinig van de (zinvolle!) opmerkingen meegenomen wordt.

Bij Pair Programmen review je elkaar's werk live, en kan er dus direct ingegrepen worden als dat nodig is. Overigens wil dat niet zeggen dat de code helemaal niet meer gereviewd hoeft te worden - dat kan immers nog steeds zinvol zijn voor opmerkingen van anderen, en een blik van een afstand. Ik ben het dus wel met je eens dat code reviews heel zinvol zijn - zeker als er weinig andere vormen van controle zijn!

* Zoals bijna altijd zijn er ook gegevens die laten zien dat het niet werkt, dus ik zou zeggen: probeer het eens een tijdje uit op een project en kijk wat je er van vindt (ik heb het gedaan, en ik ben overtuigd :)). Een goed boek om mee te beginnen is Pair Programming Illuminated van Laurie Williams.

** Deze cijfers zijn maar een voorbeeld om het principe uit te leggen. In werkelijkheid is er geen factor 2 verlaging van fouten. Onderzoek (PDF) laat zien dat Pair Programming 15% meer tijd kost, maar ook 15% minder fouten oplevert. Aangezien de fouten echter in een eerder stadium worden verholpen dan anders, levert dit uiteindelijk een fikse besparing op.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op zaterdag 03 juni 2006 @ 00:13:
[...]

Volgens mij wordt deze strategie nog steeds toegepast bij Airbus, waarbij twee onafhankelijke systemen elkaar controleren en instructies pas worden doorgegeven als beide systemen hetzelfde resultaat geven. De ene draait dan op Intel en de andere op Motorola om zodoende eventuele fouten in de processor af te vangen. Dus het is een soort PC/Mac battle maar dan in de lucht :) Weet niet of ze dit nog zo doen, het artikel is jaren oud.
Sterker nog, dit wordt nog steeds gebruikt in meerder militaire systemen. In bijvoorbeeld een F16 zijn systemen meerdere malen uitgevoerd en wordt door middel van een soort van Vote systeem bepaald wat er gebeurd. Hoe belangrijker een systeem is hoe vaker het uitgevoerd is. Er zijn zelfs systemen waar 7 aparte systemen een vote uit brengen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op zaterdag 03 juni 2006 @ 00:36:
[...]
P1P2Pair
geen foutgeen foutgeen fout
geen foutwel foutgeen fout
wel foutgeen foutgeen fout
wel foutwel foutwel fout
Maar als je 2 verschillende antwoorden hebt hoe kun je dan bepalen wat de goede keuze is om te maken. Stel je hebt een splitsing en de ene zegt links af en de ander rechts af. Je weet dan nooit wat de beste keuze is. Je hebt daarvoor altijd een oneven aantal nodig of je moet van te voren weten welke keuze je voorang geeft boven de andere.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Verwijderd

rwb schreef op zaterdag 03 juni 2006 @ 01:40:
Maar als je 2 verschillende antwoorden hebt hoe kun je dan bepalen wat de goede keuze is om te maken.
Mensen komen daar samen wel uit. Het is dan niet anders dan een normale situatie als een test faalt: is de test code fout, of de echte code?

Maar wat betreft machines heb je gelijk. Het enige dat je met twee kunt doen is een alarm geven als er iets niet klopt, en de mens laten beslissen (als daar tijd voor is, en mogelijkheden toe zijn). Als dat niet kan moet er een voorrang krijgen, en dat maakt natuurlijk de tweede overbodig (tenzij er een slim algoritme is om te kiezen wie gelijk heeft, maar daar kan ook weer iets mee fout gaan...)

  • flowerp
  • Registratie: September 2003
  • Laatst online: 04-02 02:01
Verwijderd schreef op zaterdag 03 juni 2006 @ 00:36:
Het nadeel van traditioneel code reviewen is dat dit achteraf pas gebeurt. De programmeur zal dan (vaak) zijn harde werk willen verdedigen en niet geneigd zijn snel iets aan te passen.
In het verlengde hiervan: in de praktijk worden aantekeningen in code reviews vaak gebruikt om meningen door te drukken; iets is niet perse goed of fout, maar programmeur A heeft een groot ego en vind dat alles op manier A moet, maar programmeur B heeft een nog veel groter ego en vind dat alles op B moet.

Pas nog meegemaakt tijdens een code review. De ene persoon is zwaar tegen het gebruik van singleton patterns in code en streep elk gebruik hiervan meteen als fout aan. De andere echter vind het juist de oplossing voor elk probleem en pas het zeer vaak toe. Wat gebeurd er dan in een review? Een uur lange discussie over singletons, en aan het eind van de dag is de code nog steeds hetzelfde.

Persoonlijk zou ik wel wat zien in pair programming, maar ik zou 't niet echt kunnen. Als je samen achter de computer zit heb je altijd zo'n drang om een dialoog open te houden. Dingen moeten 'meteen' gedaan worden want alles 'duurt te lang'. Als ik in m'n eentje ben staar ik eens 5 minuten naar buiten, of step ik eens rustig door wat source heen. Als er iemand naast je zit (wat we soms wel eens doen) doe je dat niet, want je wilt de ander niet ophouden.

Wat ik wel belangrijk vind is dat je een soort code roulatie doet, waarbij verschillende programmeurs om en om aan een zelfde 'module' werken. Wij werken op dit moment aan een systeem dat uit verschillende onderdelen bestaat (welke groter systeem niet). Het punt is dat voor elk onderdeel eigenlijk 1 programmeur verandwoordelijk is. Zo hebben we een data-import en die hele module is het domein van Eric. Een ander onderdeel is een tijd planner en dat hele stuk, van GUI via business logic tot DB tables 'is van' Marco. Dit gaat eigenlijk zo door voor alle onderdelen.

Het probleem is dat er nu eilandjes ontstaan, omdat elke programmeur vind dat hij/zij het het beste weet en elke keer het wiel opnieuw gaat uitvinden. Zo had Eric voor de data-import bijvoorbeeld een serie filtering classes door en bouwde daar ad-hoc maar even een eigen mini frameworkje voor. Bestaat uit tig spannend klinkende namen voor classes en packages, maar... alleen Eric's code gebruikt dit. Nu zag ik laatst dat ook Marco -ook- aan data import doet; namelijk de user wordt de mogelijkheid gebode om complete schema's te uploaden, en daar voor heeft ie dan dan een UniversalCSVToXMLParser voor geschreven. Eric had echter al een BaseCSVImporter.

Aan de ene kant zou je zeggen dat dit goed is. De aparte onderdelen van onze app hebben bijna 0% dependencies op elkaar, maar de code duplicatie is ook zeer groot. Opzich is er wel de wil om van elkaars code gebruik te maken, maar zodra Eric een functie mist in Marco's code gaat ie gewoon zelf een nieuw vervangend systeem maken wat die functie wel heeft.

Als je de code rouleerd dan heb je imho meer het gevoel dat het ook 'jou' code is.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 11:55

hamsteg

Species 5618

Topicstarter
Verwijderd schreef op zaterdag 03 juni 2006 @ 00:36:
[...]
Het nadeel van traditioneel code reviewen is dat dit achteraf pas gebeurt. De programmeur zal dan (vaak) zijn harde werk willen verdedigen en niet geneigd zijn snel iets aan te passen.
Dat hangt een beetje samen denk ik met je projectenteam en hoe je projectleider er mee om gaat. De eerste review is nooit leuk (echt de eerste keer is verschikkelijk) maar als de rest van het team dat samen met jou ook oppakt ontstaat er een teamgeest en valt de verdediging snel weg. Als je met elkaar eerlijk bent over het doel moet dit geen probleem geven. Maar zie ook volgende opmerking.
Bij Pair Programmen review je elkaar's werk live, en kan er dus direct ingegrepen worden als dat nodig is. Overigens wil dat niet zeggen dat de code helemaal niet meer gereviewd hoeft te worden - dat kan immers nog steeds zinvol zijn voor opmerkingen van anderen, en een blik van een afstand. Ik ben het dus wel met je eens dat code reviews heel zinvol zijn - zeker als er weinig andere vormen van controle zijn!
Persoonlijk vind ik dit te laat. Coderen is het uitontwikkelen van een design. Dat je in de design fase met elkaar om tafel zit lijkt mij een must. Vaak heeft een architect of senior programmeur het globale overall beeld en kent de programmeur de grenzen van gekozen hard/software. Daarom maak je als programmeur een detailed design waarbij critische elementen in pseudo code worden uitgewerkt. Dit wordt gereviewed. Het coderen zelf is de kunst en ervaring van omzetten van functionaliteit naar bits en bytes.

In mijn ervaring is het efficienter om zelf te coderen en daarna reviews te doen ... met 1 uitzondering: In een team met teamgeest zal een programmeur sneller geneigd zijn even iemand te vragen eerder al na een stukje code te kijken of gewoon mee te denken als de programmeur al weet dat dat deel critisch is. Maar omdat het grootste deel van de code gewoon uitcoderen van een design is, zie ik 100% pair coding niet zitten. Bij onze teams zal dat eerder een percentage onder de 5% zijn. Dat is 95% winst in een tweede programmeur kwa tijd en dat verlies je normaal gesproken niet met de twee reviews (design en code).

Let wel pair programming voor critische delen wordt ook door mij 100% aangeraden!

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


Verwijderd

flowerp schreef op zondag 04 juni 2006 @ 14:03:
Als je samen achter de computer zit heb je altijd zo'n drang om een dialoog open te houden. Dingen moeten 'meteen' gedaan worden want alles 'duurt te lang'. Als ik in m'n eentje ben staar ik eens 5 minuten naar buiten, of step ik eens rustig door wat source heen. Als er iemand naast je zit (wat we soms wel eens doen) doe je dat niet, want je wilt de ander niet ophouden.
Dit maakt het werk wel een stuk efficienter :). Het is ook meteen het gevaar, want je bent veel intensiever bezig, en moet dus bewust af en toe pauze houden. Normaal betrap ik me er ook vaak op dat ik eigenlijk alleen voor de lunch pauzeer, maar met Pair Programming is dat niet vol te houden en moet je echt (bijvoorbeeld) ieder uur minimaal 5 minuten 'afkoelen'. Even koffie/thee halen, gewoon wat rondlopen, of bijvoorbeeld even je email checken.
hamsteggot schreef op zondag 04 juni 2006 @ 14:09:
In mijn ervaring is het efficienter om zelf te coderen en daarna reviews te doen ...
Ik denk dat het een (beetje) verschil van definitie is. Voor mij is 'programmeren' het hele proces dat ontwerp, implementatie en testen omvat. Het is bijna nooit zo dat ik een design zie dat zo ver uitgewerkt is dat de implementatie triviaal is. Juist bij de implementatie kom ik vaak dingen tegen die eerder over het hoofd gezien waren, of die beter kunnen dan gedacht.

Natuurlijk gaat het bij Pair Programming niet om alleen de implementatie samen te doen als er een 'perfect' design klaar ligt. Je moet het in meer of mindere mate in alle stadia toepassen, en voor echt triviale dingen (wat je 'uitcoderen' noemt veronderstel ik) inderdaad liever niet - want dan levert het te weinig op. Wellicht is een naam die men beter begrijpt ook 'Pair Working', om verwarring te voorkomen.

Anderhalf jaar geleden heb ik een pilot opgestart op mijn toenmalige werkplek, waarbij we met drie man een deelproject op deze manier aangepakt hebben. We wisten dat het niet 100% van de tijd nuttig zou zijn, maar om een goed beeld te kunnen vormen hebben we activiteiten waarvan we niet zeker wisten of het positief of negatief zou uitpakken wel met Pair Programming gedaan. Daardoor konden we achteraf beter inzien hoe het werkt. Uiteindelijk is het ons allemaal heel goed bevallen. We hebben geen harde cijfers kunnen verzamelen (er is natuurlijk nooit een situatie om goed mee te vergelijken) maar onze indruk was wel:
* Plezierige manier van werken
* Betere code (betere designkeuzes, minder fouten)
* Voor triviale code kost het meer tijd
* Je leert van elkaar (kennisspreiding, risicoverlaging)
* Meer gefocusseerd op het werk

Bij de pilot was kennisspreiding ook een belangrijke wens (vooral om te voorkomen dat bij uitval van personeel bepaalde kennis verloren zou gaan), maar het laatste voordeel was deels onverwacht. Bij Pair Programming ziet men dat je bezig bent en onderbreekt men je veel minder vaak voor triviale dingen. Dit in tegenstelling tot wanneer je alleen (maar geconcentreerd) zit te werken, dan ziet men dat niet en wordt je gewoon van alles gevraagd, en ben je steeds je 'flow' kwijt...

Maar goed, nu heb ik er wel genoeg over gezegd denk ik. Degenen die het interessant vinden moeten het maar eens uitproberen :) Slotopmerking: een goed ontwikkelteam heeft een hele serie 'tools' ter beschikking, past die op de juiste momenten toe en begrijpt dat iedere situatie uniek is en zijn eigen aanpassingen nodig heeft.
Pagina: 1 2 Laatste