Objectgericht Autoloading in WordPress, deel 1

Ik heb onlangs een serie ingepakt waarin ik namespaces en autoloading in WordPress heb behandeld. Als u niet bekend bent met een van de bovenstaande voorwaarden, raad ik u aan de serie te bekijken.

De kern van wat u kunt verwachten te leren is als volgt:

In deze serie gaan we precies bekijken welke PHP-naamruimten zijn, waarom ze nuttig zijn en hoe ze te gebruiken. Vervolgens gaan we kijken hoe we autoloaders kunnen gebruiken om de bestanden die we nodig hebben automatisch te laden zonder ze handmatig in onze code te hoeven laden.

Tijdens het werken aan de serie, met name die van de autoloader, kon ik niet anders dan een aantal code geuren herkennen die werden geïntroduceerd toen ik de code met u deelde.

Dit wil niet zeggen dat de autoloader slecht is of dat hij niet werkt. Als je de plug-in hebt gedownload, hebt uitgevoerd of hebt gevolgd en je eigen autoloader hebt geschreven, weet je dat doet in feite werk.

Maar in een reeks die zich richt op naamruimten - iets dat deel uitmaakt van objectgeoriënteerd programmeren - voelde ik me ongemakkelijk bij het verlaten van de autoloader in de eindfase aan het einde van de serie.

Lees mij niet verkeerd: ik sta nog steeds achter de serie, wat was bedekt, en het eindresultaat van wat we produceerden. Maar vanuit een objectgeoriënteerd standpunt is er meer werk dat kan worden gedaan. Dus in deze vervolgserie gaan we het concept van autoloaders opnieuw bekijken vanuit het perspectief van objectgeoriënteerd programmeren.

Concreet gaan we het hebben over het concept van:

  • interfaces
  • interface-implementatie
  • het beginsel van één verantwoordelijkheid
  • en andere principes en ideeën die essentieel zijn voor objectgeoriënteerd programmeren

Ik heb de hoop dat we tegen de tijd dat we deze serie voltooien, onze autoloader niet alleen hebben aangepast aan iets dat beter leesbaar en gemakkelijker te lezen is, maar dat het zich ook houdt aan objectgeoriënteerde praktijken..

Met dat gezegd, laten we aan de slag gaan.

Ermee beginnen

Zoals met bijna elke post die ik schrijf, probeer ik graag twee dingen te doen:

  1. Definieer een routekaart van waar we naartoe gaan.
  2. Geef u alles wat u moet weten om uw machine aan de gang te krijgen.

Voordat we beginnen met het schrijven van een code, laten we dat nu doen. 

Onze routekaart

In de volgende twee berichten gaan we een aantal object-georiënteerde concepten bekijken die ons in staat stellen om de plug-in die we in de vorige serie bouwden te verbeteren.. 

Als u geen kopie van die plug-in hebt, kunt u een kopie ervan downloaden; Ik deel echter volledige codevoorbeelden, opmerkingen en uitleg gedurende elke zelfstudie. 

De serie gaat ervan uit dat je het weet niets over een van de concepten die we zullen bespreken, zodat we van de grond af beginnen. Het enige wat u nodig hebt, is voldoende software op uw computer hebben om een ​​kopie van WordPress aan de gang te krijgen en een editor waarin u code kunt bewerken.

Wat je nodig hebt

Om te beginnen heb je de volgende tools nodig:

  • Een lokale ontwikkelomgeving inclusief tenminste PHP 5.6.20, de Apache-webserver en een MySQL-databaseserver. MAMP 4 is hiervoor perfect.
  • Een map waaruit WordPress 4.6.1 wordt gehost.
  • Een teksteditor of IDE naar keuze die u prettig vindt om een ​​plug-in te schrijven.
  • Een praktische kennis van de WordPress Plugin API.

Nadat je dat allemaal op zijn plaats hebt (en ik weet dat het veel lijkt, maar het duurt niet lang om het in te stellen), moet je een kopie van de hierboven gekoppelde plug-in installeren.

Als we klaar zijn, zijn we klaar om te beginnen praten over interfaces en het principe van de enkele verantwoordelijkheid.

Interfaces Defined

Afhankelijk van je achtergrond in software, wanneer je het woord "interface" hoort, zou je uiteindelijk kunnen denken aan wat de gebruiker daadwerkelijk op het scherm ziet. U weet het: een gebruikersinterface.

Maar als het gaat om objectgericht ontwerpen, daar hebben we het helemaal niet over. In plaats daarvan hebben we het over een klasse-interface. En dit kan meestal worden beschreven als de klasse en de openbare methoden die het blootstelt voor andere klassen om ermee te communiceren.

Is er een meer formele definitie? Zeker. Wikipedia biedt een:

In de informatica is een interface een gedeelde grens waarover twee afzonderlijke componenten van een computersysteem informatie uitwisselen.

