Je zal altijd zien dat je de pittigste problemen tegenkomt net als de deadline in je nek begint te hijgen. Problemen zo complex dat zelfs de gebruiksaanwijzing je niet kan helpen, omdat die er alleen maar globaal op ingaat. Verschrikkelijk! Sommige van deze problemen worden pas zichtbaar als de code al is gecommit. Wij benoemen zeven van de grootste problemen waar programmeurs mee te maken krijgen.

Multithreading

Het leek zo'n goed idee. Splits je programma op in verschillende onafhankelijke secties en laat het besturingssysteem ze draaien als onafhankelijke kleine programma's. Als processoren vier, zes, acht of zelfs meer cores hebben, waarom je programma dan niet zo schrijven dat deze vier, zes, acht of zelfs meer threads heeft die al deze cores onafhankelijk van elkaar gebruiken?

Het idee werkt wel, als de onderdelen écht apart van elkaar werken en niets met elkaar te maken hebben. Maar zodra zij variabelen moeten benaderen of bits moeten wegschrijven naar dezelfde bestanden is het over en uit. Een van deze threads zal als eerste bij je data zijn en je kan niet voorspellen welke thread dat zal zijn.

Daarom maken wij monitoren, semaforen en andere tools om de gemultithreade rotzooi een beetje te ordenen. Als ze werken, werken ze. Maar ze voegen wel een extra laag complexiteit toe en veranderen de kunst van het opslaan van data in een variabele in iets dat wat meer aandacht vereist.

Als het niet werkt, is het pure chaos. De data slaat nergens meer op, allemaal losse bits in het geheugen. Succes met het uitvogelen waar wat hoort. De meeste ontwikkelaars blokkeren grote blokken data zodat er maar één thread tegelijk aan kan zitten. Dat kan de chaos een beetje indammen, maar dat gaat dan wel weer ten koste van de prestatieverbeteringen die meerdere threads met zich meebrengen. En dan kan je net zo goed een "single-threaded"-programma schrijven.

Closures

Iemand heeft ooit besloten dat het handig zou zijn om functies te behandelen als data. Dit werkte goed in simpele instances, maar programmeurs liepen tegen problemen aan als deze functies andere data benaderden. Deze functies werden "free variables" genoemd. Welke versie was de juiste? Was het de data wanneer de function call was geïnitieerd? Of was het wanneer de functie zelf draaide? Dit was vooral belangrijk voor JavaScript. Vooral bij deze taal konden er soms grote hiaten ontstaan.

De oplossing? "closure" is een van de grootste hoofdpijndossiers voor JavaScript (en nu Java- en Swift)-programmeurs. Newbies en zelfs veel veteranen komen er niet altijd uit wat er precies gesloten is en waar de grenzen van deze zogenaamde closures zijn.

De naam helpt ook niet echt. Het is niet alsof de toegang permanent is gesloten, zoals men in een kroeg soms "Laatste ronde" roept en "De hoogste tijd" gaat draaien. Sterker nog, de toegang is er gewoon nog, maar alleen via een wormhole in het data-time continuüm, een vreemd tijdsverschuivend mechanisme waarvan het slechts een kwestie van tijd is voordat er een sci-fi-tv-serie aan gewijd wordt (een Reboot kloon?) Maar een naam als "Complex Stack Access Mechanism" of "Data Control Juggling System" lijkt te lang. Dus we houden het maar op "Closures".

Too big data

Als je RAM vol begint te lopen gaat er van alles mis. Het maakt niet uit of je met supercomplexe analyses bezig bent of een simpel spreadsheetje. Als je computer geen RAM meer over heeft, wordt er geschakeld naar zogenaamd virtueel geheugen, meestal te vinden op je (in vergelijking) supertrage harde schijf. Het is beter dan een crash, maar alles wordt wel ongelooflijk traag.

Het probleem is dat harde schijven gemiddeld 20 tot 30 keer trager zijn dan RAM en dat goedkopere consumenten-schijven zelfs nog trager zijn dan dat. Als er dan ook nog eens andere processen data moeten wegschrijven op de schijf, is het helemaal dramatisch aangezien de schijven maar één ding tegelijk kunnen doen.

Het activeren van virtueel geheugen verergert andere verborgen problemen met je software. Als er threading glitches ontstaan, breken deze veel sneller, omdat de threads die zijn verhuisd naar de harde schijf veel trager draaien dan de andere threads. Als deze later weer naar RAM geswapt worden, komt de boel weer op op gang, tenminste, andere, nieuwere threads zullen daar weer op moeten wachten. Als de code perfect is, resulteert dit slechts is trage software, als de code niet perfect is, kan de boel al snel crashen. Dat is slechts een klein voorbeeld.

Het managen van dit alles is een echte uitdaging voor programmeurs die met grote hopen data werken. Iedereen die ook maar een beetje slordig is, eindigt met code die in de productie-omgeving niet vooruit te branden is. De boel kan goed werken in testcases, maar in de echte wereld kan de boel goed onderuit gaan.

NP-complete

Iedereen met een universitair diploma in computerwetenschappen in de achterzak kent de mysterieuze problemen die nondeterministic polynomial complete (NP-complete) met zich mee kan brengen. De details rondom dit probleem kunnen makkelijk een heel semester in beslag nemen om onder de knie te krijgen en zelfs dan zijn er veel CS-studenten die er alleen een vaag begrip aan overhouden dat niemand deze problemen zomaar kan oplossen omdat ze te moeilijk zijn.

