Kris van Rens (Trainer)
Ondanks een groot aantal opkomende alternatieven is C++ nog steeds een kracht om rekening mee te houden, zeker in de door legacy geplaagde high-tech industrie. In een serie artikelen plaatst High Tech Institute trainer Kris van Rens de taal in een modern perspectief. In onze nieuwe 4-daagse training laat Kris van Rens deelnemers kennismaken met de basisprincipes van de taal en essentiële best practices.
Om de paar jaar worden C en C++ doodverklaard. Onlangs verklaarde Microsoft Azure CTO Mark Russinovich publiekelijk dat ze afgeschreven zouden moeten worden ten gunste van Rust. Hoewel dit op persoonlijke titel is geuit, is het een interessant standpunt voor iemand van Microsoft, dat een enorme C++ codebase heeft en veel actieve leden in de C++ commissie.
Hoe dan ook, C en C++ zijn nog steeds springlevend – elk de lingua franca van veel industriële softwareontwikkelomgevingen. Toch is Rust tegenwoordig blijkbaar de ‘place to be’ in systeemprogrammeerland. Wat maakt deze taal zo aantrekkelijk? Laten we het eens bekijken vanuit het perspectief van C++.
Opmerkelijke verschillen
Ten eerste biedt Rust een duidelijk en objectief voordeel ten opzichte van C++: gegarandeerde geheugenveiligheid voor het gecompileerde resultaat. In wezen ruilt Rust compilatietijd (en compilercomplexiteit) voor een veiligere runtime. De compiler zal zichzelf proberen te bewijzen dat de code die je hem geeft geheugenveilig is, door gebruik te maken van zijn typesysteem en soms de hulp van de ontwikkelaar om dingen aan te geven zoals afhankelijkheden van variabele of referentielevensduur.
Er zijn meerdere onafhankelijke beveiligingsonderzoeken uitgevoerd op grote C en C++ codebases waaruit is gebleken dat maar liefst 70 procent van alle bugs en beveiligingsproblemen te maken heeft met geheugenveiligheid. In het licht hiervan lijkt het inruilen van compileertijd voor een geheugenveilige runtime een no-brainer. Het schrijven van C++ van hoge kwaliteit met behulp van de juiste tools, tests, best practices en compiler sanitizers kan u daar ook brengen, maar het biedt geen harde garanties vanaf het begin. De ‘vangrails’ die Rust implementeert om u te beschermen tegen jezelf in de voet schieten kunnen soms complex of zelfs irritant zijn, maar denk eens aan de aanzienlijke voordelen die een runtime geheugenveiligheidsgarantie met zich meebrengt voor het programmeren van gelijktijdige software.
''As software engineers, we should use the right tool for the job.''
Een ander opmerkelijk verschil met C++ is de manier waarop Rust de afhandeling van fouten en functieresultaatwaarden integreert. In tegenstelling tot C++ heeft het geen uitzonderingen; het biedt mechanismen om met fouten om te gaan met behulp van reguliere controlestroom. Resultaatwaarden moeten worden verwerkt, wat de ontwikkelaar dwingt om foutafhandeling te implementeren en onjuiste code te voorkomen, dus fouten of uitzonderingen vliegen zelden onder de radar. Als het tijdens runtime echt misgaat – bijvoorbeeld als het geheugen uitgeput raakt – zal Rust een zogenaamde panic genereren, een fatale fout, waardoor de thread in kwestie stopt (wat netjes afgehandeld kan worden).
De Rust compiler, gebouwd bovenop de LLVM compiler back-end, is duidelijk erg pedant, om geheugenveiligheid en correctheid van code te handhaven, maar tegelijkertijd erg behulpzaam. Beschouw het als een koppel programmeurs, die over je schouder meekijkt en leesbare foutmeldingen geeft, en zelfs mogelijke oplossingen voorstelt. Afgezien van de compiler, draait het grootste deel van het ecosysteem van Rust rond Cargo, dat een buildsysteem, een pakket- en afhankelijkheidsmanager en nog veel meer is, alles in één. Ondanks de overvloed aan pakketbeheerders, bouwsystemen en andere tools die beschikbaar zijn voor C++, kan het opzetten van een serieus C++ project nog steeds een lastige klus zijn.
Omdat Rust relatief jong is, heeft het de luxe gehad om meer dan 40 jaar taalontwikkeling te verwerken in zijn syntaxis en structuur. Veel van de inspiratie is gehaald uit zowel imperatieve talen als C++ en functionele talen als Haskell en Scheme. Dit geeft het het subjectieve voordeel van een zeer ‘modern’ gevoel. Bovendien zijn veel dingen in Rust expressies, wat zorgt voor meer flexibiliteit in de codenotatie.
In mijn vorige bijdrage heb ik betoogd dat de gebruikersbasis van een programmeertaal van het grootste belang is. Rust, met hulp van de Rust Foundation, bouwt geleidelijk aan deze gebruikersbasis, zoals kan worden afgeleid uit vele indicatoren, zoals de Tiobe-index en het Stack Overflow-onderzoek, en door de adoptie van Rust in de Linux v6.1 kernel – geen geringe prestatie. Naarmate meer en meer beveiligingsrapporten melding maken van netto positieve effecten die sterk gerelateerd zijn aan het gebruik van geheugenveilige talen zoals Rust, zal de gebruikersbasis blijven groeien. Elke aanwijzing (geen woordspeling bedoeld) lijkt te wijzen op een mooie toekomst voor Rust.
Niet alles rozengeur en maneschijn
Moeten we dan gewoon C en C++ afschrijven ten gunste van Rust? Naar mijn mening is dit een valse dichotomie. Waarom zouden we moeten kiezen tussen het een of het ander? Als software-ingenieurs moeten we het juiste gereedschap voor de klus gebruiken.
Migreren naar Rust is ook niet allemaal rozengeur en maneschijn. Als je een grote hoeveelheid bestaande C++ code hebt, zal Rust niet direct helpen, tenzij je bereid bent om C API’s te gebruiken voor interactie. Er zijn tools voor C++-niveau interoperabiliteit, maar deze staan nog in de kinderschoenen. U kunt natuurlijk ook uw code herschrijven, maar dat zal niet eenvoudig zijn, vooral niet als u zwaar leunt op geavanceerde sjablonen. En als je vertrouwt op absolute maximale prestatie-eisen, is safe Rust daar misschien (nog?) niet op berekend. Bovendien, in strengere omgevingen zoals de auto- of luchtvaartindustrie, schrijven standaarden vaak het gebruik van een formeel gespecificeerde programmeertaal voor, wat Rust op dit moment niet is.
Het beste advies is om je niet vast te pinnen op één programmeertaal. Het leren van meerdere talen is over het algemeen echt nuttig en zal uw competentie, stijl en kennis verbeteren in elke taal die u beheerst. Kijk dus eens naar C++, Rust en andere alternatieven om je perspectief te verbreden – of gewoon voor de lol.