Dit is eigenlijk niet zo erg. Het is algemeen genoeg om op bijna elke programmeertaal van toepassing te zijn, en dat is het niet zo technisch dat we het niet kunnen begrijpen.

Aan de andere kant werken we met PHP. Dus wat heeft de PHP-handleiding te bieden over het onderwerp?

Met objectinterfaces kunt u een code maken die aangeeft welke methoden een klasse moet implementeren, zonder dat u hoeft te definiëren hoe deze methoden worden behandeld.

Naar mijn mening is dit een heel goede definitie. Het is makkelijk. Het is taalagnostisch (voor zover ik weet) en het werkt goed in de meeste (zo niet alle) objectgerichte talen. De handleiding gaat zelfs door:

Interfaces worden op dezelfde manier gedefinieerd als een klasse, maar met de interface sleutelwoord ter vervanging van de klasse sleutelwoord en zonder een van de methoden waarvan de inhoud is gedefinieerd.
Alle in een interface gedeclareerde methoden moeten openbaar zijn; dit is de aard van een interface.

Dit zijn twee punten die wij moet onthoud als we onze eigen interfaces gaan implementeren, vooral als het gaat om deze plug-in. Namelijk, we moeten het volgende onthouden:

  1. We definiëren een interface die lijkt op een klasse, maar we gebruiken de interface trefwoord.
  2. De methoden die zijn gedefinieerd in een interface hebben het publiek (in tegenstelling tot het zijn beschermde of privaat) omdat dit de functionaliteit garandeert die andere klassen kunnen gebruiken.

Voordat we verder gaan, hoe ziet een interface in een WordPress-project eruit? Hier is een voorbeeld van een project waaraan ik heb gewerkt:

De bovenstaande code moet duidelijk zijn met welk doel het dient, vooral gezien de opmerking boven de interface.

Zoals we allemaal weten, kan WordPress twee soorten activa registreren en in de wacht slepen: stylesheets en JavaScript-bestanden.

Aangezien beide activa zijn, zou het vanzelfsprekend zijn dat wanneer we klassen maken voor stijlbladbeheer of JavaScript-beheer, we het zouden generaliseren als een activa-interface, juist?

Bovendien weten we dat we het bestand willen initialiseren met behulp van een init-methode, zodat we de opgegeven wachtfunctie aan de juiste WordPress API-functie kunnen koppelen. Als alternatief kan er nog een ander werk zijn dat u zou willen doen, en als dat het geval is, wilt u misschien een andere methodeshandtekening toevoegen aan de interface.

Hoe het ook zij, elke klasse die deze interface implementeert moet bieden functionaliteit voor de volgende methoden. Dus hoe ziet een klasse die deze interface implementeert eruit??

Hier is een heel eenvoudig voorbeeld van een klasse die stylesheets toevoegt aan het beheergebied van WordPress:

Nu hoe dit wordt geïnstantieerd en afgedwongen via PHP valt buiten het bestek van deze tutorial. We zullen het genoeg zien wanneer we onze autoloader beginnen te refactoren. 

Maar het punt dat ik probeer te laten zien is dat een interface de openbare methoden definieert die een klasse moet implementeren. Het definieert de implementatie niet, maar het garandeert dat een bepaalde set functies zal bestaan ​​en publiek toegankelijk is voor externe klassen.

Het beginsel van één verantwoordelijkheid

Een van de uitdagingen van het praten over het principe van de enkele verantwoordelijkheid is dat het vaak verkeerd begrepen wordt als iets als:

Een klasse (of functie of routine) zou één en slechts één ding moeten doen.

Maar dat is een beetje misleid, is het niet? Ik bedoel dat zelfs een simpele for-lus meer dan één ding doet: het initialiseert een waarde, vergelijkt het met waarden, en itereert de waarde wanneer de body van de lus voltooid is.

In plaats daarvan vermeldt het principe het volgende:

Een klasse zou maar één reden moeten hebben om te veranderen.

Omdat zoveel van ons ontwikkelaars Google gebruiken om ons te helpen bij ons dagelijks werk, vind ik het belangrijk om de bron van dit idee te begrijpen. Dat wil zeggen, dit kwam van oom Bob Martin, zoals hij terloops bekend is, of Robert Martin, die een aantal programmeerboeken van de bovenste plank heeft geschreven.

Het idee dat een klasse maar één reden heeft om te veranderen, heeft een hele reeks implicaties met zich mee, nietwaar? Hier volgt een voorbeeld van onze autoloader zoals hij er vandaag uitziet.

