[alg]Optimale lengte van een methode/functie

Pagina: 1 2 Laatste
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
Janoz schreef op maandag 17 januari 2011 @ 14:00:
Ik doe het nu al een tijdje en ik moet zeggen dat het inderdaad eerst wat tegen mijn normale werkwijze in ging, maar uiteindelijk wordt alles wel weer een stuk leesbaarder.
wat ?
Bedoel je dat je je local variables 'promoveert' tot class-members ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
.oisyn schreef op maandag 17 januari 2011 @ 14:05:
Wat is daar mis mee dan? Je laat eerst een modal dialog zien, en als die call returnt dan kun je kijken of er op Ok of op Cancel gedrukt was. Zo zou het in win32 iig werken, geen idee hoe de Delphi API daarmee omgaat.
Volgens mij returned ShowModal een enum, die aangeeft wat het 'Modalresult' was. In Delphi kan dit dus mrOk, mrCancel, mrYes, mrNo, zijn als ik het me nog goed herinner.

Idem in .NET: ShowDialog() returned ook een DialogResult enum waarde.

/spuit-elvendertig dus

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
niet meer makkelijk returnen uit een inner loop oid.
Hoezo niet?
CodeCaster schreef op maandag 17 januari 2011 @ 14:03:
Zeggen dat vijftien regels lang is voor een functie, zonder dat je weet wat 'ie doet? Zeker importfunctionaliteit (wat je al snel hebt als je met bestanden werkt) kun je soms beter imperatief/procedureel doen dan strikt OO waarbij je voor elk lullig, éénmalig voorkomend taakje een nieuwe procedure of zelfs klasse mag schrijven, dan blijft het nog overzichtelijk doordat alle acties die met de data worden uitgevoerd op één plek staan.
Mwah, juist het toevoegen van de extra methodes verhoogt de leesbaarheid. Wanneer je alles laat staan kun je op detail niveau heel goed zien wat er gebeurt, maar het hogere niveau is nauwelijks terug te vinden.

Wanneer pieppiep zelf al aangeeft dat de code te partitioneren is (alinea's toevoegen) geeft al aan dat de methode uit verschillende stappen bestaat. In 99.9% van de gevallen kun je die delen weer in aparte methoden onderbrengen. Hierdoor is het overzicht van de originele methode beter. Je hebt immers geen 53 regels meer nodig om te zien wat er gedaan wordt. Daarnaast bieden de nieuw geextraheerde methoden een ideale plek om op de standaard plek (voor de methode) commentaar te geven op wat daar gebeurt (en bij een fatsoenlijke IDE krijg je die terug wanneer je de informatie opvraagt bij die methode)

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


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
whoami schreef op maandag 17 januari 2011 @ 14:23:
[...]

wat ?
Bedoel je dat je je local variables 'promoveert' tot class-members ?
Dat ik eerder uit automatisme eigenlijk alles compleet threadsave maakte terwijl dat eigenlijk vaak helemaal niet nodig is omdat het object toch maar binnen 1 thread bruikbaar was. Niet dat alles nu een classmember wordt, maar ik merk dat het prettiger werkt wanneer niet alle methoden een berg parameters hebben omdat ik eigenlijk overal de state aan het meegeven ben die eigenlijk ook wel in het object zelf zou kunnen.

Als voorbeeld had ik een SAX parser waar ik op een gegeven moment in de abstracte parser implementatie zelf de tag stack bij ging houden ipv het bij de methoden mee te geven en enkele utilility methoden rechtstreeks op die stack te laten wereken ipv methoden maken die eigenlijk ook wel static konden worden omdat ze toch niks met het object zelf deden.
AbstractSaxParser.java

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


Acties:
  • 0 Henk 'm!

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 18-01-2023
Janoz schreef op maandag 17 januari 2011 @ 14:37:
[...]


Hoezo niet?


[...]

Mwah, juist het toevoegen van de extra methodes verhoogt de leesbaarheid. Wanneer je alles laat staan kun je op detail niveau heel goed zien wat er gebeurt, maar het hogere niveau is nauwelijks terug te vinden.

Wanneer pieppiep zelf al aangeeft dat de code te partitioneren is (alinea's toevoegen) geeft al aan dat de methode uit verschillende stappen bestaat. In 99.9% van de gevallen kun je die delen weer in aparte methoden onderbrengen. Hierdoor is het overzicht van de originele methode beter. Je hebt immers geen 53 regels meer nodig om te zien wat er gedaan wordt. Daarnaast bieden de nieuw geextraheerde methoden een ideale plek om op de standaard plek (voor de methode) commentaar te geven op wat daar gebeurt (en bij een fatsoenlijke IDE krijg je die terug wanneer je de informatie opvraagt bij die methode)
Sorry, ik ben het hier echt totaal niet mee eens.
Dat voorbeeld van extract till you drop vind ik ook vreselijk om te zien. Het eerste stukje code was gewoon goed leesbaar en het laatste is een hoop kleine dingetjes die gezamelijk 'iets' doen.
Een fatsoenlijke IDE laat zien wat een functie doet als je met je muis erover gaat maar dat wil ik helemaal niet doen als het niet nodig is. In dit extract till you drop moet ik dus telkens met de muis over de code gaan of zelf over het scherm zoeken waar de functie staat en die bekijken of de functienaam moet duidelijk zijn. Als je teveel functies gaat creeren vind ik zelf de namen over het algemeen steeds slechter worden, je kan er mijns inziens beter minder hebben met duidelijkere namen.
Verder is 1 functie van 50 regels die in 5 groepjes van 10 regels met in die 10 regels 5 regels code en 5 regels commentaar veel beter de volgorde te zien.

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 22:44
Vergeet ook niet dat een functie weer 4 regels ruimte kost: 1 witregel, 1 regel met functiedeclaratie, 2 regels met accolades. Daarnaast nog wat commentaar natuurlijk. Er past dus minder effectieve code op je scherm, waardoor je het overzicht eerder kwijt raakt.

Vaak maak ik ergens pas een functie van op het moment dat het een herbruikbare unit is, dus als ik hem op een 2e plek nodig heb of dat de control flow anders te complex wordt. 85 regels zonder control flow kan veel overzichtelijker zijn dan diezelfde code over 10 functies verspreid.

[ Voor 9% gewijzigd door MBV op 17-01-2011 15:19 ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Het is inderdaad de bedoeling dat je duidelijke functienamen moet hebben. Functienamen die duidelijk omschrijven wat er gebeurt. Wanneer je aangeeft dat je in de knel komt met naamgeving dan komt dat dus waarschijnlijk omdat je veel stukjes code hebt die bijna hetzelfde doen. Dat zou een indicator kunnen zijn van dat het ook iets beter zou kunnen.

Verder over commentaar. In principe zou je zo min mogelijk commentaar moeten gebruiken*. Het grote probleem met commentaar is dat het niet door de compiler wordt gecompileerd, niet door de unittests wordt getest en niet door automatische refactoring meegenomen wordt. Het is een handmatige actie om het commentaar in lijn met de code te houden en niks is schadelijker voor de onderhoudbaarheid wanneer het commentaar niet overeenkomt met de uiteindelijke werking.
Verder is 1 functie van 50 regels die in 5 groepjes van 10 regels met in die 10 regels 5 regels code en 5 regels commentaar veel beter de volgorde te zien.
Als je evenveel commentaar als code nodig hebt om je code leesbaar te houden is er IMHO toch echt iets mis aan code. Daarnaast zul je eerst de afzonderlijke blokjes van 10 regels moeten bekijken wat er precies in dat blok gebeurt voordat je een uitspraak kunt doen over wat de hele methode doet.


* let op, ik zeg zo min mogelijk.Een beetje zoals Einstein ooit zei: "Make things as simple as possible, but not simpler"
MBV schreef op maandag 17 januari 2011 @ 15:18:
Vergeet ook niet dat een functie weer 4 regels ruimte kost: 1 witregel, 1 regel met functiedeclaratie, 2 regels met accolades. Daarnaast nog wat commentaar natuurlijk. Er past dus minder effectieve code op je scherm, waardoor je het overzicht eerder kwijt raakt.
Het doel is niet om je class/module zo kort mogelijk te houden. Het doel is om een enkele functie zo klein mogelijk te houden. Zolang je naamgeving duidelijk is is vervolgens elke functie goed leesbaar zonder dat je de functies zelf weer erbij hoeft te pakken. Maar mocht je ze nodig hebben, met een beetje fatsoenlijke IDE spring je met CTRL-click er heen en met back weer terug naar je originele functie.
Vaak maak ik ergens pas een functie van op het moment dat het een herbruikbare unit is, dus als ik hem op een 2e plek nodig heb of dat de control flow anders te complex wordt. 85 regels zonder control flow kan veel overzichtelijker zijn dan diezelfde code over 10 functies verspreid.
Ik niet. Een verzameling statements die eigenlijk 1 actie uitvoert refactor ik vaak al naar een losse methode met als naam die actie. (Maar eigenlijk ontwikkel ik vaak wat meer topdown waarbij ik mijn hoofd algoritme uittik met nog niet bestaande methoden die ik later implementeer)

Ik ben erg benieuwd naar je lap code van 85 regels die niet overzichtelijker zou kunnen.

[ Voor 46% gewijzigd door Janoz op 17-01-2011 15:29 ]

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


Acties:
  • 0 Henk 'm!

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 18-01-2023
Zo min mogelijk commentaar vind ik een mooie uitspraak, als de code zelf al leesbaar is hoeft er idd geen commentaar bij.
Ook vind ik vaak het automatisch gegenereerde commentaar onduidelijk en dus overbodig.
Interface naam is IAction en functie heet Execute dan krijg je 'Executes the action.'

Maar een idee van een lange functie.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void StaOpEnGaNaarDeBus()
{
  ZetDeWekkerUit();
  StapUitBed();
  DoeKledingAan();
  GaNaarBeneden();
  ZetComputerAan();
  SchenkMelkIn();
  LogComputerIn();
  MaakBoterhamKlaar();
  OpenTweakersSite();
  while (MelkNietOp && BroodNietOp)
  {
    NeemHapOfSlok();
    LeesNieuwsOfForum();
  }
  ZetComputerUit();
  DoeJasAan();
  GaNaarBuitenEnLoopNaarBus();
}

Ik zie hier niet zo snel dingen die je als groepje in een extra functie kan plaatsen.

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


Acties:
  • 0 Henk 'm!

  • barfieldmv
  • Registratie: Maart 2004
  • Laatst online: 23-08 21:37
PiepPiep schreef op maandag 17 januari 2011 @ 15:53:
Zo min mogelijk commentaar vind ik een mooie uitspraak, als de code zelf al leesbaar is hoeft er idd geen commentaar bij.
Ook vind ik vaak het automatisch gegenereerde commentaar onduidelijk en dus overbodig.
Interface naam is IAction en functie heet Execute dan krijg je 'Executes the action.'

Maar een idee van een lange functie.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void StaOpEnGaNaarDeBus()
{
  ZetDeWekkerUit();
  StapUitBed();
  DoeKledingAan();
  GaNaarBeneden();
  ZetComputerAan();
  SchenkMelkIn();
  LogComputerIn();
  MaakBoterhamKlaar();
  OpenTweakersSite();
  while (MelkNietOp && BroodNietOp)
  {
    NeemHapOfSlok();
    LeesNieuwsOfForum();
  }
  ZetComputerUit();
  DoeJasAan();
  GaNaarBuitenEnLoopNaarBus();
}

Ik zie hier niet zo snel dingen die je als groepje in een extra functie kan plaatsen.
Dit is dan wel weer een goed moment om te kijken of je een soort XML config file nodig heb met plugins en interfaces.

Voor mij mag een functie een regel of 40-50 zijn, das ongeveer een scherm vol. Dat moet uit ongeveer 3-4 alinea's bestaan en eentje voor fout afhandeling. Zodra daaronder/in de buurt een functie komt met een zelfde alinea dan moet dat in een functie, anders niet blijf je bezig en krijg je van de vreselijke 1-3 regel code functies die niet handig te debuggen zijn.

Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Ja, je kan ook teveel extracten en elke keer als je 2 statements in een methode hebt een nieuwe methode aanmaken.

Je moet ook niet zozeer naar het aantal regels kijken als wel naar hoeveel taken een methode uitvoert.
Een methode zou in principe maar één taak uit moeten voeren waarbij die taak de ene keer iets meer omvat dan de andere. En dan kun je dingen die je vaak doet (database-connectie) wel extracten.

Even een losse tip: Ik gebruik voor Visual Studio de extensie VS10x Code Map.
Hiermee heb ik in een sidebar een mooi overzicht van mijn properties, methods en events etc. mooi gegroepeerd per zelf aangegeven region.

Acties:
  • 0 Henk 'm!

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 18-01-2023
Ik bedenk me dat dit waarschijnlijk net zo persoonlijk is als of er nou wel of niet goto gebruikt mag worden.

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


Acties:
  • 0 Henk 'm!

  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21:22
Volgens mij ben ik het compleet met jou eens voor wat betreft het maken van code, zeker ook Clean Code gelezen?

Ik snap echter niet waarom je dit hebt gemaakt:
Java:
1
2
3
4
5
6
7
8
9
10
11
 protected List<String> getStackTail(int offset) {
                return stack.subList(offset, stack.size());
        }
        
        protected String getNodeName() {
                return stack.getLast();
        }
        
        protected boolean isStackSize(int i) {
                return i == stack.size();
        }

Dit lijken gewoon wrappers van bestaande functionaliteit. Dat vind ik dan weer iets minder mooi. getStackTail zou nog kunnen, maar de andere 2 lijken mij op het eerste gezicht overbodig.

Battle.net - Jandev#2601 / XBOX: VriesDeJ


Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Ik zou van de tweede dan sowieso een property maken, kan dat ook in Java?

C#:
1
protected String NodeName { get { return stack.getLast(); } }

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Jan_V schreef op maandag 17 januari 2011 @ 16:09:
[...]

Volgens mij ben ik het compleet met jou eens voor wat betreft het maken van code, zeker ook Clean Code gelezen?

Ik snap echter niet waarom je dit hebt gemaakt:
Java:
1
2
3
4
5
6
7
8
9
10
11
 protected List<String> getStackTail(int offset) {
                return stack.subList(offset, stack.size());
        }
        
        protected String getNodeName() {
                return stack.getLast();
        }
        
        protected boolean isStackSize(int i) {
                return i == stack.size();
        }

Dit lijken gewoon wrappers van bestaande functionaliteit. Dat vind ik dan weer iets minder mooi. getStackTail zou nog kunnen, maar de andere 2 lijken mij op het eerste gezicht overbodig.
stack is private en dit zijn de enige 3 bewerkingen die ik nodig had, en ja, ik heb ook Clean Code gelezen. Ga binnenkort weer 10 boeken weggeven tijdens een workshop waarmee ik mijzelf member of the CLUB maak ;)
Davio schreef op maandag 17 januari 2011 @ 16:13:
Ik zou van de tweede dan sowieso een property maken, kan dat ook in Java?

C#:
1
protected String NodeName { get { return stack.getLast(); } }
Java kent geen properties, maar enkel getters en setters. Je C# voorbeeld is dus equivalent (en wanneer ik C# gedaan zou hebben zou ik het inderdaad ook op jou manier doen).

[ Voor 24% gewijzigd door Janoz op 17-01-2011 16:27 ]

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


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
PiepPiep schreef op maandag 17 januari 2011 @ 15:53:

code:
1
2
3
4
void StaOpEnGaNaarDeBus()
{
// ..
}
Het probleem met deze code is dat hij beweert 'sta op en ga naar bus' doet, terwijl er voornamelijk gegeten, gedronken en nieuwsgelezen wordt. Daarnaast zou ik 'zet wekker uit' eerder thuis vinden horen bij de trigger die je wakker maakt en dus eigenlijk een abstractie niveau hoger moeten zitten ;).

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


Acties:
  • 0 Henk 'm!

  • barfieldmv
  • Registratie: Maart 2004
  • Laatst online: 23-08 21:37
Janoz schreef op maandag 17 januari 2011 @ 16:19:
[...]

stack is private en dit zijn de enige 3 bewerkingen die ik nodig had, en ja, ik heb ook Clean Code gelezen. Ga binnenkort weer 10 boeken weggeven tijdens een workshop waarmee ik mijzelf member of the CLUB maak ;)
[...]

