Archief - Break en/of return in een loop?

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

SDEC

Legacy Member
Op school wordt ons aangeleerd dat een break/return in een lus (for/while/foreach) een slechte gewoonte is en dat we het niet mogen doen!

Is dit nu echt zo? Ik vind breaken en returnen in een lus echter heel gemakkelijk en overzichtelijk + het spaart geheugen omdat je geen extra variabele moet aanmaken!

Het argument op school is dat het "overzichtelijker" is voor de beginnende programmeur, we krijgen er zelfs minpunten voor op het examen, zelfs al is het perfect correcte syntax.

Wat doen mensen in de praktijk nu? Iemand die dit argument ondersteund of het, zoals mij, ook totale onzin vind?


Even om te verduidelijken:

Zo moet het op school:
Code:
public void testFunc() {
    boolean stop = false;

    // for lus
    for(int i=0; i<MAX_IETS && stop == false; i++) {
        if(isIetsWaar()) {
            doeIets();
            stop = true;
        }
    }

    // while lus
    while(stop == false) {
        if(isIetsWaar()) {
            doeIets();
            stop = true;
        }
    }
}

Zo (vind ik) is het logischer:

Code:
public void testFunc() {
    // for lus
    for(int i=0; i<MAX_IETS; i++) {
        if(isIetsWaar()) {
            doeIets();
           break;
        }
    }

    // while lus
    while(true) {
        if(isIetsWaar()) {
            doeIets();
            break;
        }
    }
}

NeverwinterX

Legacy Member
Mja het is bekend dat ze op veel scholen aanraden om dat zo te doen. Vermoedelijk vloeit dat voort uit dezelfde redering als het afwijzen van goto's.

Maar ik ben het daar niet mee eens en de vergelijking met goto's is niet van toepassing. Bij een break of continue is het precies gedefinieerd naar waar je springt en er zijn geen verrassingen mogelijk. Bovendien verlies je het overzicht als de stopconditie wat ingewikkelder wordt: dan moet dat een lange boolean constructie worden. Bovendien is het gewoon overbodig en verboos.

En scholen raden ook vaak aan om niet meerdere returns te hebben in een functie, vb:
Code:
public int foo(){
   int result;
   if(blabla)
      result = ....

   if(lalala){
      calculate something
      result = ...
   }
   else{
      more calculation
      result += ...
      more calculation
      result = ...
   }

   return result;
}

vs

Code:
public int foo(){
   int result;
   if(blabla)
      return x;

   if(lalala){
      calculate something
      return y;
   }

   more calculation
   result += ...
   more calculation
   return z;
}

Daar ben ik het al helemaal niet mee eens: meerdere returns is veel overzichtelijker en laat toe om alles meer op te delen in stukjes, wat het makkelijker te begrijpen maakt. Zodra je een return tegenkomt, hoe je over dat geval verder niet meer na te denken: anders moet je daar altijd nog rekening mee houden.

SDEC

Legacy Member
NeverwinterX zei:

Volkomen mee eens. Blijkbaar maken de docenten in het begin van het jaar de afspraak om het zo te doen, in het 3e semester is het dan ineens wel toegelaten om te breaken, returnen en te continueen waar je wilt.

In de plaats van het ons in één keer deftig aan te leren... :wtf:

Code:
if(blabla)
    return x;

Mag ook niet, zelfs als het maar één statement is wordt er verplicht om haakjes te gebruiken. Slaat echt op niets... Akkoord het oogt mooier en de "beginnende programmeur" wordt er minder door verward maar is het dan zo fout om een andere (juiste) techniek ook te gebruiken?

SideShow

Legacy Member
in de meeste gevallen is het toch beter om je voorwaarden te centraliseren bovenaan in je lus, waar het hoort, maar inderdaad, af en toe (heel af en toe imo) is het leuker om gewoon in je code te breken...

Fraggie

Legacy Member
SDEC zei:
In de plaats van het ons in één keer deftig aan te leren... :wtf:
Ik bevind mij de laatste tijd meer en meer in de embedded wereld en daar maakt het effectief een verschil.

Allereerst moet je een onderscheid maken tussen:
- for-loops die het gedrag van een while hebben (cf. vele breaks -> oplossing een while met: Lazy evaluation - Wikipedia, the free encyclopedia)
- returnen in het midden van een methode zonder loops

