Overzichtelijk programmeren

Een paar algemene vuistregels:

De lijst

Gebruik accolades

De inhoud van een if-statement moet tussen {accolades}. Bij maar één statement mag je die weglaten. Ik adviseer dat niet te doen. Zo zie je sneller wat bij elkaar hoort, en hoef je er niet aan te denken als je een tweede statement bijvoegt.

Laat code inspringen

Om aan te geven wat onderdeel is van wat, laten we code inspringen. Regels tussen een “ {” en een “ ” begint een kolom verder naar rechts.

Zo zie je snel welke haakjes bij elkaar horen.

1
2
3
4
5
6
7
8
9
10
11
12
13
if instance_exists(enemy{
    with enemy {
        if y > 400 {
            if gravity > 0 {
                vspeed = 0;
            }
            else {
                vspeed += 0.01;
            }
        }
        hspeed += 0.1;
    }
}

In dit voorbeeld horen regels 2 en 12 bij elkaar. Dat kun je snel zien, want ze beginnen op dezelfde kolom.

Gebruik witruimte

Gebruik vorm om de inhoud te structureren, zoals in een gedicht. Als je dat niet doet ...

1
2
3
4
5
6
7
b=0;
for (i=1;i<=15;i+=1){
if real(argument[i])=0{break;}else{b+=1;}}
a=ceil(random(argument0-b));
for (i=1;i<=b;i+=1){
if a>=argument[i]{a+=1}}
return a;

... ontstaat een brij van tekens zonder structuur. Neem dus de tijd om het te ordenen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
b = 0;

for (i = 1i <= 15i += 1{
    if real(argument[i]) = 0 {
        break;
    }
    else {
        b += 1;
    }
}

a = ceil(random(argument0 - b));
for (i = 1i <= bi += 1{
    if a >= argument[i{
        a += 1;
    }
}

return a;

Zo zie je de structuur en de afzonderlijke onderdelen beter.

Doe alles in het Engels

Alle ingebouwde woorden zijn al in het Engels. Als je alles in het Engels doet lijkt het het meest op mensentaal. Bovendien kunnen dan buitenlandse programmeurs het ook lezen, mocht dat ooit nodig blijken.

Geef dingen logische namen

Zorg dat alles een naam heeft die beschrijft wat het is. Dus niet zo:

1
2
3
4
5
6
if a > 0 {
    with en01 {
        compute(xdyd);
    }
    a = 0;
}

maar zo:

1
2
3
4
5
6
if enemies_killed_count > 0 {
    with flyingenemyobject {
        enemy_compute_shortest_path(xgoalygoal);
    }
    enemies_killed_count = 0;
}

Zo beschrijft de code zichzelf.

Voor- en achtervoegsels

Gebruik een standaard-naamgevingsschema met voorvoegsels en achtervoegsels om om dingen te groeperen en dubbele namen te voorkomen.

Verder gebruik ik voor objecten nog deze regel:

Dus het object menu omdat er maar één menu is, en het object menubuttonobject omdat er meerdere menubuttons zijn. De naam menubutton blijft dan beschikbaar als variabelenaam, bijvoorbeeld var menubutton = instance_nearest(mouse_xmouse_ymenubuttonobject);.

Gebruik true, false, noone

Als een variabele alleen aan of uit kan zijn, gebruik dan true en false in plaats van 0 en 1, zodat je kan zien dat het geen andere waarden kan hebben.

Als een variabele een instantie-id bevat, gebruik dan noone voor géén instantie. Dan kun je meteen aflezen dat deze variabele instantie-id’s bevat.

Voor strings, gebruik "" als standaardwaarde.

Bedenk een passende standaardwaarde voor variabelen, die past bij het waardenbereik.

Houd variabelen typevast

Als een variabele een string is, zorg dat die altijd een string is. Op die manier is het type steeds duidelijk. Uitzondering is de speciale waarde undefined die je mooi kunt inzetten als standaardwaarde voor allerlei dingen en de functie is_undefined kan gebruiken.

Gebruik constanten

Constanten als fa_centeren c_red bevatten getallen, maar met deze woorden wordt je code beter leesbaar. Gebruik dit idee ook voor je eigen getallen. Heb je drie wapens, maak dan drie constanten aan, en gebruik die overal. De getalswaarde is dan helemaal niet belangrijk.

1
2
3
4
5
switch current_weapontype {
    case weapontype_shotgun:      /*do something*/break
    case weapontype_minigun:      /*do something*/break
    case weapontype_flamethrower/*do something*/break
}

Het is ook handig om een weapontype_none te maken voor “geen wapen”.

Noem hetzelfde ding steeds hetzelfde

Als je je wapentypevariabele weapontype noemt, is het handig om alles dat te maken heeft met wapentypes, weapontype te noemen en niet later ineens wp of weapon.

1
2
3
4
5
switch current_weapontype {
    case weapontype_shotgun:      /*do something*/break
    case weapontype_minigun:      /*do something*/break
    case weapontype_flamethrower/*do something*/break
}

Vervang “if a = true” door “if a”

De volgende twee doen hetzelfde als foo een boolean variabele is:

De volgende twee zijn ook inwisselbaar:

Vervang “&&” door “and”

Computertalen hebben de neiging steeds beter op normaal Engels te lijken. Het ligt dus voor de hand om voor de logische operatoren de Engelse varianten te gebruiken:

Voor de bitsgewijze operatoren |, & en ^ zijn dergelijke alternatieven er niet.

Gebruik comments nuttig en spaarzaam

Voeg comments toe waar nodig, maar niet meer dan dat. Te veel comments is ook niet handig. Handige comments zijn:

1
2
//point_line_distance(x, y, p, q, s, t)
//returns the distance from (x, y) to line (p, q)-(s, t).

Voeg geen commentaren toe die alleen de code vertalen.

1 instance_create(320240enemyobject); //create the enemy

Het commentaar zegt niets dat niet al in de code staat, maar voegt wel meer tekst toe. Hou deze vuistregel aan: de code vertelt hoe, het commentaar vertelt waarom.

Begin elk event met ///Omschrijving hier op de eerste regel. Je omschrijving verschijnt dan in de actielijst.

Wijzig commentaar samen met code

Als je code aanpast, en er staat commentaar bij, verander dat commentaar dan ook. Anders klopt het misschien niet, en verkeerd commentaar is nog erger dan géén commentaar.

Breek te lange regels af

Zorg dat je alleen de verticale scrollbalk nodig hebt.

Als regels te lang worden, dan raad ik aan om ze op logische plaatsen af te breken. Bij lange functieaanroepen kun je elk argument op een aparte regel zetten, bijvoorbeeld zo:

1
2
3
4
5
6
var dist = point_distance(
    controllerobject.node_x[controllerobject.edge_b[e]],
    controllerobject.node_y[controllerobject.edge_b[e]],
    controllerobject.node_x[controllerobject.edge_e[e]],
    controllerobject.node_y[controllerobject.edge_e[e]]
);

Op deze manier gebruik je de haakjes net zoals je accolades gebruikt.

Gebruik scripts

Maak scripts waar het kan. Dan kun je het een (beschrijvende) naam geven en dat maakt het overzicht groter. Het advies is om al een script te maken zodra je een berekening twee keer of vaker nodig hebt.

Zet argumenten in tijdelijke variabelen

De variabelenamen argument0 etc. zijn weinig beschrijvend. Als je argument een instantie is, begin dan met var inst = argument0; zodat je de beschrijvende naam inst kunt gebruiken.

1
2
3
4
5
6
7
8
var ind = argument0;

var dist = point_distance(
    x1[indcount[ind]], y1[indcount[ind]],
    x2[indcount[ind]], y2[indcount[ind]]
) + margin[n];
var box_xdiff = abs(box_x2[ind] - box_x1[ind]) / dist;
var box_ydiff = abs(box_y2[ind] - box_y1[ind]) / dist;

Deel code op in logische blokken

Zet niet te veel code in één actie, maar deel die op in logische stukken en geef elk stuk een duidelijke omschrijving. Dan krijg je overzicht over wat er gebeurt in een event, en kun je makkelijker stukken verwisselen.

Kies een fijne kleurcodering

Pas in de Preferences de syntaxismarkering aan naar je voorkeuren, zodat je dingen snel kan terugvinden.