Java kent geen properties, maar enkel getters en setters. Je C# voorbeeld is dus equivalent (en wanneer ik C# gedaan zou hebben zou ik het inderdaad ook op jou manier doen).
Ik ben 'nu' clean code aan het lezen. Veel informatie en goede voorbeelden om over je code na te denken. Nu de rest hier nog meekrijgen.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void foo()
{
    // wat code

    for (int i = 0; i < num; i++)
    {
        if (conditie1(i))
            return;
        if (conditie2(i)
            break;

        // wat andere code
    }
}

Als je de inhoud van de for loop verhuist naar een eigen functie, dan heb je dus een returnvalue met 3 mogelijke waarden, waar je dan weer op moet controleren om te bepalen of je moet breaken of returnen oid. Het wordt er vaak ook niet leesbaarder op ofzo, dus dan kun je je afvragen waarom je sowieso nou per se zo nodig de boel wilt opdelen omdat iemand heeft bepaald dat X regels nou eenmaal te lang is.

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.


Acties:
  • 0 Henk 'm!

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 18-01-2023
Oh, maar dan krijg je weer de discussie of een functie maar 1 einde mag hebben of wel halverwege return mag doen :)

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
@.oisyn
Ah op die manier, maar als je de initialisatie code extract, en wat andere code extract dan zit (conditie codes zijn al extracted) dan zit je nog steeds ruim onder de 15 :).

Maar ik moet zeggen dat ik een dergelijke constructie niet veel gebruik, maar dat zal ook wel komen omdat we compleet verschillende typen software ontwikkelen.

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


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

whoami schreef op maandag 17 januari 2011 @ 14:23:
[...]

wat ?
Bedoel je dat je je local variables 'promoveert' tot class-members ?
Wat ík bedoelde is dat je een class maakt voor het opslaan van de local state, zodat je niet 15 argumenten mee hoeft te geven aan een functie, en dat een functie dan ook (zeker in het geval van Java) die argumenten aan kan passen.

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.


Acties:
  • 0 Henk 'm!

  • Guldan
  • Registratie: Juli 2002
  • Laatst online: 16-09 20:58

Guldan

Thee-Nerd

Ik zelf kijk altijd naar de volgende zaken hoewel het natuurlijk een mening per persoon is:
1.Code moet duidelijk zijn;
2.Het moet onderhoudbaar zijn;
3.Wanneer een methode groot wordt: Splits deze op maar laat het de duidelijkheid niet in de weg zitten. dwz. Als je het op kan splitsen maar het voegt alleen complexiteit toe qua onderhoud omdat het minder duidelijk is. Doe het dan niet. (of zorg ervoor dat het wel duidelijk is natuurlijk :))

You know, I used to think it was awful that life was so unfair. Then I thought, wouldn't it be much worse if life were fair, and all the terrible things that happen to us come because we actually deserve them?


Acties:
  • 0 Henk 'm!

  • Avalaxy
  • Registratie: Juni 2006
  • Laatst online: 15:53
Aanrader? Ook als je Code Complete 2 hebt?

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Dus eigenlijk een soort structs? Dat doe ik niet. Ik doe eerder wat whoami aangeeft.

@avalaxy
Ik heb code complete nog niet gelezen, maar als ik dit mag geloven is Clean Code zeker een aanvulling. Daarnaast kost het boek nog geen E19 op amazon, dus om de prijs hoef je het ook niet te laten.

[ Voor 68% gewijzigd door Janoz op 17-01-2011 16:53 ]

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


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 22:44
Janoz schreef op maandag 17 januari 2011 @ 15:21:

Het doel is niet om je class/module zo kort mogelijk te houden. Het doel is om een enkele functie zo klein mogelijk te houden.
Dat is heel simpel: als er meer dan 2 regels in staat, kan je het opsplitsen in 2 functies. Ik zou hem andersom willen stellen: mijn doel is een functie zo groot mogelijk te maken, zodat hij nog altijd 1 coherent ding doet, met een maximum van 50 regels (ongeveer 1 scherm). Het hangt heel erg af van het soort project hoe groot mijn functies worden, vaak maar een paar regels, maar er zitten altijd een paar functies tussen van 50 regels. Bijv een functie om de argumenten te verwerken, command-line help weer te geven, dat soort dingen. Ik zal misschien eens de LOC-statistieken van mijn afstudeerproject (parser met visitor-pattern, dus niet helemaal representatief) opzoeken, kijken hoe lang de langste functie was.
Ik niet. Een verzameling statements die eigenlijk 1 actie uitvoert refactor ik vaak al naar een losse methode met als naam die actie.
Dus als jij een functie hebt van 50 statements die 1 actie uitvoeren, dan refactor je die naar een functie van 50 statements die 1 actie uitvoeren. Leg uit, hoe doe je dat? 8)7
Ik ben erg benieuwd naar je lap code van 85 regels die niet overzichtelijker zou kunnen.
Ik heb even geen voorbeeld dat ik hier neer wil dumpen, maar laatst had ik een python-script dat 30 argumenten verwerkte. application.py had dus een switch/case van 100 regels waarin wat booleans werden aan/uit gezet (elke case had hooguit 2 regels, bij meer regels had ik er een functie van gemaakt). Betere suggesties?
Python:
1
2
3
4
def handleArgs(argsList)
    if (argName == 'first'):
        handleArgFirst(head(argsList))
    handleArgsNotFirst(tail(args))

Zoiets dus? :'(