Enkel over het eerste kan ik mij uitspreken, de tweede doet er niet veel toe imo.

Het zit namelijk zo dat wanneer je met embedded realtime applicatie te maken hebt je bijna altijd met pipelining te maken zult hebt. Hierbij kan de processor reeds bewerkingen 'prepareren' vooraleer ze worden uitgevoerd.
Voor vele DSP toepassingen is het dus ongehoord dat je code hebt die:
- de procossor toelaat om even voorop te lopen
- en dan uit het niets de pipeline verbreekt
=> werk en tijd is verspilt! Want alle enkele bewerkingen hebben plots 0% betekenis en vele registers moeten eerst worden gecleared vooraleer de processor terug verder kan doen -> terug tijd verspilt.

Wanneer je dan nog eens met multiple cores werkt wordt er nog meer tijd verspilt. De kans op glitches wordt ook groter.



Wanneer je mooi en zuiver programmeert kan de compiler tips in ASM steken die helpen voor prediction voor de processor. Deze zal dan i.p.v. de instructies van een loop, die toch gebroken wordt, instructies gaan voorbereiden die NA de loop komen -> geen tijd verspilt.

tl;dr: er is een reden waarom men zegt dat er geen goeie C programmers meer zijn.

Cycloon

Legacy Member
Ik heb het laatste jaar quasi constant met legacy code gewerkt waar for/while lussen vol zaten met vroegtijdige returns, continues, etc... Geloof mij vrij, vroeg of laat kom je een lus tegen waar de stopcondities zo onduidelijk worden dat refactoren en onderhoud een hell is. In kleine lusjes die je voor schoolopdrachten doet zal je nauwelijks inzien dat vroegtijdig een lus verlaten een slechte manier is van programmeren.

Ik zou zeggen, trek geen stijlregels in twijfel wanneer je net begint te programmeren. Stijlregels kan je pas volledig appreciëren en begrijpen wanneer je meer ervaring hebt en voldoende situaties bent tegengekomen waar het onduidelijk wordt.

SDEC

Legacy Member
@Fraggie & Cycloon: Bedankt :) Dat is nu de goed geargumenteerde uitleg die ik hoopte te horen te krijgen.

virtualdude

Legacy Member
SDEC zei:
Mag ook niet, zelfs als het maar één statement is wordt er verplicht om haakjes te gebruiken. Slaat echt op niets...

Tot je aan je code gaat sleutelen en een veel voorkomende fout programmeert. Oeps heb de haakjes vergeten.

Als ik code bekijk dan wil ik direct zien wat het nu ervan is.
Indien men een for gaat neerpennen dat in de loop der tijd gigantisch wordt dan kan ik niet direct zien wat er eigenlijk gaande is. Een goed gedefinieerde while lus geeft me direct de info die ik wil. Zoals hierboven vermeld is het inderdaad zo dat op 5 regels code het wel altijd duidelijk is maar stel dat de lus tientallen lijnen code bevat en daarin ergens de voorwaarde verwerkt zit om eruit te springen. Als een andere persoon naar die code zal kijken zal het zeer lastig zijn om te weten wat h'm doet.

Code:
for(....){
    ....
    (if negatief gevonden)
    return
}

vs

Code:
while( geen negatief gevonden && niet door m'n set....){
    ....
    (if negatief)
    negatief gevonden = true
}

Als ik bovenstaande while lees dan weet ik direct dat men iets negatiefs gaat zoeken waar dit in de while structuur absoluut niet duidelijk is.

forloRn_

Legacy Member
Als je resoluut voor manier A dan wel manier B kiest, ga je je op den duur weer in bochten moeten wringen. Wees een beetje pragmatisch en schrijf het gewoon op de meest leesbare manier. Er zijn andere dingen om van wakker te liggen, dunkt me.

Ice

Legacy Member
SDEC zei:
Code:
if(blabla)
    return x;

Mag ook niet, zelfs als het maar één statement is wordt er verplicht om haakjes te gebruiken. Slaat echt op niets... Akkoord het oogt mooier en de "beginnende programmeur" wordt er minder door verward maar is het dan zo fout om een andere (juiste) techniek ook te gebruiken?