De NP-complete problemen zijn vaak behoorlijk pittig als je ze simpelweg met een brute-force-aanval te lijf gaat. Het "handelsreizigersprobleem" (TSP) kan bijvoorbeeld exponentieel lang duren als de af te leggen route steeds meer steden gaat bevatten. Het oplossen van het knapzakprobleem door een subset van nummers te vinden die het dichtstbij de N-waarde komen door alle mogelijke subsets te proberen, kan ervoor zorgen dat je een hele hoop subsets moet afgaan. Iedereen is bang voor dit probleem, omdat het het prototype is van een van de grootste boeman in de IT: onschaalbare algoritmen.

De grap is dat sommige NP-complete makkelijk op te lossen zijn met een simpele benadering. De algoritmen beloven geen exacte oplossing, maar het komt aardig in de buurt. Ze zullen niet de perfecte route vinden voor de handelsreiziger, maar de afwijking is niet al te groot waardoor het juiste antwoord sneller gevonden kan worden.

Het bestaan van deze redelijk goede oplossing maken het probleem alleen maar mysterieuzer. Niemand weet zeker of deze problemen echt heel moeilijk zijn of juist zo makkelijk dat je genoegen kunt nemen met een antwoord dat slechts goed genoeg is.

Beveiliging

"There are known knowns; there are things we know we know," Zei Donald Rumsfeld, Secretaris van defensie tijdens Bush. "We also know there are known unknowns; that is to say we know there are some things we do not know. But there are also unknown unknowns, the ones we don't know we don't know."

Rumsfeld zei dit tijdens een persconferentie over de oorlog in Irak. Hetzelfde geldt helaas ook voor computerbeveiliging. De grootste problemen zijn de beveiligingsgaten waarvan wij niet eens weten dat deze mogelijk zijn. Iedereen begrijpt dat je geen makkelijk te raden wachtwoord moet gebruiken. Dat is een "known known". Maar wie heeft je ooit verteld dat je netwerkhardware een eigen softwarelaag bevat? De mogelijkheid dat iemand je besturingssysteem overslaat en zich direct richt op deze geheime laag is een "unknown unknown".

De mogelijkheid dat zulke hacks uitgevoerd kunnen worden, zijn vast niet onbekend voor jou, maar wat als er meerdere zijn? We hebben geen idee hoe wij deze onderdelen moeten beveiligen als we niet eens van hun bestaan afweten. Je kan je wachtwoord nog zo complex maken, maar er bestaan gaten en lekken waar je je niks bij kan voorstellen. Dat is het leuke van werken in de computerbeveiliging. Als je dat idee doortrekt op programmeren zal je ook goed rekening moeten houden met beveiliging. Je kan niet simpelweg alles in de handen van beveiligingsexperts leggen en verwachten dat ze jouw rommel gaan opruimen.

Encryptie

Encryptie klinkt krachtig en ondoordringbaar als zelfs de politie vraagt om achterdeurtjes, verzwakking en het achterhouden van kwetsbaarheden. Het probleem is echter dat de meeste vormen van encryptie gebouwd zijn rondom een vage wolk van onzekerheid. De wiskundige bewijzen die zij hebben zijn afhankelijk van vage aannames. Het is nou eenmaal moeilijk om zeer grote getallen of een goede log uit te rekenen.

Zijn deze problemen echt moeilijk? Niemand heeft algoritmes voor het oplossen van deze problemen geopenbaard, maar dat betekent niet dat de oplossingen niet bestaan. Als je een manier zou vinden om elk gesprek af te kunnen luisteren of kon inbreken in elke bank, zou jij dat dan kenbaar maken en iedereen helpen de gaten te dichten, of zou je je mond houden?

De echte uitdaging is het gebruiken van encryptie in je eigen code. Zelfs als we de standaard algoritmen vertrouwen en ervan uit gaan dat ze echt veilig zijn. Het is nogal arbeidsintensief om met wachtwoorden, sleutel en verbindingen te jongleren. Als je ergens een foutje maakt en een wachtwoord onbeschermd laat, ligt alles open.

Identity management

De populaire strip "On the internet, nobody know you're a dog" heeft zelfs een eigen Wikipedia-pagina.

Het goede nieuws is dat anonimiteit bevrijdend kan werken en erg nuttig is. Het slechte nieuws is dat wij geen idee hebben hoe wij dat tegenwoordig voor elkaar kunnen krijgen. Sommige programmeurs praten over "two-factor authentication," maar de slimme gaan voor "N-factor authentication."

Naast het wachtwoord en misschien een SMSje hebben wij niet echt iets dat erg stabiel is. Vingerafdruklezers mogen er dan wel indrukwekkend uitzien, maar er zijn genoeg mensen die maar al te graag uitleggen hoe makkelijk deze gehackt kunnen worden. (Zie hier, hier en hier).

Dat maakt niet zoveel uit op websites en diensten als Snapchat en Reddit, maar de stroom van gehackte Facebook-pagina's is wel zorgwekkend. Er is geen simpele oplossing om belangrijke dingen als eigendom, geld, gezondheidszorg of wat dan ook echt goed te beveiligen. De Bitcoin-fanboys houden ervan om te pochen hoe geweldig en ondoordringbaar blockchain is, maar op de een of andere manier worden er nog steeds Bitcoin gestolen. We hebben nog geen echt goede methode om identiteit te managen.

Measuring hardness

Is er een echt goede manier om de complexiteit van een probleem te meten? Niemand schijnt het echt te weten. We weten dat sommige problemen makkelijk op te lossen zijn, maar het is erg lastig om van tevoren te kunnen zeggen hoe moeilijk een probleem echt is. NP-completeness is maar een klein deel van alle pogingen om de complexiteit van algoritmes en data-analyses te "codificeren". De theorie is handig, maar geeft geen garanties. Het is aanlokkelijk te zeggen dat het moeilijk is om van te voren te weten hoe lastig een probleem is. Maar ach, we zullen ermee moeten leren leven.