[ Voor 5% gewijzigd door MBV op 17-01-2011 17:00 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Janoz schreef op maandag 17 januari 2011 @ 16:42:
Dus eigenlijk een soort structs? Dat doe ik niet. Ik doe eerder wat whoami aangeeft.
Dus je gaat members toevoegen aan een class die alleen maar zinnig zijn tijdens een bepaalde method call?

Dus niet dat je bijv. een inner class maakt met de betreffende state en de methods die hebt geëxtract dan members van die inner class maakt dan he.

[ Voor 20% gewijzigd door .oisyn op 17-01-2011 17:11 ]

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.


Acties:
  • 0 Henk 'm!

  • FragFrog
  • Registratie: September 2001
  • Laatst online: 18-09 17:57
MBV schreef op maandag 17 januari 2011 @ 16:56:
Ik heb even geen voorbeeld dat ik hier neer wil dumpen, maar laatst had ik een python-script dat 30 argumenten verwerkte.
Bedoel je dan enkele argumenten met 30 mogelijke waardes? Of daadwerkelijk 30 argumenten? In dat laatste geval is de lengte van je functie niet verwonderlijk, maar ook niet het grootste probleem ;)

Zelf hou ik ~ 15 regels per functie aan als ideaal maximum. Inclusief comments moet het makkelijk op een scherm kunnen, en een class probeer ik binnen 150 regels te houden. Ga ik daar overheen is het bijna altijd wel mogelijk om dingen te refactoren. Juist omdat je gedurende de levensduur van je applicatie nog wel dingen erbij wilt zetten, bugfixes wilt implementeren, etc. Een OS project waar ik aan werk heeft classes van 12.000 regels ertussen zitten, zelfs de meest simpele bugfix kost me daar uren aan uitzoekwerk omdat alles weer linkt naar alles en een fix op de ene plek kan vanalles stuk maken op een compleet andere plek.

Overigens hoeft het gebruik van korte functies niet te betekenen dat je ook veel class variabelen gebruikt, of ellenlange parameterlijsten. Als je echt veel verschillende informatie van een functie ook in meerdere andere functies wilt hebben kun je daar prima objecten / structs / andere taal-specifieke wrappers voor gebruiken. En die kun je juist weer makkelijk refactoren zodat je code er alleen maar beter leesbaar door wordt, in plaats van vijftien verschillende variabelen continue gebruiken in een functie van honderd regels.

[ Voor 20% gewijzigd door FragFrog op 17-01-2011 17:14 ]

[ Site ] [ twitch ] [ jijbuis ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
MBV schreef op maandag 17 januari 2011 @ 16:56:
Dus als jij een functie hebt van 50 statements die 1 actie uitvoeren, dan refactor je die naar een functie van 50 statements die 1 actie uitvoeren. Leg uit, hoe doe je dat? 8)7
In een methode van >50 statements zou ik dan inderdaad beginnen om die 50 statements te extracten naar een nieuwe method. Daarna verwacht ik dat ik die 50 regels nog wel verder op kan delen.
Ik heb even geen voorbeeld dat ik hier neer wil dumpen, maar laatst had ik een python-script dat 30 argumenten verwerkte. application.py had dus een switch/case van 100 regels waarin wat booleans werden aan/uit gezet (elke case had hooguit 2 regels, bij meer regels had ik er een functie van gemaakt). Betere suggesties?
Python:
1
2
3
4
def handleArgs(argsList)
    if (argName == 'first'):
        handleArgFirst(head(argsList))
    handleArgsNotFirst(tail(args))

Zoiets dus? :'(
In dat geval zou ik zeker Clean Code eens lezen aangezien een argumenten parser daar 1 van de case studies is.

In het kort, ja, het kan korter en netter.

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


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
.oisyn schreef op maandag 17 januari 2011 @ 16:59:
Dus je gaat members toevoegen aan een class die alleen maar zinnig zijn tijdens een bepaalde method call?

Dus niet dat je bijv. een inner class maakt met de betreffende state en de methods die hebt geëxtract dan members van die inner class maakt dan he.
Niet bij een bepaalde method call, wel bij bepaalde method calls.

Kijk, ik ga niet de 'je moet zo min mogelijk parameter gebruiken'-regel oplossen door de 6 parameters die mijn methode nodig heeft te wrappen in een class en die meegeven. Kijk, maar 1 parameter \o/. Ik kijk eerder of ik ze alle 6 wel nodig heb en of het echt parameters zouden zijn. Uiteindelijk blijkt dan vaak dat enkele van die parameters eigenlijk gewoon state zijn die je overal in je class gebruikt. Maar ik vind het lastig om hier zo over te discussiëren zonder concrete voorbeelden omdat je dan nogal snel tegen terminologie verschillen aanloopt.

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


Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 18:28

alienfruit

the alien you never expected

Ach, ik heb hier een klasse rondslingeren van 1760 regels aan code. Een echte God class, die de flow van een systeem managed. Met vier interne state machines die afhankelijk zijn van externe processen (distributed media ontvangst over GPRS, CCA/CCR over SOAP, webservice-based event logging). Zonder unit tests, end-to-end testing. Een prima kandidaat om te refactoren als er tijd en geld voor was...

[ Voor 13% gewijzigd door alienfruit op 17-01-2011 23:33 ]


Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 20:37
alienfruit schreef op maandag 17 januari 2011 @ 23:24:
Ach, ik heb hier een klasse rondslingeren van 1760 regels aan code. Een echte God class, die de flow van een systeem managed. Met vier interne state machines die afhankelijk zijn van externe processen (distributed media ontvangst over GPRS, CCA/CCR over SOAP, webservice-based event logging). Zonder unit tests, end-to-end testing. Een prima kandidaat om te refactoren als er tijd en geld voor was...
Dat zoiets kan bestaan is al onbegrijpelijk!

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 22:44
@alienfruit: Ik heb hier een klasse van 15000 regels in de CPP, de headerfile is 2000 regels. Een soort mother-of-all-factories, maar dan met nog 'een paar' functies die handig zijn om overal bij de hand te hebben :P Unittesten is bijna onmogelijk, omdat bijna alle klasses afhankelijk zijn van die klasse, en daardoor de hele wereld wordt geinclude.

Niet zelf geschreven trouwens ;)

Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 18:28

alienfruit

the alien you never expected

Caelorum schreef op maandag 17 januari 2011 @ 23:42:
Dat zoiets kan bestaan is al onbegrijpelijk!
Ik ben al blij dat het stabiel werkt...

Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Caelorum schreef op maandag 17 januari 2011 @ 23:42:
[...]

Dat zoiets kan bestaan is al onbegrijpelijk!
Dat valt wel mee, hoor. :) Zoals in elk vakgebied is lang niet iedereen de purist die we allemaal (niet) als collega wensen. Er schijnen nu eenmaal mensen rond te lopen die nette code onbelangrijk vinden, zolang het maar werkt. Soms is de tijd gewoon op. Soms zijn die mensen manager en leggen ze die mening op aan hun developers, soms zijn het de programmeurs zelf die met die insteek rondlopen. En ze leveren wellicht nog sneller op dan mensen die netjes programmeren ook. Dat onderhoud een crime is bagatelliseren ze vervolgens.

[ Voor 13% gewijzigd door CodeCaster op 18-01-2011 11:14 ]

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Als er alleen maar puristen rondlopen komt een product nooit af.

Elke keer als het product bijna af is, zou er een nieuwe taal / methodiek uitkomen die helemaal hip is en wordt alles opnieuw geschreven.

How many programmers does it take to change a lightbulb?

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Bovendien vind ik 1760 regels nog wel meevallen. Natuurlijk gaat er iets goed fout als dat meer de norm is, maar een enkele class die zo groot is zou ik echt geen ramp vinden.

“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.”


Acties:
  • 0 Henk 'm!

  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21:22
MBV schreef op dinsdag 18 januari 2011 @ 10:59:
@alienfruit: Ik heb hier een klasse van 15000 regels in de CPP, de headerfile is 2000 regels. Een soort mother-of-all-factories, maar dan met nog 'een paar' functies die handig zijn om overal bij de hand te hebben :P Unittesten is bijna onmogelijk, omdat bijna alle klasses afhankelijk zijn van die klasse, en daardoor de hele wereld wordt geinclude.

Niet zelf geschreven trouwens ;)
In dit boek het boek Working Effectively with Legacy Code (http://www.amazon.com/Wor...el-Feathers/dp/0131177052) wordt uitgelegd hoe je zoiets 'heel eenvoudig' kunt doen.
Tijdens het lezen vond ik de theorie op zich wel leuk, maar inderdaad, met zo'n enorme klasse zie ik dat in de praktijk niet snel gebeuren. Dat is het nadeel vaak, in theorie weet je vaak precies wel hoe het moet, maar ja, de praktijk is altijd anders.

Battle.net - Jandev#2601 / XBOX: VriesDeJ


Acties:
  • 0 Henk 'm!

  • kwaakvaak_v2
  • Registratie: Juni 2009
  • Laatst online: 02-06 12:29
Caelorum schreef op maandag 17 januari 2011 @ 23:42:
[...]

Dat zoiets kan bestaan is al onbegrijpelijk!
Waar gewerkt wordt op basis van betaalde uren, i.p.v onbeperkte tijd die ook nog eens niks kost, is dat helemaal niet zo heel raar hoor.

Soms heb je tijd om iets helemaal tot op het bot mooi te maken, maar soms moet het gewoon af in xx uur omdat er gewoon niet meer geld is. En ja dan kun je zeggen dat je het niet zo willen doen, maar dat vind de instantie die mijn hypotheek maandelijks afschrijft niet zo'n heel goed idee. Principe's zijn leuk, maar je verdient er zo weinig aan of mee ;)

Driving a cadillac in a fool's parade.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Maar die god class is er toch niet ineens. Die 'groeit' toch zo? Als er blijkbaar geld was om er pukkels tegenaan te maken dan was er dus eigenlijk ook geld geweest om het pukeltje er netjes in te hangen. Bij het eerste pukkeltje had het misschien marginaal langer geduurd, maar de daaropvolgende pukkels zullen allemaal korter duren.

Ik herken het wel. Ik zit nu op een project waar toch wel best wat mis is. Maar wanneer ik dat met een beetje scouting insteek benader maak ik het bij elke fix of uitbreiding telkens weer een stukje netter. Paar unittestjes erbij, stukje refactoren. Dat kost echt geen extra tijd. Die tests zul je toch wel moeten schrijven (zeker met brakke software kun je niet zonder tests om voor jezelf te bewijzen dat de boel blijft werken). Dat kost je misschien een half uurtje, maar die win je direct terug wanneer je je aanpassing doet omdat je je test kunt blijven gebruiken.

Er is maar 1 iemand die echt verantwoordelijk is voor het brak blijven van de software waar je aan moet werken, en dat ben je toch echt zelf. Verkondigen dat je er de tijd niet voor krijgt is een zwak excuus.

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


Acties:
  • 0 Henk 'm!

  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21:22
Nou ja, een zwak excuus...het is in ieder geval geen goed excuus.

Ik kan me voorstellen dat sommigen het niet 'durven' te doen, omdat ze niet volledig bekend zijn met de materie. Die wel ongeveer weten hoe iets verbeterd moet worden, maar niet precies. Wanneer je dan iets gaat refactoren ben je vaak al veel te snel en te diep bezig. Dan wil je het al snel te groot aanpakken.