Protip: schrijf ALTIJD haakjes.
Waarom? Omdat er gegarandeerd iemand na u die code gaat aanpassen.
Als er dan ineens het volgende komt te staan is uw code omzeep.
Code:
 if (blabla) 
    calMyMethod(x);
    return x;
Zo'n fout is sneller gemaakt dan je denkt en niet altijd even eenvoudig terug te vinden. We leven nu eenmaal niet in een ideale wereld waar alles perfect en automatisch wordt getest.

metalleke

Legacy Member
NeverwinterX zei:
Mja het is bekend dat ze op veel scholen aanraden om dat zo te doen. Vermoedelijk vloeit dat voort uit dezelfde redering als het afwijzen van goto's.

De regel om geen gebruik te maken van early returns komt gewoon uit de talen waar je nog zelf geheugenbeheer moet doen.

Goto's geven eerder aanleiding tot spaghetticode, terwijl early returns aanleiding geven tot memoryleaks.

Cycloon zei:
Ik heb het laatste jaar quasi constant met legacy code gewerkt waar for/while lussen vol zaten met vroegtijdige returns, continues, etc... Geloof mij vrij, vroeg of laat kom je een lus tegen waar de stopcondities zo onduidelijk worden dat refactoren en onderhoud een hell is. In kleine lusjes die je voor schoolopdrachten doet zal je nauwelijks inzien dat vroegtijdig een lus verlaten een slechte manier is van programmeren.

Ik zou zeggen, trek geen stijlregels in twijfel wanneer je net begint te programmeren. Stijlregels kan je pas volledig appreciëren en begrijpen wanneer je meer ervaring hebt en voldoende situaties bent tegengekomen waar het onduidelijk wordt.

Slechte code refactoren is gewoon altijd een hell.

You should quit worrying about micro-optimizations and start worrying about indenting code in a way that people can read it.

NeverwinterX

Legacy Member
Ice zei:
Protip: schrijf ALTIJD haakjes.
Waarom? Omdat er gegarandeerd iemand na u die code gaat aanpassen.
Als er dan ineens het volgende komt te staan is uw code omzeep.
Code:
 if (blabla) 
    calMyMethod(x);
    return x;
Zo'n fout is sneller gemaakt dan je denkt en niet altijd even eenvoudig terug te vinden. We leven nu eenmaal niet in een ideale wereld waar alles perfect en automatisch wordt getest.

Imo verdient die persoon dan gewoon slaag omdat die duidelijk geen IDE gebruikt. Ik zet die haakjes eerder omdat het dan later makkelijker is om een statement toe te voegen binnen de if.

Fraggie zei:
Ik bevind mij de laatste tijd meer en meer in de embedded wereld en daar maakt het effectief een verschil.

Allereerst moet je een onderscheid maken tussen:
- for-loops die het gedrag van een while hebben (cf. vele breaks -> oplossing een while met: Lazy evaluation - Wikipedia, the free encyclopedia)
- returnen in het midden van een methode zonder loops

Enkel over het eerste kan ik mij uitspreken, de tweede doet er niet veel toe imo.

Het zit namelijk zo dat wanneer je met embedded realtime applicatie te maken hebt je bijna altijd met pipelining te maken zult hebt. Hierbij kan de processor reeds bewerkingen 'prepareren' vooraleer ze worden uitgevoerd.
Voor vele DSP toepassingen is het dus ongehoord dat je code hebt die:
- de procossor toelaat om even voorop te lopen
- en dan uit het niets de pipeline verbreekt
=> werk en tijd is verspilt! Want alle enkele bewerkingen hebben plots 0% betekenis en vele registers moeten eerst worden gecleared vooraleer de processor terug verder kan doen -> terug tijd verspilt.

Wanneer je dan nog eens met multiple cores werkt wordt er nog meer tijd verspilt. De kans op glitches wordt ook groter.



Wanneer je mooi en zuiver programmeert kan de compiler tips in ASM steken die helpen voor prediction voor de processor. Deze zal dan i.p.v. de instructies van een loop, die toch gebroken wordt, instructies gaan voorbereiden die NA de loop komen -> geen tijd verspilt.

