BLOG

Softwarebeheer

PHP 7.4: Onze weg naar de nieuwste versie van PHP

14 april 2020

De nieuwste versie van PHP, versie 7.4, is al enige maanden uit. Misschien bent u met uw applicaties al over naar de nieuwste versie, maar misschien doet u net onderzoek naar de gevolgen van deze migratie. In deze blogpost vertellen wij u meer over onze ervaringen met het geschikt maken van software voor PHP 7.4.

PHP wordt volwassen met versie 7.4

Zoals velen weten is PHP van origine een ‘scripting taal’. Een taal om in hoog tempo simpele websites in elkaar te zetten. Maar door de jaren heen heeft PHP zich steeds meer ontwikkeld tot een serieuze programmeertaal, met juist heel goede ondersteuning voor complexere vraagstukken. Met de nieuwste versie van PHP, PHP 7.4, kan je zeggen dat PHP echt volwassen is geworden.

Er zijn grote stappen gemaakt zoals arrow functions, weak references, limited return type covariance en opcache preloading. Een heel mooi overzicht is te vinden op Stitcher.io.  De toevoeging die voor ons de grootste impact had is ‘typed properties’. Deze nieuwe functionaliteit had voor ons een grote toegevoegde waarde, en we hebben deze dan ook snel ingevoerd.

Updatebeleid binnen Senet

Het is belangrijk om bij te blijven. Senet wil voorlopen op technisch gebied en bij blijven met nieuwe PHP-versies is daar een onderdeel van. Om ook de stabiliteit van de software te kunnen garanderen gaan wij niet direct bij het uitkomen van een nieuwe versie over, maar wachten we 1 of 2 patch releases af. Natuurlijk is er dan ook een uitgebreide testronde, net zoals bij elke andere release.

We maken gezamenlijk als development team een upgrade-plan, waarin we kijken welke stappen er genomen moeten worden om de software voor te bereiden op de nieuwe PHP versie. Ook bekijken we de consequenties van depreciations, en gebruiken tooling waar mogelijk om te vinden welke onderdelen van de software worden geraakt. Er worden tevens gezamenlijk afspraken gemaakt over nieuwe functionaliteiten in de taal. Gaan we deze gebruiken? En zo ja, wanneer en waar? En is het de moeite waard om legacy code om te schrijven?

Het is van belang om een migratie naar een nieuwe PHP-versie als team te doen, met commitment van iedereen.

Typed Properties

Typed Properties is een verdere doorontwikkeling van nieuwe functionaliteiten binnen PHP om ‘typed programming’ mogelijk te maken. Talen zijn vaak danwel loosely typed (variabelen kunnen ‘onderweg’ van type veranderen, en wanneer een variabele een onverwacht type heeft zal deze d.m.v. ‘type juggling’ worden aangepast) of strict typed (variabelen hebben een vooraf gedefinieerd type en kunnen niet veranderen).

Strict typed binnen PHP

Beide varianten hebben hun voor- en nadelen, maar het valt niet te ontkennen dat er de afgelopen jaren een groeiende behoefte was naar meer strict types. Op die manier kon software beter worden getest, makkelijker worden uitgebreid en kon er een hogere stabiliteit worden behaald. Vooral bij organisaties- die complexere software ontwikkelen, zoals bij ons, maakten hulpmiddelen zoals type docblocks en de  beberlei/assert bibliotheek hun intrede. Beide tools worden gebruikt om in een loosely typed wereld toch wat structuur en duidelijkheid aan te brengen.

Het PHP core ontwikkelteam heeft duidelijk geluisterd naar deze behoefte bij PHP-programmeurs, en de afgelopen versies zijn er steeds meer functionaliteiten gekomen die strict typed functionaliteiten naar PHP halen. 

Nieuwe toevoeging

De nieuwste aanwinst op dit gebied is typed properties. Het is nu ook mogelijk om een class property een verplichte type te geven. Bij een poging om een waarde van een ander type te zetten wordt bij de strict type een fatal error geworpen. Dit klinkt raar, maar dit komt uiteindelijk de stabiliteit ten goede. Waar een foute waarde bij een loosely typed misschien niet opvalt tijdens het testen kan deze uiteindelijk onverwacht en foutief gedrag vertonen in de uiteindelijke applicatie. Dit kan natuurlijk heel gevaarlijk zijn. Een foutieve waarde bij een strict typed property geeft direct een fatal error. Dit valt direct op tijdens het testen, en kan ook verder geen foutief gedrag meer veroorzaken.

Bij Senet was de keuze snel gemaakt. Door ons intensieve gebruik van de type docblocks die we eerder hebben genoemd was de verwachte type van de properties gemakkelijk te achterhalen. Door de complexiteit van onze applicaties zagen we veel toegevoegde waarde.

Tools

Maar hoe ga je dan aan de slag? Wij hebben eerst gekeken naar hoe tools ons konden helpen.