Moet toegeven dat ik ook geen grote wijzigingen durf te maken bij m'n nieuwe werkgever. Wil de theorie eerst uitproberen op iets kleinere projecten (en wat credits opbouwen), voordat ik grote veranderingen ga toepassen.

Kan uiteraard nooit kwaad om een unittest project te bouwen. Hoeft niet eens een unit testen te bevatten, kan ook prima met scenario testen (in het begin), omdat je anders overal al snel DI moet gaan toepassen of allemaal gebinde objecten moet gaan mocken op een of andere manier.

Battle.net - Jandev#2601 / XBOX: VriesDeJ


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Op zich hoef je weinig aan je werkwijze aan te passen. Als je een bak lelijke code voor je neus krijgt waar je een aanpassing in moet doen begin je toch altijd met uitzoeken wat er op dit moment gebeurt. In plaats van zomaar wat code uitvoeren kun je dit ook doen door er een unittest bij te maken. Dat kost je net zo veel tijd als los kijken wat er gebeurt, maar vervolgens heb je wel een test voor dat stukje code. Uiteraard hoort er bij je nieuwe aanpassing ook een stukje unittest en als je op een gegeven moment voldoende testdekking hebt op een stukje code zou je je er aan kunnen wagen om eens een stukje te refactoren.

Bij een bug is het nog makkelijker. Over het algemeen ben je best wat tijd kwijt bij het zoeken naar de bug. Hier is het juist nog veel waardevoller om dat middels unittests te doen. Uiteindelijk is het dan de bedoeling dat je een unittest weet te maken die faalt vanwege juist die bug. Daarna kun je de bug fixen en kun je met die unittest aantonen dat het nu wel werkt. En ook hier krijg je een steeds hogere testdekking waardoor je op een gegeven moment eens aan wat kleine refactordingetjes kunt denken.

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


Acties:
  • 0 Henk 'm!

Verwijderd

Wat vinden jullie de maximale lengte van een C/C++ main functie? Hier wordt vooral ingegaan op member functies e.d. Maar in C++ (en al helemaal in C) moet je toch echt de main functie ook dingen laten doen...

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Wij zijn een tijdje terug afgestapt van prefixes om korte functies. Het argument was altijd: dan weet je wat voor soort variabele het is. Maar met korte functies en een goede doc voor je class/functie weet je dat direct als je de functie bekijkt. Op die manier is code zonder prefixes veel leesbaarder en veel makkelijker te refactoren. Helaas hebben we er nog 1 die dit niet echt wil inzien.

Hiervoor was het inderdaad ook functies met enorme lappe code erin die wel 50 dingen deden en er werd veel gecopy/paste, drama om te debuggen/onderhouden. Heerlijk nu die korte functies icm. een goede IDE.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 18 januari 2011 @ 22:44:
Wat vinden jullie de maximale lengte van een C/C++ main functie? Hier wordt vooral ingegaan op member functies e.d. Maar in C++ (en al helemaal in C) moet je toch echt de main functie ook dingen laten doen...
Wat is er zo speciaal aan main() :?

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.


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17:02
Verkondigen dat je er de tijd niet voor krijgt is een zwak excuus
Lekker praktische insteek ook. Als de klant de aanpassing over een week moet hebben ga jij em dan uitleggen dat dat niet kan omdat je ergens anders code zit aan te passen? Zal wel overheidswerk zijn dan ofzo want mijn klanten zitten daar echt niet op te wachten.

Moet je ook nog gaan uitleggen dat die code eigenlijk bagger is, gaat die kant nog harder steigeren omdat het dus de eerste keer ook al brak was.

De lengte van een functie is echt de moeite van de discussie niet waard eigenlijk : een functie is zo lang als tie moet zijn en niet langer maar ook niet korter.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Verwijderd schreef op dinsdag 18 januari 2011 @ 22:44:
Wat vinden jullie de maximale lengte van een C/C++ main functie? Hier wordt vooral ingegaan op member functies e.d. Maar in C++ (en al helemaal in C) moet je toch echt de main functie ook dingen laten doen...
Als jij om wat voor reden dan ook vijftig forms wil spawnen in je main()-procedure dan doe je dat toch lekker. :)

Of die code niet gegroepeerd kan worden in logisch genaamde procedures is een tweede vraag.

[ Voor 9% gewijzigd door CodeCaster op 18-01-2011 23:54 ]

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op dinsdag 18 januari 2011 @ 23:39:
[...]

Wat is er zo speciaal aan main() :?
Nou, zeker in C, gebeurd daar vaak nog wel het een en ander. Ook op embedded platformen, daar is het ook inefficienter om overal een functie aanroep te doen.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat bewijst niet wat er speciaal is aan main(). Het is gewoon een functie zoals alle andere (die toevallig als entry point voor je app dient). Als het inefficient is om functieaanroepen te doen, dan geldt dat ook voor andere functies, en niet alleen voor main(). Ergo, exact dezelfde argumenten gaan op voor main() als voor elke andere functie.

[ Voor 13% gewijzigd door .oisyn op 19-01-2011 02:26 ]

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.


Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 21:41

RayNbow

Kirika <3

farlane schreef op dinsdag 18 januari 2011 @ 23:45:
[...]

Lekker praktische insteek ook. Als de klant de aanpassing over een week moet hebben ga jij em dan uitleggen dat dat niet kan omdat je ergens anders code zit aan te passen? Zal wel overheidswerk zijn dan ofzo want mijn klanten zitten daar echt niet op te wachten.
Als je maar een week de tijd hebt en je zit ergens aan andere code te werken, dan moet je dingen beter plannen. ;)

Daarnaast kost het refactoren van een enkele functie nauwelijks tijd (en helemaal weinig als je refactoring-tools gebruikt). Het idee is namelijk dat je kleine aanpassingen maakt en die telkens test, zoals beschreven in het originele Refactoring boek. Dit is trouwens ook de manier hoe je het in de wiskunde doet. Je schrijft niet een draak van een expressie in 1x om, maar vervangt geleidelijk stap voor stap subexpressies.
Moet je ook nog gaan uitleggen dat die code eigenlijk bagger is, gaat die kant nog harder steigeren omdat het dus de eerste keer ook al brak was.
Bij wie ligt de verantwoordelijkheid voor die brakke code? ;)
  • Als je zelf de code hebt geschreven, dan lijkt het me duidelijk dat je jezelf ermee geholpen hebt.
  • Indien de code reeds bestond en door een andere partij geschreven is, dan had je bij aanvang van de opdracht moeten aankaarten dat de kwaliteit van de code zodanig is, dat onderhoud meer werk kost.
De lengte van een functie is echt de moeite van de discussie niet waard eigenlijk : een functie is zo lang als tie moet zijn en niet langer maar ook niet korter.
Het is geen wet dat als een functie langer dan N regels beslaat, dat de functie per definitie te lang is. Het zijn vuistregels dat er zeer waarschijnlijk iets mis en dat je de boel kunt refactoren. Het is vergelijkbaar met code coverage. Als je geen 100% code coverage haalt, wil dat niet zeggen dat je testsuite niet goed is, maar het is wel raadzaam om te controleren welke zaken niet gedekt worden.

Daarnaast bestaan er trouwens refactoring-technieken die een functie langer kunnen maken, zoals bijv. Introduce ExplainingVariable:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if ( (platform.toUpperCase().indexOf("MAC") > -1) &&
      (browser.toUpperCase().indexOf("IE") > -1) &&
       wasInitialized() && resize > 0 )
{
    // do something
}


// Introduce Explaining Variable -->


final boolean isMacOs     = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE")  > -1;
final boolean wasResized  = resize > 0;

if (isMacOs && isIEBrowser && wasInitialized() && wasResized)
{
    // do something
}

Een groei van 2 regels. ;)

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • Camulos
  • Registratie: Januari 2009
  • Laatst online: 06-09 22:59

Camulos

Stampert

farlane schreef op dinsdag 18 januari 2011 @ 23:45:
De lengte van een functie is echt de moeite van de discussie niet waard eigenlijk : een functie is zo lang als tie moet zijn en niet langer maar ook niet korter.
Idd :) Elke programmeur zal zo zijn voorkeur en stijl hebben bij het proggen van lappen code ^^

Persoonlijk heb ik best wel een hekel eraan als alles totaal over-engineered wordt, oftewel dat alles tot in de puntjes ge-extract en ge-refactored wordt. Dit soort code is namelijk prima voor de originele progger, alleen kost het vet veel tijd als collega/extern progger om de code te begrijpen! En al helemaal er ook nog eens een niet-logische of niet consistente naamgeving aan de methoden gegeven worden.

In het voorbeeld dat eerder werd aangehaald: Ik heb liever het eerste dan wel 2e stukje code dan de spaghetti op het einde.

Daarnaast is de lengte afhankelijk van de taal waarin je progt en het doel van je functie.
Voorbeelden:
- PHP library klasse kan methoden hebben van gemiddeld 20 tot 40 regels per functie...
- terwijl een JAVA GUI code lappen (lees 80 tot 100 regels) voor enkele functies heeft.
- Extende klassen in C# die super kort zijn per functie omdat ze alles door zetten naar hun parent ^^

[ Voor 8% gewijzigd door Camulos op 19-01-2011 08:48 ]

Not just an innocent bystander


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Camulos schreef op woensdag 19 januari 2011 @ 08:43:
[...]
Dit soort code is namelijk prima voor de originele progger, alleen kost het vet veel tijd als collega/extern progger om de code te begrijpen!
Integendeel denk ik. Als ik een functie van 200 regels voor m'n neus krijg dan zal ik echt heel erg goed moeten gaan lezen wat er nu precies allemaal gebeurt. Bij een functie van 5 regels zie je dat direct.
En al helemaal er ook nog eens een niet-logische of niet consistente naamgeving aan de methoden gegeven worden.
Dat is een kwestie van code-standaard en goed code reviewen en iemand die daar niet op let erop aanspreken.

Acties:
  • 0 Henk 'm!

  • Camulos
  • Registratie: Januari 2009
  • Laatst online: 06-09 22:59

Camulos

Stampert

Cartman! schreef op woensdag 19 januari 2011 @ 08:48:
Integendeel denk ik. Als ik een functie van 200 regels voor m'n neus krijg dan zal ik echt heel erg goed moeten gaan lezen wat er nu precies allemaal gebeurt. Bij een functie van 5 regels zie je dat direct.
Je vergeet even dat jij die functie van 5 regels eerst moet vinden :) Een functie van 200 regels refactoren naar 5-regel-functies.. (40 functies ongeveer?). Een wir-war van functies doorspitten om die ene functie te vinden...

Nu vind ik 200 regels ook best lang :) ^^ zelf streef ik naar maximaal 50 regels per functie

Not just an innocent bystander


Acties:
  • 0 Henk 'm!

  • BertS
  • Registratie: September 2004
  • Laatst online: 14-04 17:14