Laten we de code herzien (en ik weet dat het geen klasse is, het is een functie, maar het principe is van toepassing):

 0; $ i--) // Lees de huidige component van het bestanddeel. $ current = strtolower ($ file_parts [$ i]); $ current = str_ireplace ('_', '-', $ current); // Als we bij de eerste invoer zijn, staan ​​we bij de bestandsnaam. if (count ($ file_parts) - 1 === $ i) / * Als 'interface' deel uitmaakt van de bestandsnaam, definieer * dan de $ file_name anders, zodat deze correct is geladen. * Anders zet je gewoon de $ file_name gelijk aan die van de class * bestandsnaamstructuur. * / if (strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interface')) // Pak de naam van de interface uit zijn gekwalificeerde naam. $ interface_name = ontploffen ('_', $ file_parts [count ($ file_parts) - 1]); $ interface_name = $ interface_name [0]; $ file_name = "interface- $ interface_name.php";  else $ file_name = "class- $ current.php";  else $ namespace = '/'. $ stroom. $ Namespace;  // Bouw nu een pad naar het bestand met mapping naar de bestandslocatie. $ filepath = trailingslashit (dirname (dirname (__FILE__)). $ namespace); $ filepath. = $ bestandsnaam; // Als het bestand bestaat in het opgegeven pad, neemt u het op. if (file_exists ($ filepath)) include_once ($ filepath);  else wp_die (esc_html ("Het bestand dat probeert te worden geladen op $ filepath bestaat niet."));  

Er bestaat veel van dingen die binnen deze functie gebeuren. Alleen al vanaf een hoog niveau kunnen we zien dat het het volgende doet:

  • Het bepaalt of PHP de code in deze functie probeert aan te roepen.
  • De functie bepaalt of we een interface of een klasse laden.
  • De autoloader probeert vervolgens het bestand op te nemen of het genereert een fout.

Als een klasse verondersteld wordt slechts één reden te hebben om te veranderen, zijn er drie redenen hierboven (en dat is slechts op een hoog niveau) waarop deze enkele functie zou kunnen veranderen. Bovendien zou de code ook duidelijker kunnen zijn.

Ik ben niet iemand die schuivende code-opmerkingen achterhoudt, maar er is veel uitleg in de bovenstaande code. En het is prima als je net begint met het schrijven van een autoloader, maar als je op weg bent naar een meer geavanceerd gebied zoals wij, dan kan dat niet tegen strengere architecturen..

Bringing the Two Together

Dit is waar interfaces en het beginsel van één enkele verantwoordelijkheid hand in hand kunnen komen.

Net zoals een interface een set functionele handtekeningen (of een contract) biedt voor wat zijn implementeerders zullen bieden, kan het ervoor zorgen dat elke klasse die die interface implementeert zich strikt houdt aan wat het definieert.

Maar dit roept een interessante vraag op: moeten we meerdere interfaces hebben? En het antwoord is dat dit afhangt van de aard van de oplossing die u probeert te maken. 

In ons geval denk ik dat het logisch is. 

We willen tenslotte een inkomende klassennaam onderzoeken en bepalen of het een interface of een klasse is, of dat het een fout oplevert. Verder willen we ervoor zorgen dat het juiste bestand wordt meegeleverd met de rest van het systeem.

Maar dat gaat verder dan het onderwerp van deze specifieke tutorial en die zullen we verder moeten onderzoeken als het tijd is om meer code te schrijven.

Conclusie

Op dit punt hebben we de nodige concepten behandeld, zodat we onze autoloader kunnen gaan refactoren. Dat wil zeggen, we zullen een interface introduceren, ervoor zorgen dat onze code eraan vasthoudt, en dan zullen we ervoor zorgen dat onze klasse (of klassen) en hun respectieve methoden zich houden aan het principe van de enkele verantwoordelijkheid.

Bovendien zorgen we ervoor dat het goed blijft functioneren binnen de context van de plug-in, het is goed gedocumenteerd en dat het de WordPress coderingsstandaarden volgt.

Als je in de tussentijd meer wilt lezen over objectgeoriënteerd programmeren in de context van WordPress, kun je al mijn vorige zelfstudies op mijn profielpagina vinden. Volg me gerust op mijn blog of volg mij op Twitter, waar ik het vaak over beide heb.

Zoals altijd, als u op zoek bent naar andere hulpprogramma's om uw groeiende verzameling hulpprogramma's voor WordPress uit te breiden of bijvoorbeeld om code te bestuderen en meer vertrouwd te raken met WordPress, vergeet dan niet te zien wat we beschikbaar hebben in Envato Market.

Met dat gezegd, zal de volgende tutorial in de serie veel praktischer zijn. Dat wil zeggen, we zullen code schrijven, bestaande code herformuleren en alles toepassen wat we hebben geleerd in deze tutorial. Tot die tijd, aarzel dan niet om feedback achter te laten in de commentaren.

Middelen

  • Naamruimte en Autoloader-plug-in
  • namespaces
  • autoloading
  • interfaces
  • De WordPress Plugin-API
  • MAMP 4
  • Single Responsibility Principle