Rector is een refactoring-tool voor PHP applicaties die automatisch enkele transities kan uitvoeren. Ook het omzetten van typed properties is tegenwoordig mogelijk (zie ook: Github). Hoewel in een testronde Rector redelijk accuraat bleek, hebben we er toch voor gekozen om dit niet toe te passen. Bij het aanpassen van de strict types was uitgebreid testen toch echt nodig, en daar kan Rector ook niet bij helpen.

We hebben wel PHPMD toegepast. Deze toolkit gebruiken we al enkele jaren zeer intensief om de kwaliteit van onze software te monitoren. Een check op typed properties is tegenwoordig ook beschikbaar (zie ook: Github) en met een nightly build met deze additionele check controleren we de verspreiding van typed properties over onze codebase. Langzaam maar zeker neemt het aantal classes zonder typed properties af.

Doctrine entities en nullable typed properties

Een uitdaging rondom typed properties zijn de entities in Doctrine. Je zou verwachten dat properties in een class die zijn gemapped naar een non-nullable veld in de database, ook nullable zijn in de entity. Maar deze gedachtegang is alleen juist als deze non-nullable velden een standaardwaarde hebben, of wanneer ze zijn opgenomen als een verplicht veld in de constructor.

Bij legacy code waar properties die non-nullable zijn in de database met een setter worden gezet, is de property in de class dus wél nullable.

 

Opcache Preloading

PHP 7.4 brengt weer een mooie snelheidsverbetering ten opzichte van de voorganger. Opcache preloading brengt nog een grotere verbetering, maar vraagt wel enige veranderingen aan de infrastructuur. Het is namelijk mogelijk om belangrijke onderdelen van de applicatie, bijvoorbeeld de basis van het framework, vooraf te compileren en te laden. Hierdoor kan een mooie performance-winst worden geboekt.

Een consequentie van het preloaden van onderdelen van de applicatie is dat deze onderdelen daarna niet meer getranspileert worden. Bij een wijziging aan de software zal de opcache moeten worden geleegd en in ons geval php-fpm worden herstart. Omdat dit een grote invloed heeft op de beschikbaarheid van onze applicatie hebben we besloten om te wachten met de implementatie van preloading tot het invoeren van kubernetes, waarbij deze restart zonder downtime kan worden uitgevoerd.

Omgaan met legacy

Bij de opmerkingen over omgaan met Doctrine entities en typed properties komen we op een belangrijk punt. Hoe ga je om met legacy binnen je applicatie?

Alle code die geschreven wordt, wordt uiteindelijk legacy. Standaarden veranderen, mogelijkheden van talen veranderen en ook de business verandert. Maar code die niet meer modern is hoeft zeker niet slecht te zijn. Legacy code is voortdurend getest in productie, is stabiel en waarschijnlijk ook geoptimaliseerd. Alle kennis die erin is gestoken weggooien, simpelweg om te “moderniseren” is niet anders dan onverstandig. Er zijn betere manieren om om te gaan met legacy code.

Maar hoe gaan we dan wel om met legacy code? Dit verschilt per geval. Het is belangrijk om als development team te bespreken welke depreciations en features van toepassing zijn bij een PHP-versie. Welke hiervan moeten we verwerken in onze legacy, en wat is alleen voor nieuwe code van toepassing? En als we onze legacy code gaan aanpassen, moet dat dan in een big bang, of kunnen we dat meenemen in onderhoud van de komende maanden? Dit is een afweging tussen de toegevoegde waarde van de deprecations en features in de PHP-versie enerzijds, en de stabiliteit van de applicatie anderzijds.

Als Senet hebben we besloten langzaam maar zeker over te willen gaan naar 100% strict typed. We nemen langzaam stappen om de gehele codebase over te krijgen, door code die we aanraken te moderniseren, en soms als ‘opvulling’ van de sprint modules te moderniseren zonder verdere functionele wijzigingen door te voeren.

PHP 8.0, wij zijn er klaar voor

Er komt inmiddels een nieuwe major versie van PHP aan, PHP 8.0. Als we de roadmap moeten geloven zal deze voor het einde van 2020 worden uitgebracht.

Er zijn weer een paar mooie uitbreidingen die strict typed programmeren van PHP makkelijker maken. Denk aan union types, die wij alleen in noodzakelijke randgevallen gaan toepassen, static return types en de Stringable interface. 

Ook is er een groot aantal depreciations en dat kan effect hebben op bestaande applicaties. Wij analyseren alvast onze applicaties om in te schatten hoeveel tijd wij hierin zullen moeten investeren. Gelukkig lijkt het in ons geval mee te vallen, maar het is belangrijk om uw applicatie voor te bereiden op deze grote verandering.

Heeft u vragen over het migreren van uw applicaties naar de nieuwste PHP versie of wilt u de geschiktheid van uw applicaties voor PHP 8.0 alvast laten analyseren? Een vrijblijvende afspraak is altijd mogelijk, onze software specialisten staan voor u klaar.

Interesse in een gesprek?

neem contact op met Geurt Jan van Ek

Neem contact op

Zie onze privacyverklaring.