Davio schreef op maandag 17 januari 2011 @ 16:01:
Even een losse tip: Ik gebruik voor Visual Studio de extensie VS10x Code Map.
Hiermee heb ik in een sidebar een mooi overzicht van mijn properties, methods en events etc. mooi gegroepeerd per zelf aangegeven region.
Thanx! is een mooie toevoeging.

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Camulos schreef op woensdag 19 januari 2011 @ 09:12:
[...]
Je vergeet even dat jij die functie van 5 regels eerst moet vinden :) Een functie van 200 regels refactoren naar 5-regel-functies.. (40 functies ongeveer?). Een wir-war van functies doorspitten om die ene functie te vinden...
Dat lijkt me geen enkel probleem, gewoon doorklikken in je IDE. En als iedereen netjes werkt weet je meestal wel ongeveer waar iets zit, of je klikt gewoon wat rond in je IDE dus.

Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 21:41

RayNbow

Kirika <3

Camulos schreef op woensdag 19 januari 2011 @ 09:12:
[...]


Je vergeet even dat jij die functie van 5 regels eerst moet vinden :) Een functie van 200 regels refactoren naar 5-regel-functies.. (40 functies ongeveer?). Een wir-war van functies doorspitten om die ene functie te vinden...
Het is natuurlijk wel de bedoeling dat je de gerefactorde functie grotendeels kunt begrijpen zonder de details erop na te hoeven slaan. Hierbij is van groot belang dat de kleinere functies een duidelijke naam hebben.
Mocht je geinteresseerd zijn in de details van een bepaalde functie, dan helpt een IDE je om er naar toe te springen. Het is echter niet de bedoeling om bij elke functieaanroep die je tegenkomt tijdens het lezen meteen de diepte in te gaan.**

(** Dit is vooral een slechte manier om bijv. een recursieve functie f te begrijpen. Tijdens het lezen van f kom je gegarandeerd een aanroep van f tegen. Om f te begrijpen moet je dus eerst f begrijpen? :p)

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

Verwijderd

Er schijnen nu eenmaal mensen rond te lopen die nette code onbelangrijk vinden, zolang het maar werkt.
Die mensen heten klanten, managers en ontwikkelaars. Je kan het je in het bedrijfsleven gewoon niet permitteren altijd purist te zijn. Dat levert vertraging op. Soms moet iets ad hoc gebeuren en dan zul je uiteindelijk pragmatisme over purisme gaan prefereren.
De spaghettivorming is iets van kwadratisch aan het aantal onderhoudsbeurten :+

Overigens vind ik dat verhaal over 1 functie-call in een method ook echt onzin. Je code wordt er alleen minder leesbaar en onderhoudbaar door. Daarnaast maak je debuggen ook alleen maar lastiger, omdat je je call-stack onnodig groot maakt (wat daarnaast ook nog eens een negatieve invloed heeft op performance). Je moet gewoon logische stukken groeperen. Niet extracten om het extracten.

[ Voor 29% gewijzigd door Verwijderd op 19-01-2011 09:55 ]


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 22:44
RayNbow schreef op woensdag 19 januari 2011 @ 09:36:

(** Dit is vooral een slechte manier om bijv. een recursieve functie f te begrijpen. Tijdens het lezen van f kom je gegarandeerd een aanroep van f tegen. Om f te begrijpen moet je dus eerst f begrijpen? :p)
Vooral leuk bij 2-laags-recursie (of hoe dat ook heet): f roept g aan, en g roept in bepaalde gevallen f weer aan. "Volgens mij heb ik daarnet net zo'n functie gezien, welke malloot gaat dit nou copy/pasten?" Oh ja, recursie... :z

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
farlane schreef op dinsdag 18 januari 2011 @ 23:45:
[...]

Lekker praktische insteek ook. Als de klant de aanpassing over een week moet hebben ga jij em dan uitleggen dat dat niet kan omdat je ergens anders code zit aan te passen? Zal wel overheidswerk zijn dan ofzo want mijn klanten zitten daar echt niet op te wachten.
Nee, ik zit niet ergens anders code aan te passen. Lees nog eens mijn beschrijving door. Ik doe mijn aanpassing en laat de code netter achter dan dat ik hem gevonden heb. Als dat bij elke aanpassing gebeurt evolueert de code vanzelf naar nettere code.

En overheid? Dat valt wel mee. Niet alles anders dan cowboy omgevingen is overheid.
Moet je ook nog gaan uitleggen dat die code eigenlijk bagger is, gaat die kant nog harder steigeren omdat het dus de eerste keer ook al brak was.
Hier is al eerder op gereageerd. Het is echt niet de klant die brakke code geschreven heeft. Als je nu meer tijd voor je aanpassing nodig hebt dan is dat de consequentie van de kantjes die je team er eerder vanaf gelopen heeft. Verder zijn jullie blijkbaar niet goed in het onderkennen en communiceren van de technical debt en daarnaast kost nette code niet meer tijd dan brakke aanpassingen.
De lengte van een functie is echt de moeite van de discussie niet waard eigenlijk : een functie is zo lang als tie moet zijn en niet langer maar ook niet korter.
Het is geen keiharde regel. Het is een leidraad. Bij enorme lange lappen code is de kans veel groter dat je met ononderhoudbare code te maken hebt. Het is een belangrijke metric die wij gebruiken om onderhoudbaarheid te kunnen afleiden.

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


Acties:
  • 0 Henk 'm!

  • Camulos
  • Registratie: Januari 2009
  • Laatst online: 06-09 22:59

Camulos

Stampert

Verwijderd schreef op woensdag 19 januari 2011 @ 09:49:
Overigens vind ik dat verhaal over 1 functie-call in een method ook echt onzin. Je code wordt er alleen minder leesbaar en onderhoudbaar door. Daarnaast maak je debuggen ook alleen maar lastiger, omdat je je call-stack onnodig groot maakt (wat daarnaast ook nog eens een negatieve invloed heeft op performance). Je moet gewoon logische stukken groeperen. Niet extracten om het extracten.
+1 !! kan het niet beter verwoorden :)

Not just an innocent bystander


Acties:
  • 0 Henk 'm!

  • Flapmo
  • Registratie: April 2000
  • Laatst online: 14:14

Flapmo

and back is gigi!

Camulos schreef op woensdag 19 januari 2011 @ 10:14:
[...]


+1 !! kan het niet beter verwoorden :)
en nog een +1 :).

"The purpose of computing is insight, not numbers." -- Richard Hamming


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Verwijderd schreef op woensdag 19 januari 2011 @ 09:49:
Die mensen heten klanten, managers en ontwikkelaars. Je kan het je in het bedrijfsleven gewoon niet permitteren altijd purist te zijn. Dat levert vertraging op. Soms moet iets ad hoc gebeuren en dan zul je uiteindelijk pragmatisme over purisme gaan prefereren.
Het heeft niks met purisme te maken, maar alles met professionaliteit. Ook bij een adhoc aanpassing kost het geen extra tijd om daar een unittestje bij te bouwen.
De spaghettivorming is iets van kwadratisch aan het aantal onderhoudsbeurten :+
Dat hoeft dus helemaal niet. Dat gebeurt alleen wanneer je je code laat rotten.
Overigens vind ik dat verhaal over 1 functie-call in een method ook echt onzin. Je code wordt er alleen minder leesbaar en onderhoudbaar door. Daarnaast maak je debuggen ook alleen maar lastiger, omdat je je call-stack onnodig groot maakt (wat daarnaast ook nog eens een negatieve invloed heeft op performance). Je moet gewoon logische stukken groeperen. Niet extracten om het extracten.
Je kunt het natuurlijk in het belachelijke trekken. Een functie hoeft echt niet uit 1 regel te bestaan. Echter wanneer bij voorbaat je onderhoudbaarheid in gaat leveren vanwege vermoedelijk performance verlies dan ben je imho niet goed bezig.

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


Acties:
  • 0 Henk 'm!

Verwijderd

Janoz schreef op woensdag 19 januari 2011 @ 10:38:
[...]

Het heeft niks met purisme te maken, maar alles met professionaliteit. Ook bij een adhoc aanpassing kost het geen extra tijd om daar een unittestje bij te bouwen.
Tja, dat vind jij, dat vind ik, maar wat je ziet is toch dat er dingen on-the-fly veranderd gaan worden, om het snel even iets op te leveren. Een regeltje code in een method, zonder opnieuw te testen.
Dat is niet leuk, maar dagelijkse praktijk. Er zijn nog legio bedrijven waar unit-testen uberhaupt niet vanzelfsprekend is. Ik heb bij een multinational gewerkt waar unit-testen nu pas geimplementeerd wordt. En nu klaagt men al over het feit dat dat tijd kost.
Je kunt het natuurlijk in het belachelijke trekken. Een functie hoeft echt niet uit 1 regel te bestaan. Echter wanneer bij voorbaat je onderhoudbaarheid in gaat leveren vanwege vermoedelijk performance verlies dan ben je imho niet goed bezig.
Daar zijn we het dus eens, het sloeg voornamelijk op deze blogpost: http://blog.objectmentor....ing-extract-till-you-drop die door iemand gelinkt werd.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op woensdag 19 januari 2011 @ 00:53:
[...]


Nou, zeker in C, gebeurd daar vaak nog wel het een en ander. Ook op embedded platformen, daar is het ook inefficienter om overal een functie aanroep te doen.
Dat valt toch wel mee. Ik werk ook best veel op embedded platformen, maar mijn main function is nooit erg lang. Je roept een paar initialisatie routines aan, en dan start je je main loop/scheduler. Meestal zal de compiler toch ook nog wel het een en ander inlinen, dus dan is de overhead van een functie aanroepen ook geen argument meer.

“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.”


Acties:
  • 0 Henk 'm!

  • SeatRider
  • Registratie: November 2003
  • Laatst online: 08:18

SeatRider

Hips don't lie

CodeCaster schreef op maandag 17 januari 2011 @ 11:14:
Wat zei Joel daar ook alweer over?

[...]

Oh die was gelukkig pas twee keer genoemd. :X :P
Die blogpost haal ik ook altijd aan ja, briljant gewoon.

Nederlands is makkelijker als je denkt


Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Woy schreef op woensdag 19 januari 2011 @ 10:48:
[...]

Dat valt toch wel mee. Ik werk ook best veel op embedded platformen, maar mijn main function is nooit erg lang. Je roept een paar initialisatie routines aan, en dan start je je main loop/scheduler. Meestal zal de compiler toch ook nog wel het een en ander inlinen, dus dan is de overhead van een functie aanroepen ook geen argument meer.
Ik ga toch liever voor leesbaarheid van mijn code dan voor micro-optimalisatie middels het minimaliseren van functie-aanroepen.

Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 21:41

RayNbow

Kirika <3

MBV schreef op woensdag 19 januari 2011 @ 09:56:
[...]

Vooral leuk bij 2-laags-recursie (of hoe dat ook heet): f roept g aan, en g roept in bepaalde gevallen f weer aan. "Volgens mij heb ik daarnet net zo'n functie gezien, welke malloot gaat dit nou copy/pasten?" Oh ja, recursie... :z
Haskell:
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
-- De priemgetallen:

primes = 2 : oddprimes
oddprimes = filter isPrime [3,5..]




-- Wanneer is iets priem?
-- Nou, als het maar 1 priemfactor heeft:

isPrime n = case (primeFactors n) of
              [p] -> True
              _   -> False




-- Maar hoe bereken je de priemfactoren van een getal n?
-- Nou, we delen gewoon herhaaldelijk door elk priemgetal:

primeFactors n = factor n primes
  where factor m (p:ps)
          | p*p > m         =  [m]
          | m `mod` p == 0  =  p : factor (m `div` p) (p:ps)
          | otherwise       =  factor m ps

Mutual recursion. *O*

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Davio schreef op woensdag 19 januari 2011 @ 10:55:
[...]

Ik ga toch liever voor leesbaarheid van mijn code dan voor micro-optimalisatie middels het minimaliseren van functie-aanroepen.
Het zijn alleen niet altijd micro-optimalisaties. Zo hebben wij onlangs wat vaak aangeroepen virtual methods ontdaan van het virtual zijn. Op embedded platforms waar een cycle relatief lang duurt is de impact nog veel groter.
Cartman! schreef op woensdag 19 januari 2011 @ 09:32:
[...]

Dat lijkt me geen enkel probleem, gewoon doorklikken in je IDE. En als iedereen netjes werkt weet je meestal wel ongeveer waar iets zit, of je klikt gewoon wat rond in je IDE dus.
De mens is slecht in recursie. Als jij 3 of 4 functies diep moet raak je al snel het overzicht kwijt.

[ Voor 30% gewijzigd door .oisyn op 19-01-2011 11:29 ]

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.


Acties:
  • 0 Henk 'm!

Verwijderd

whoops, scrollfaal*

[ Voor 87% gewijzigd door Verwijderd op 19-01-2011 12:06 ]


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
.oisyn schreef op woensdag 19 januari 2011 @ 11:28:
[...]
De mens is slecht in recursie. Als jij 3 of 4 functies diep moet raak je al snel het overzicht kwijt.
Dan ga je er voor t gemak even vanuit dat alle code die je schrijft recursief is. We maken vast heel verschillende producten, ik gebruik t maar zelden iig.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik heb het niet over recursieve functies, ik heb het over in je hoofd steeds weer opnieuw een functie in en maar proberen te onthouden wat je 'stack' was.

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.


Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 21:41

RayNbow

Kirika <3

.oisyn schreef op woensdag 19 januari 2011 @ 16:41:
ik heb het over in je hoofd steeds weer opnieuw een functie in en maar proberen te onthouden wat je 'stack' was.
En daarom is het niet de bedoeling om bij elke functieaanroep de diepte in te gaan. :)

Als je iets ziet als...
Python:
1
2
xs = range(10)
random.shuffle(xs)

...spring je niet naar de definitie van random.shuffle, maar behandel je het als een black box.

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Tot je wilt weten hoe die geïmplementeerd is. Volgens mij ging de discussie over http://blog.objectmentor....ing-extract-till-you-drop.

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.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:51
Ik geloof dat de term cyclomatic complexity nog niet gevallen is? Het is een maat van de complexiteit van een procedure aan de hand van het aantal punten waarop branching plaats vindt. Voorbeelden zoals hier gegegeven werden van functies die simpelweg een heleboel andere procedures aanroepen maar verder nauwelijks branching bevatten kunnen wel uit veel statements bestaan, maar zijn volgens deze maat nog steeds niet complex. Dit sluit waarschijnlijk beter aan bij het intuïtieve idee van complexiteit dan simpelweg statements tellen.

(Sowieso geldt dat het aantal statements dat je nodig hebt om een bepaalde taak uit te voeren nogal verschilt per taal. In C heb je relatief veel code nodig voor het alloceren en vrijgeven van resources ten op zichte van bijvoorbeeld C++, waar dat soort dingen meestal automatisch via constructors en destructors gebeuren, maar dat maakt de code nauwelijks moeilijker om te begrijpen.)

Ik heb het ook eens met (o.a.) .oisyn dat het weinig zin heeft om meer procedures te introduceren tenzij daarbij ook abstractie plaatsvindt. Als je de hele context expliciet moet meegeven, dan heb je alleen maar meer code nodig om hetzelfde gedaan te krijgen, en de resulterende code is dan niet eenvoudiger om in z'n geheel te begrijpen. Afsplitsen van functionaliteit is mijns inziens pas zinnig als je daardoor ófwel codeduplicatie voorkomt (soms moet je dan helaas nog steeds veel contextinformatie meegeven), óf onafhankelijke functionaliteit die eerst verweven was ontwart. Kortom: als het afsplitsen van functionaliteit tot makkelijker te begrijpen code leidt.

Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 21:41

RayNbow

Kirika <3

.oisyn schreef op woensdag 19 januari 2011 @ 17:41:
Tot je wilt weten hoe die geïmplementeerd is.
Tuurlijk, als je echt wilt weten hoe iets geimplementeerd is, dan kun je altijd naar de definitie springen. Dit doe je echter niet als je al bezig bent om de functie te begrijpen waarin deze functieaanroep (in mijn voorbeeld random.shuffle) plaatsvindt.
Volgens mij ging de discussie over http://blog.objectmentor....ing-extract-till-you-drop.
Daarvan vind ik helaas alle iteraties van de code lelijk. :p

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 18:28

alienfruit

the alien you never expected

Het probleem met die klasse van eerder is. Dat het te veel afhankelijk is van externe partijen. Gezien de klant niet een onafhankelijk test omgeving wilde leveren. Nu moeten we dus altijd een vier onderaannemers van de klant bellen. Om delen van het systeem te testen. Volgens vaste richtlijnen die minstens een week in beslag nemen. Dus breek me de bek niet open. Eigenlijk zou ik de klasse wat willen refactoren zodat de state machines gesepareerd worden. Om het overzichtelijker te maken en state guard etc.

Verder was dit mijn eerste project bij mijn baas en was de documentatie in een taal waar ik niet vloeiend in ben. Acht het project waarop het gebaseerd is (v1) was nog erger... Wat ik mijn nu al een tijd afvraag hoe werk je met unit tests als je zoveel afhankelijkheden hebt?

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17:02
Janoz schreef op woensdag 19 januari 2011 @ 10:06:
Nee, ik zit niet ergens anders code aan te passen. Lees nog eens mijn beschrijving door. Ik doe mijn aanpassing en laat de code netter achter dan dat ik hem gevonden heb. Als dat bij elke aanpassing gebeurt evolueert de code vanzelf naar nettere code.
Ik snap de werkwijze ( en ook de impuls om dat soort dingen te doen ), maar elke aanpassing die je maakt kost tijd, hoe dan ook. En in brakke code kost het meer tijd want kleine aanpassingen hebben meestal meer gevolgen dan je kunt zien in een korte tijd. Jouw oplossing daarvoor is tests schrijven, wat ook tijd kost.

Imho moet je je gewoon blijven afvragen of dat wat je aan het doen bent wel iets gaat opleveren, anders dan alleen 'nettere code'.
Hier is al eerder op gereageerd. Het is echt niet de klant die brakke code geschreven heeft. Als je nu meer tijd voor je aanpassing nodig hebt dan is dat de consequentie van de kantjes die je team er eerder vanaf gelopen heeft.
Ik heb het over code die uit hetzelfde 'nest' komt, dus waarvoor jij/ik verantwoordelijk bent. Dat kan code van jezelf zijn, of code geschreven door iemand/iemanden ander en waarvoor je eigenlijk niet de verantwoordelijkheid wilt, omdat je weet dat het geen goede code is. Ook al heb je er geen hand in gehad, je moet alsnog met de billen bloot op dat moment. Wat de oorzaak ook geweest is, de klant zal niet blij zijn om te horen dat het brakke code is.
Verder zijn jullie blijkbaar niet goed in het onderkennen en communiceren van de technical debt en daarnaast kost nette code niet meer tijd dan brakke aanpassingen.
Met het tweede ben ik het helemaal eensch, maar soms heb je daar gewoon geen invloed op.
Het eerste punt vind ik erm, vaag. Wat bedoel je daar mee, dat ik/wij niet weten dat goede software maken belangrijk is?
Het is geen keiharde regel. Het is een leidraad.
Als leidraad zou het kunnen functioneren misschien.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

RayNbow schreef op woensdag 19 januari 2011 @ 18:20:
[...]

Tuurlijk, als je echt wilt weten hoe iets geimplementeerd is, dan kun je altijd naar de definitie springen.
Ja, en als die functie is opgesplitst in 5 niveaus diep, dan spring je en spring je en wordt de code zo onoverzichtelijk als de pest.

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.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
farlane schreef op woensdag 19 januari 2011 @ 20:29:
[...]

Ik snap de werkwijze ( en ook de impuls om dat soort dingen te doen ), maar elke aanpassing die je maakt kost tijd, hoe dan ook. En in brakke code kost het meer tijd want kleine aanpassingen hebben meestal meer gevolgen dan je kunt zien in een korte tijd. Jouw oplossing daarvoor is tests schrijven, wat ook tijd kost.
Uiteraard kost een aanpassing tijd. Ik neem verder aan dat we het eens zijn dat een aanpassing in nette code minder tijd kost dan een aanpassing in rotte code. Wat ik echter daarnaast nog beweer is dat een aanpassing maken en de code netter achter te laten dan je hem gevonden hebt niet meer tijd hoeft te kosten dan de aanpassing adhoc doorvoeren en werkend te krijgen.
Imho moet je je gewoon blijven afvragen of dat wat je aan het doen bent wel iets gaat opleveren, anders dan alleen 'nettere code'.
Als het enkel daarom ging dan zou nu gelijk alle rotte code gerefactord worden op het moment dat er daadwerkelijk een wijziging nodig was ;)
Ik heb het over code die uit hetzelfde 'nest' komt, dus waarvoor jij/ik verantwoordelijk bent. Dat kan code van jezelf zijn, of code geschreven door iemand/iemanden ander en waarvoor je eigenlijk niet de verantwoordelijkheid wilt, omdat je weet dat het geen goede code is. Ook al heb je er geen hand in gehad, je moet alsnog met de billen bloot op dat moment. Wat de oorzaak ook geweest is, de klant zal niet blij zijn om te horen dat het brakke code is.
Als de waarheid vervelend is vindt niemand dat fijn om te horen. Het is echt niet pas een probleem op het moment dat je het probeert op te lossen. Het is nu al een probleem. Zeker wanneer je de schijn op wilt houden dat de code niet brak is lijkt het mij het handigste om er beetje bij beetje voor te zorgen dat de code niet meer brak is.
Met het tweede ben ik het helemaal eensch, maar soms heb je daar gewoon geen invloed op.
Het eerste punt vind ik erm, vaag. Wat bedoel je daar mee, dat ik/wij niet weten dat goede software maken belangrijk is?
Nee, eerder dat jullie niet weten wat de gevolgen van jullie technical debt is, of dit niet over weten te brengen op het project managment/sales afdeling. Dat kan aan jullie liggen, maar ligt over het algemeen vaker aan de managment/sales afdeling.
Als leidraad zou het kunnen functioneren misschien.
Lees gewoon het eerder aangehaalde boek eens en probeer het zo nu en dan eens toe te passen.

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


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17:02
Janoz schreef op woensdag 19 januari 2011 @ 22:50:
Als de waarheid vervelend is vindt niemand dat fijn om te horen. Het is echt niet pas een probleem op het moment dat je het probeert op te lossen.
Dat klopt wel, maar het probleem is dat ook rotte code meestal wel redelijk werkt, alleen de uitzonderingen op de regel laten de boel in het honderd lopen. Die uitzonderingen echter koment niet vaak voor, zodat de klant van mening is dat het product redelijk werkt, behalve die paar 'speciale situaties' die een onevenredige hoeveelheid werk vergen om op te lossen.
Nee, eerder dat jullie niet weten wat de gevolgen van jullie technical debt is, of dit niet over weten te brengen op het project managment/sales afdeling. Dat kan aan jullie liggen, maar ligt over het algemeen vaker aan de managment/sales afdeling.
Ah ok, tja ik ben me daar maar al te bewust van en ik zie het als mijn taak om het management er ook van te blijven overtuigen. Echter, prioriteiten liggen vaak ergens anders op het moment dat puntje bij paaltje komt, en het momentum van de 'andere partij' is op dat moment vaak moeilijk te stoppen.
Lees gewoon het eerder aangehaalde boek eens en probeer het zo nu en dan eens toe te passen.
Als ik tijd heb ga ik dat zeker doen .. :P

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21:22
alienfruit schreef op woensdag 19 januari 2011 @ 20:03:
Wat ik mijn nu al een tijd afvraag hoe werk je met unit tests als je zoveel afhankelijkheden hebt?
Dat zou je met Dependency Injection moeten oplossen om zo verschillende mock objecten te kunnen maken. Echter ben ik er daar ook nog niet helemaal uit hoe ik zoiets moet gaan ontwikkelen.
Je krijgt dan een constructor met mogelijk 10 verschillende interfaces als parameter. Volgens mij is dat inderdaad de bedoeling, zo kun je iedere gebruikte klasse binnen de klasse die je wilt testen aanroepen met een benodigde interface. Het is dan wel noodzakelijk dat iedere aangeroepen klasse ook zo werkt natuurlijk.

Zeker in het boek Working Effectively with Legacy Code wordt hier op ingegaan, maar omdat ik dat boek zo droog vind, kom ik er niet echt door en blijft het ook niet echt hangen.

Battle.net - Jandev#2601 / XBOX: VriesDeJ


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Jan_V schreef op donderdag 20 januari 2011 @ 07:53:
[...]
Dat zou je met Dependency Injection moeten oplossen om zo verschillende mock objecten te kunnen maken. Echter ben ik er daar ook nog niet helemaal uit hoe ik zoiets moet gaan ontwikkelen.
Maar op bestaande code is dat een stuk lastiger.
Je krijgt dan een constructor met mogelijk 10 verschillende interfaces als parameter. Volgens mij is dat inderdaad de bedoeling, zo kun je iedere gebruikte klasse binnen de klasse die je wilt testen aanroepen met een benodigde interface. Het is dan wel noodzakelijk dat iedere aangeroepen klasse ook zo werkt natuurlijk.
DI hoeft niet perse via de constructor te gaan natuurlijk
Zeker in het boek Working Effectively with Legacy Code wordt hier op ingegaan, maar omdat ik dat boek zo droog vind, kom ik er niet echt door en blijft het ook niet echt hangen.
Ik ga dat boek ook eens bestellen, het lijkt me wel interessant want ik loop ook vaak tegen het probleem van Legacy Code aan, waar je aan de ene kant van alles aan wil veranderen, maar aan de andere kant niet durft omdat je bang bent dat er van alles omvalt, omdat het afhankelijk is van de quircks van het systeem.

“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.”


Acties:
  • 0 Henk 'm!

  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21:22
Woy schreef op donderdag 20 januari 2011 @ 09:16:
[...]
DI hoeft niet perse via de constructor te gaan natuurlijk

[...]
Hoeft niet natuurlijk, maar als je het niet aan de constructor mee geeft, waar zou je het dan willen doen?
In een overload van een methode of iets dergelijks, of een property?
Nadeel is dan dat je weer in de gaten moet houden of je wel tegen het juiste object praat, anders zit je alsnog het hele systeem te testen.

Of zou je het op een andere manier willen doen?

Battle.net - Jandev#2601 / XBOX: VriesDeJ


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Mijn voorkeur gaat altijd uit naar setters (of properties bij .net). Dat maakt het imho altijd wat leesbaarder dan een reeks parameters in de constructor.

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


Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Janoz schreef op donderdag 20 januari 2011 @ 13:23:
Mijn voorkeur gaat altijd uit naar setters (of properties bij .net). Dat maakt het imho altijd wat leesbaarder dan een reeks parameters in de constructor.
Ja, maar in .NET kun je de properties gelijk initialiseren bij het aanmaken (Object Initialization), werkt zo:

C#:
1
2
3
4
5
6
MyObject o = new MyObject()
{
    PropString = "Jaep",
    PropInt = 3,
    PropBool = false
};


Dan hoef je je constructor niet onnodig te overloaden. Parameters in constructors zou je eigenlijk alleen moeten gebruiken voor verplichte properties / fields.

Acties:
  • 0 Henk 'm!

  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21:22
Hmm, als je met properties gaat werken, zou een dergelijke implementatie dan niet handig zijn?
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private IOtherClass1 _otherClass1 = null;

public IOtherClass1 OtherClass1
{
    get
    {
        if (_otherClass1 == null)
        {
            _otherClass1 = new OtherClass1();
        }
        return _otherClass1;
        }
    set{ _otherClass1 = value; }
}

Default je 'normale' object terug krijgen en als je iets anders wilt, dan een andere klasse setten.

Heb er nog steeds een minder warm gevoel bij als bij een constructor overloaden, je moet nu namelijk nog steeds weten welke klassen er allemaal worden gebruikt binnen je te testen 'unit'. Wanneer je deze in de constructor hebt staan, dan weet je zeker dat ze allemaal zijn geinitialiseerd met je eigen gekozen object. Wellicht initialiseer je teveel (heb je maar 1 object nodig ipv alle 5).

Misschien moet ik er eens een nachtje over slapen om het voordeel te zien.

Battle.net - Jandev#2601 / XBOX: VriesDeJ


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Topicstarter
Davio schreef op donderdag 20 januari 2011 @ 13:52:
[...]

Ja, maar in .NET kun je de properties gelijk initialiseren bij het aanmaken (Object Initialization), werkt zo:

C#:
1
2
3
4
5
6
MyObject o = new MyObject()
{
    PropString = "Jaep",
    PropInt = 3,
    PropBool = false
};


Dan hoef je je constructor niet onnodig te overloaden. Parameters in constructors zou je eigenlijk alleen moeten gebruiken voor verplichte properties / fields.
Ik ken .NET niet, maar zo te zien zou dat zeker mijn voorkeur hebben. Bij spring (DI bij java) kun je middels een annotatie op de setter aangeven dat een dependecy verplicht is. Dan krijg je nog steeds een foutmelding wanneer je (runtime) vergeet het verplichte veld te vullen.

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


Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Ik zie dat Microsoft er zelf ook een mooi verhaal over geschreven heeft: http://msdn.microsoft.com/en-us/magazine/cc163739.aspx

Acties:
  • 0 Henk 'm!

  • Killemov
  • Registratie: Januari 2000
  • Laatst online: 24-08 23:40

Killemov

Ik zoek nog een mooi icooi =)

Davio schreef op donderdag 20 januari 2011 @ 13:52:
[...]

Ja, maar in .NET kun je de properties gelijk initialiseren bij het aanmaken (Object Initialization), werkt zo:

C#:
1
2
3
4
5
6
MyObject o = new MyObject()
{
    PropString = "Jaep",
    PropInt = 3,
    PropBool = false
};


Dan hoef je je constructor niet onnodig te overloaden. Parameters in constructors zou je eigenlijk alleen moeten gebruiken voor verplichte properties / fields.
Huh? Zo maak je in Java een instantie van een ter plekke gedefinieerde class. (Anonymous inner class dus.)

De lengte van een method of function is ondergeschikt aan zo'n beetje al het andere. Een aardige tip voor de refactorjunkies is kijken naar de oppervlakte van de code. Als je veel geneste constructies hebt, 10 geneste for-loops anyone?, dan loont het om te onderzoeken of er een aantal uit kunnen worden getrokken.

Hey ... maar dan heb je ook wat!


Acties:
  • 0 Henk 'm!

  • Killemov
  • Registratie: Januari 2000
  • Laatst online: 24-08 23:40

Killemov

Ik zoek nog een mooi icooi =)

Janoz schreef op donderdag 20 januari 2011 @ 15:25:
[...]

Ik ken .NET niet, maar zo te zien zou dat zeker mijn voorkeur hebben. Bij spring (DI bij java) kun je middels een annotatie op de setter aangeven dat een dependecy verplicht is. Dan krijg je nog steeds een foutmelding wanneer je (runtime) vergeet het verplichte veld te vullen.
Dat is enigzins vreemd. De DI constructie zou er voor moeten zorgen dat de container die de class load dat automatisch invult. Dat lijkt me juist het hele doel van DI. Toch?

Hey ... maar dan heb je ook wat!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Davio schreef op donderdag 20 januari 2011 @ 13:52:
[...]

Ja, maar in .NET kun je de properties gelijk initialiseren bij het aanmaken (Object Initialization), werkt zo:

C#:
1
2
3
4
5
6
MyObject o = new MyObject()
{
    PropString = "Jaep",
    PropInt = 3,
    PropBool = false
};
Dat is echter ook niks anders dan een andere manier van schrijven van
C#:
1
2
3
4
MyObject o = new MyObject();
o.PropString = "Jaep";
o.PropInt = 3;
o.PropBool = false;

“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.”


Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Nee, het is niet anders, maar ik vind het wel handiger, anders heb je overal die variabelenaam weer voor staan en die is vaak wel wat langer dan 'o'.

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Meuh, ik vind dat constructor initialisatie altijd de voorkeur zou moeten hebben over dit. Waarom runtime controleren wat je compile-time (of, in het geval van een beetje IDE, schrijf-time) kunt controleren? Nee, je hebt geen named variables bij constructors, maar qua syntax kun je nog wel zoiets doen:

Java:
1
2
3
4
5
Object obj = new Object(
   pietje,
   henkje,
   klaasje
);


Een lelijke oplossing om toch een soort van 'named' params te krijgen is het builder pattern misbruiken. Nee dit moet je niet overnemen, nee dit is niet ongelofelijk slim om te doen, en ja, named arguments zou een goed iets zijn:

Java:
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
class PietjeBuilder {
    public String pietje;
    public Object klaas;
    public int henk;
}

class Pietje {
   private final String pietje;
   private final Object klaas;
   private final int henk;

   // ja ook dit zou beter moeten kunnen. Zelfs met IDE hulp wordt je hier simpel van.
   public Pietje(String pietje, Object klaas, int henk) {
      this.pietje = pietje;
      this.klaas = klaas;
      this.henk = henk;
   }
}

public static void main(String[] args) {
    PietjeBuilder pietjeBuilder = new PietjeBuilder();
    pietjeBuilder.pietje = "HENKJE";
    pietjeBuilder.klaas = RandomObjectBuilderFactory.getFactory().newInstance(new Random().nextInt(1337));
    pietjeBuilder.henk = 1337;

    Pietje pietje = new Pietje(
       pietjeBuilder.pietje,
       pietjeBuilder.klaas,
       pietjeBuilder.henk
    );
}


Named parameters, verplicht in te vullen @ build-time, wat wil je nog meer? :+

Fake edit: Ow wacht, dit kan ook nog:

Java:
1
2
3
4
5
6
   PietjeBuilder pb = new PietjeBuilder();
   Pietje pietje = new Pietje(
      pb.pietje = "henk",
      pb.klaas = new Object(),
      pb.henk = 3771
   );


:+ :+ :+ maar het werkt wel. Je moet alleen voor het object dat je wilt initialiseren een nieuw builder object maken met dezelfde velden.

[random idee] Misschien is er een tooltje te bouwen die automagisch dit soort builders voor elk object aanmaakt oid[/random idee]


Echte edit: Wat ook nog kan: initializer block misbruiken, bouw je een subclass inline. Helaas geen compile-time-verplichte-velden-verplichting.

Java:
1
2
3
4
5
Pietje pietje = new Pietje() {{
    setPietje("henk");
    setKlaasje("piet");
    setLeetje(1337);
}};


Echte edit 2: Wat V zegt dus.

[ Voor 6% gewijzigd door YopY op 20-01-2011 22:03 ]


Acties:
  • 0 Henk 'm!

  • RSchellhorn
  • Registratie: Augustus 2001
  • Laatst online: 09:01
Killemov schreef op donderdag 20 januari 2011 @ 17:00:
[...]

Huh? Zo maak je in Java een instantie van een ter plekke gedefinieerde class. (Anonymous inner class dus.)
Inderdaad, maar je moet een initializer blok gebruiken om de variabelen/setters aan te roepen. Correcte Java syntax is dus:

Java:
1
2
3
4
5
6
MyObject obj = new MyObject() {
  {
    setA("a")
    setB("b")
  }
};


Nadeel is dat dit natuurlijk niet voor final klassen werkt.
YopY schreef op donderdag 20 januari 2011 @ 21:58:
Nee, je hebt geen named variables bij constructors...
Moderne JVM talen (lees: Scala) hebben dit wel, geen builders meer nodig! En dus significant minder code :)

Scala:
1
2
3
case class Foo(aap: String, noot: String, mies: String)

val foo = Foo( mies = "mies", noot = "noot", aap = "aap" )

[ Voor 28% gewijzigd door RSchellhorn op 20-01-2011 22:10 ]

"Ik heb zo veel soep gegeten, dat kan een mens niet aan. Ik heb zo veel soep gegeten, kan bijna niet meer staan. Ik zat daar maar te slurpen achter die grote kop en als ik bijna klaar was, dan schepten ze weer op!" (Hans Teeuwen)


Acties:
  • 0 Henk 'm!

  • Killemov
  • Registratie: Januari 2000
  • Laatst online: 24-08 23:40

Killemov

Ik zoek nog een mooi icooi =)

RSchellhorn schreef op donderdag 20 januari 2011 @ 22:00:
[...]
Inderdaad, maar je moet een initializer blok gebruiken om de variabelen/setters aan te roepen. Correcte Java syntax is dus:

Java:
1
2
3
4
5
6
MyObject obj = new MyObject() {
  {
    setA("a")
    setB("b")
  }
};
Ah, het ging me even om het verschil tussen C# en Java. Kleine brainfuck als je van de een naar de ander gaat dus.

Hey ... maar dan heb je ook wat!


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
RSchellhorn schreef op donderdag 20 januari 2011 @ 22:00:
Moderne JVM talen (lees: Scala) hebben dit wel, geen builders meer nodig! En dus significant minder code :)

Scala:
1
2
3
case class Foo(aap: String, noot: String, mies: String)

val foo = Foo( mies = "mies", noot = "noot", aap = "aap" )
Todo: Scala leren :+.

Nu kun je met Spring Framework op een paar manieren een object initialiseren:

* 'Gewoon', dwz params op volgorde doorgeven
* Per positie, ongeveer hetzelfde als 'gewoon' maar dan geef je een index-parameter mee
* Per type, dus een ctor die een string en een int verwacht geef je een int en een string en Spring zoekt vanzelf uit welke waarbij hoort (hoef je de volgorde niet te weten / aan te passen)
* Per naam (sinds Spring 3.0). Copypasta-voorbeelden:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <!-- gewoon -->
  <bean id="foo" class="x.y.Foo">
      <constructor-arg ref="bar"/>
      <constructor-arg ref="baz"/>
  </bean>

  <!-- positie / index -->
  <bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
  </bean>

  <!-- type -->
  <bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
  </bean>

  <!-- naam -->
  <bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateanswer" value="42"/>
  </bean>


Natuurlijk is dit allemaal runtime / startup time (alhoewel er mogelijk tools zijn die dit on-the-fly nakijken), en is het veel typ-intensiever dan het gewoon in de code te doen. Aan de andere kant, zo heb je wel veel controle over je applicatie zonder dat je de daadwerkelijke code in hoeft te duiken. Maar het nut en de onzin van Spring's DI en objectinitialisatie kun je een topic op zich aan wijden.

Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 21:41

RayNbow

Kirika <3

.oisyn schreef op woensdag 19 januari 2011 @ 21:38:
[...]

Ja, en als die functie is opgesplitst in 5 niveaus diep, dan spring je en spring je en wordt de code zo onoverzichtelijk als de pest.
Als het noodzakelijk is dat je de diepte in moet springen, dan is de code gewoon brak. Een functie behoort (grotendeels) begrijpbaar te zijn zonder de intieme details van elke aangeroepen functie te kennen. Het is soms geen eens mogelijk om de intieme details van een aangeroepen functie te kennen, omdat je niet over de broncode beschikt.

Het voorbeeld in het Extract till you Drop artikel vind ik in ieder geval onduidelijk. Op basis van de naamgeving van de functies alleen kun je niet de werking van de class uitvogelen. Je wordt hier genoodzaakt om door de code heen te springen.


Maar goed, als we het toch over springen-naar-definities hebben, hoe zou je de definitie van primes in m'n eerder geposte Haskell voorbeeld proberen te begrijpen?
Primes "call" graph
^ Toch niet door telkens naar elke definitie te springen, hoop ik?

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

RayNbow schreef op vrijdag 21 januari 2011 @ 10:34:
Het voorbeeld in het Extract till you Drop artikel vind ik in ieder geval onduidelijk.
Exactly my point. Dus we zijn het gewoon eens ;)
Maar goed, als we het toch over springen-naar-definities hebben, hoe zou je de definitie van primes in m'n eerder geposte Haskell voorbeeld proberen te begrijpen?
Die is vrij simpel te begrijpen. Of ie ook correct is is een ander verhaal (als in, ik zie dat je definities kloppen, maar of de recursie ook goed gaat heb ik wat meer tijd voor nodig).

[ Voor 10% gewijzigd door .oisyn op 21-01-2011 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.


Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 18:28

alienfruit

the alien you never expected

Ik doe het altijd op deze manier (builders):
https://gist.github.com/779495

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:51
@RayNbow: de vraag is echter of jou code duidelijker wordt van het afsplitsen van méér functies. Ik vind de aparte declaratie van oddprimes in jouw code zeker overbodig. Dit is korter en leest makkelijker:
Haskell:
1
primes = 2 : filter isPrime [3,5..]

Op dezelfde manier zou ik isPrime gewoon zo schrijven:
Haskell:
1
isPrime n = primeFactors n == [n]

Maar dit heeft niet echt met het afsplitsen van functies te maken.

Voor de rest zijn alle functies die je gebruikt gewoon "nodig" in de zin dat je ze niet redelijkerwijs kunt inlinen zonder het gehele programma aanzienlijk complexer te maken, ook al zijn de functies zelf relatief kort (wat niet ongebruikelijk is in functionele programmeertalen).

Dus kom ik weer uit op de cyclomatic complexity van eerder. Het is geen perfecte metric, maar het lijkt me geen slechte leidraad om de complexiteit zo laag mogelijk te houden, en van programma's met vergelijkbare complexiteit de kortste de voorkeur te geven. (In het voorbeeld hierboven zou ik bijvoorbeeld zeggen dat "primeFactors n == [n]" simpeler is dan de variant met een case-statement, en dus de voorkeur geniet, zeker aangezien in dit geval er geen verschil in efficiëntie is.)

[ Voor 10% gewijzigd door Soultaker op 21-01-2011 13:38 ]


Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 21:41

RayNbow

Kirika <3

.oisyn schreef op vrijdag 21 januari 2011 @ 11:20:
[...]

Exactly my point. Dus we zijn het gewoon eens ;)
Ah, okay. :)
[...]

Die is vrij simpel te begrijpen. Of ie ook correct is is een ander verhaal (als in, ik zie dat je definities kloppen, maar of de recursie ook goed gaat heb ik wat meer tijd voor nodig).
Om welke recursie gaat het? Die wederzijdse recursie tussen primes en primeFactors (waarbij het van belang is dat primeFactors niet meer elementen van primes consumeert dan dat er al geproduceerd zijn) of de recursie van de hulpfunctie factor?
Soultaker schreef op vrijdag 21 januari 2011 @ 13:36:
@RayNbow: de vraag is echter of jou code duidelijker wordt van het afsplitsen van méér functies. Ik vind de aparte declaratie van oddprimes in jouw code zeker overbodig. Dit is korter en leest makkelijker:
Haskell:
1
primes = 2 : filter isPrime [3,5..]
In dit specifieke voorbeeld zou ik zeggen dat er voor beide definities wat te zeggen valt, maar ik vind de een niet moeilijker of makkelijker te lezen dan de ander.

Er bestaan trouwens wel alternatieve manieren om een lijst priemgetallen te genereren waarbij het wel handig is om een naam te geven aan de oneven priemgetallen.
Op dezelfde manier zou ik isPrime gewoon zo schrijven:
Haskell:
1
isPrime n = primeFactors n == [n]

Maar dit heeft niet echt met het afsplitsen van functies te maken.
Die definitie is inderdaad korter en makkelijker te begrijpen.

(Het kost wel een extra vergelijking tegenover een simpele pattern match, maar da's verwaarloosbaar :p)

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Builders zijn leuk, maar je hebt geen compile-time checken of je wel alle waarden toekent - dat krijg je pas @ runtime, waardoor bugs later opgemerkt worden.

Tijd voor een taalfeature waarbij je @compile-time verplicht functies aan kunt laten roepen.
Pagina: 1 2 Laatste