Programmeren van onderaf

1993

(Dit essay komt uit de introductie vanOn Lisp .)

Het is een langstaand principe van programmeerstijl dat de functionele elementen van een programma niet te groot mogen zijn. Als een component van een programma groeit buiten het stadium waarin het gemakkelijk te begrijpen is, wordt het een massa complexiteit die fouten net zo gemakkelijk verbergt als een grote stad voortvluchtigen verbergt. Dergelijke software zal moeilijk te lezen, moeilijk te testen en moeilijk te debuggen zijn.

In overeenstemming met dit principe moet een groot programma worden verdeeld in stukken, en hoe groter het programma, hoe meer het moet worden verdeeld. Hoe verdeel je een programma? De traditionele benadering wordt top-down design genoemd: je zegt "het doel van het programma is om deze zeven dingen te doen, dus ik verdeel het in zeven hoofdroutines. De eerste subroutine moet deze vier dingen doen, dus die zal op zijn beurt vier van zijn eigen subroutines hebben", enzovoort. Dit proces gaat door totdat het hele programma het juiste niveau van granulariteit heeft - elk deel groot genoeg om iets substantieels te doen, maar klein genoeg om als een enkele eenheid te worden begrepen.

Ervaren Lisp-programmeurs verdelen hun programma's anders. Naast top-down design volgen ze een principe dat bottom-up design genoemd kan worden - de taal aanpassen aan het probleem. In Lisp schrijf je je programma niet alleen naar de taal toe, maar bouw je ook de taal op naar je programma toe. Terwijl je een programma schrijft, kun je denken "ik wou dat Lisp dit of dat operator had". Dus ga je het schrijven. Daarna realiseer je je dat het gebruik van de nieuwe operator het ontwerp van een ander deel van het programma zou vereenvoudigen, enzovoort. Taal en programma evolueren samen. Net als de grens tussen twee oorlogvoerende staten, wordt de grens tussen taal en programma getrokken en opnieuw getrokken, totdat deze uiteindelijk tot rust komt langs de bergen en rivieren, de natuurlijke grenzen van je probleem. Uiteindelijk zal je programma eruitzien alsof de taal ervoor is ontworpen. En wanneer taal en programma goed bij elkaar passen, krijg je code die helder, klein en efficiënt is.

Het is de moeite waard om te benadrukken dat bottom-up design niet alleen betekent dat je hetzelfde programma in een andere volgorde schrijft. Wanneer je bottom-up werkt, krijg je meestal een ander programma. In plaats van een enkel, monolithisch programma, krijg je een grotere taal met meer abstracte operatoren, en een kleiner programma dat erin geschreven is. In plaats van een latei, krijg je een boog.

In typische code, als je de delen die slechts boekhouding zijn abstraheert, is wat overblijft veel korter; hoe hoger je de taal opbouwt, hoe minder afstand je van boven naar beneden hoeft af te leggen. Dit brengt verschillende voordelen met zich mee:

  1. Door de taal meer van het werk te laten doen, levert bottom-up design programma's op die kleiner en wendbaarder zijn. Een korter programma hoeft niet in zoveel componenten te worden verdeeld, en minder componenten betekent programma's die gemakkelijker te lezen of te wijzigen zijn. Minder componenten betekent ook minder verbindingen tussen componenten, en dus minder kans op fouten daar. Net zoals industriële ontwerpers ernaar streven het aantal bewegende delen in een machine te verminderen, gebruiken ervaren Lisp-programmeurs bottom-up design om de grootte en complexiteit van hun programma's te verminderen.

  2. Bottom-up design bevordert codehergebruik. Wanneer je twee of meer programma's schrijft, zullen veel van de hulpprogramma's die je voor het eerste programma hebt geschreven ook nuttig zijn in de volgende. Zodra je een grote basis van hulpprogramma's hebt verworven, kan het schrijven van een nieuw programma slechts een fractie van de inspanning vergen die nodig zou zijn als je met ruwe Lisp zou beginnen.

  3. Bottom-up design maakt programma's gemakkelijker te lezen. Een instantie van dit type abstractie vraagt de lezer om een algemene operator te begrijpen; een instantie van functionele abstractie vraagt de lezer om een specifieke subroutine te begrijpen. [1]

  4. Omdat het je ertoe aanzet om altijd te zoeken naar patronen in je code, helpt het werken met bottom-up om je ideeën over het ontwerp van je programma te verduidelijken. Als twee verre componenten van een programma qua vorm vergelijkbaar zijn, zul je ertoe aangezet worden om de gelijkenis op te merken en het programma misschien op een eenvoudigere manier te herontwerpen.

Bottom-up design is tot op zekere hoogte mogelijk in andere talen dan Lisp. Overal waar je bibliotheekfuncties ziet, is bottom-up design aan de gang. Lisp geeft je echter veel bredere mogelijkheden op dit gebied, en het uitbreiden van de taal speelt een proportioneel grotere rol in de Lisp-stijl - zozeer zelfs dat Lisp niet alleen een andere taal is, maar een heel andere manier van programmeren.

Het is waar dat deze stijl van ontwikkeling beter geschikt is voor programma's die door kleine groepen kunnen worden geschreven. Tegelijkertijd vergroot het echter de grenzen van wat door een kleine groep kan worden gedaan. In The Mythical Man-Month stelde Frederick Brooks voor dat de productiviteit van een groep programmeurs niet lineair groeit met de grootte ervan. Naarmate de grootte van de groep toeneemt, neemt de productiviteit van individuele programmeurs af. De ervaring van Lisp-programmering suggereert een vrolijkere manier om deze wet te formuleren: naarmate de grootte van de groep afneemt, neemt de productiviteit van individuele programmeurs toe. Een kleine groep wint, relatief gezien, simpelweg omdat hij kleiner is. Wanneer een kleine groep ook profiteert van de technieken die Lisp mogelijk maakt, kan hij er met kop en schouders bovenuit steken.

Nieuw: Download On Lisp gratis.


[1] "Maar niemand kan het programma lezen zonder al je nieuwe hulpprogramma's te begrijpen." Om te zien waarom dergelijke uitspraken meestal onjuist zijn, zie Sectie 4.8.