tl;dr: er is een reden waarom men zegt dat er geen goeie C programmers meer zijn.

Embedded programmeren is inderdaad wel een geval apart. Maar of je nu een if/else binnen je for loop hebt of break/continue: in beide gevallen zal je pipeline dan dingen voorberekenen die nutteloos blijken. Dan kun je wel weer verder gaan optimaliseren om dat te vermijden, maar dat gaat voor beide gevallen op. Je kan zelfs je loops gaan unrollen en heel die shit. Als dat tenminste echt nodig is en echt iets uithaalt, want premature optimisation... En dan nog worden de processoren steeds complexer waardoor het bijzonder moeilijk is om je code correct te optimaliseren voor de pipeline en multilevel caching en die hele resem nieuwe technieken van tegenwoordig, die dan ook nog eens verschillen per processor. Sommige van die optimalisaties van vroeger die nog steeds worden doorverteld, kunnen tegenwoordig geen effect meer of zelfs een omgekeerd effect hebben.

Cycloon

Legacy Member
metalleke zei:
Slechte code refactoren is gewoon altijd een hell.

Idd, daarom dat we moeten voorkomen dat er nog slechte code wordt geschreven :). Stijlregels zijn een begin.

Parnakra

Legacy Member
Stijlregels mogen geen voorrang hebben op pragmatiek.

Het single entrance/single exit gedachtengoed heeft z'n roots in talen die vandaag de dag doorgaans niet meer relevant zijn. Dus er aan vastklingen gewoon 'omdat het zo moet' is belachelijk. Denk zelf even na of een break of return in een lus van 5 à 10 lijntjes nog leesbaar is (veel langer moeten ze trouwens niet worden, of er klopt iets niet), of als je toch met een tijdelijke variabele werkt.

dJeez

Legacy Member
Cycloon zei:
Ik heb het laatste jaar quasi constant met legacy code gewerkt waar for/while lussen vol zaten met vroegtijdige returns, continues, etc... Geloof mij vrij, vroeg of laat kom je een lus tegen waar de stopcondities zo onduidelijk worden dat refactoren en onderhoud een hell is.
Daar hebben we dan ook unit tests voor he, om te testen of niks breekt bij het refactoren :evil:.

Cycloon

Legacy Member
dJeez zei:
Daar hebben we dan ook unit tests voor he, om te testen of niks breekt bij het refactoren :evil:.

Mensen die geen notie hebben van stijlregels hebben al zeker niet gehoord van unit tests :sad:

Moto

Legacy Member
Op school wordt ons aangeleerd dat een break/return in een lus (for/while/foreach) een slechte gewoonte is en dat we het niet mogen doen!

Tja als het van hun moet, effe op de tanden bijten, en wachte dat ge uw diploma hebt :)
Die leraars weten meestal niet waar ze het over hebben, der is niks met break/return in lussen, der is zelf niks mis met goto's :p

daarentegen DRY + code reuse is soms ook gewoon een ronduit slecht idee :p

anyway in het begin is het beter om u effe aan die domme "best practices" te houden en met de jaren zult ge die wel achterwege kunnen laten. Ge hebt een beetje ervaring nodig om te weten wanneer ge die dingen overboord kunt gooien :)

InfoQ: Heresies and Dogmas in Software Development

8BitBoy

Legacy Member
Bij ons hebben ze da nie verboden... ik vind het zelf best handig. Ivm die stijlregels, ik hou ook wat van goeie structuur. Maar bv in een if-statement waar je maar 1 regel code zou hebben is het wat onozel om voor de curly braces een aparte lijn te voorzien.

nameless

Legacy Member
8BitBoy zei:
Bij ons hebben ze da nie verboden... ik vind het zelf best handig. Ivm die stijlregels, ik hou ook wat van goeie structuur. Maar bv in een if-statement waar je maar 1 regel code zou hebben is het wat onozel om voor de curly braces een aparte lijn te voorzien.

Maar die curly braces maken je code dan weer een beetje leesbaarder in de toekomst en ze gaan je code niet minder performant maken.

Parnakra

Legacy Member
nameless zei:
Maar die curly braces maken je code dan weer een beetje leesbaarder in de toekomst en ze gaan je code niet minder performant maken.
YAGNI
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan