Autoloading orientato agli oggetti in WordPress, parte 1

Recentemente ho concluso una serie in cui riguardavo spazi dei nomi e autoloading in WordPress. Se non hai familiarità con uno dei due termini sopra indicati, ti consiglio di controllare la serie.

Il succo di ciò che puoi aspettarti di imparare è il seguente:

In questa serie, daremo un'occhiata esattamente a quali sono gli spazi dei nomi PHP, perché sono utili e come usarli. Quindi daremo un'occhiata a come utilizzare i caricatori automatici per caricare automaticamente i file di cui abbiamo bisogno senza doverli caricare manualmente nel nostro codice.

Mentre lavoravo alla serie, in particolare quella del caricatore automatico, non ho potuto fare a meno di riconoscere un certo numero di odori di codice che venivano introdotti mentre stavo condividendo il codice con te.

Questo non vuol dire che il caricatore automatico sia danneggiato o che non funzioni. Se hai scaricato il plug-in, eseguito, seguito e scritto il tuo autoloader, allora lo sai fa in effetti lavoro.

Ma in una serie che si concentra sui namespace - qualcosa che è parte integrante della programmazione orientata agli oggetti - non ho potuto fare a meno di sentirmi a disagio lasciando il caricatore automatico nel suo stato finale alla fine della serie.

Non fraintendetemi: continuo a sopportare la serie, ciò che è stato coperto e il risultato finale di ciò che abbiamo prodotto. Ma da un punto di vista orientato agli oggetti, c'è più lavoro che può essere fatto. Quindi, in questa serie di follow-up, stiamo andando a rivisitare il concetto di autoloader dal punto di vista della programmazione orientata agli oggetti.

Nello specifico, parleremo del concetto di:

  • interfacce
  • implementazione dell'interfaccia
  • il principio della responsabilità unica
  • e altri principi e idee che sono alla base della programmazione orientata agli oggetti

Spero che nel momento in cui completeremo questa serie, non avremo solo rifattorizzato il nostro autoloader in qualcosa che è più manutenibile e più facile da leggere, ma che aderisce anche a pratiche più orientate agli oggetti.

Detto ciò, iniziamo.

Iniziare

Come per quasi tutti i post che scrivo, mi piace provare a fare due cose:

  1. Definire una tabella di marcia di dove stiamo andando.
  2. Darti tutto ciò che devi sapere per far funzionare la tua macchina.

Prima di saltare a scrivere qualsiasi codice, facciamolo ora. 

La nostra tabella di marcia

Nei prossimi due post daremo un'occhiata ad alcuni concetti orientati agli oggetti che ci permetteranno di migliorare il plugin che abbiamo creato nella serie precedente. 

Se non hai una copia di quel plugin, puoi scaricarne una copia; tuttavia, condividerò esempi completi di codice, commenti e spiegazioni in ogni esercitazione. 

La serie darà per scontato che tu sappia Niente su uno qualsiasi dei concetti che discuteremo quindi partiremo da zero. Tutto ciò di cui hai bisogno è avere abbastanza software sul tuo computer per avere una copia di WordPress attiva e funzionante, e un editor in cui puoi modificare il codice.

Quello di cui hai bisogno

Per iniziare, avrai bisogno dei seguenti strumenti:

  • Un ambiente di sviluppo locale che include almeno PHP 5.6.20, il server Web Apache e un server di database MySQL. MAMP 4 è perfetto per questo.
  • Una directory da cui è stato ospitato WordPress 4.6.1.
  • Un editor di testo o IDE di tua scelta che ti piace usare per scrivere un plugin.
  • Una conoscenza pratica dell'API Plugin WordPress.

Dopo aver messo tutto a posto (e so che sembra molto, ma in realtà non ci vuole molto tempo per configurare), dovrai installare una copia del plugin collegato sopra.

Una volta terminato, siamo pronti per iniziare a parlare delle interfacce e del principio di responsabilità singola.

Interfacce Definite

A seconda del tuo background nel software, quando senti la parola "interfaccia", potresti finire per pensare a ciò che l'utente effettivamente vede sullo schermo. Sai: un'interfaccia utente.

Ma quando si tratta di design orientato agli oggetti, non è quello di cui stiamo parlando. Invece, stiamo parlando di un'interfaccia di classe. E questo di solito può essere descritto come la classe e i metodi pubblici che espone per altre classi per comunicare con esso.

Esiste una definizione più formale? Sicuro. Wikipedia offre uno:

Nel calcolo, un'interfaccia è un confine condiviso attraverso il quale due componenti separati di un sistema informatico scambiano informazioni.

Questo non è poi così male, in realtà. È abbastanza generale da applicare a quasi tutti i linguaggi di programmazione e non lo è così tecnico che non possiamo capirlo.

Poi di nuovo, stiamo lavorando con PHP. Quindi cosa ha da offrire il manuale PHP sull'argomento?

Le interfacce degli oggetti consentono di creare codice che specifica i metodi che una classe deve implementare, senza dover definire come vengono gestiti questi metodi.

Secondo me, questa è una definizione davvero buona. È semplice. È indipendente dal linguaggio (per quanto ne so) e funziona bene per la maggior parte (se non tutti) i linguaggi orientati agli oggetti. Il manuale continua anche a dire:

Le interfacce sono definite allo stesso modo di una classe, ma con il interfaccia parola chiave che sostituisce il classe parola chiave e senza nessuno dei metodi con i loro contenuti definiti.
Tutti i metodi dichiarati in un'interfaccia devono essere pubblici; questa è la natura di un'interfaccia.

Questi sono due punti che noi dovere ricorda se stiamo implementando le nostre interfacce, specialmente quando si tratta di questo plugin. Vale a dire, dobbiamo ricordare quanto segue:

  1. Definiamo un'interfaccia molto come facciamo una classe, ma usiamo il interfaccia parola chiave.
  2. I metodi che sono definiti in un'interfaccia hanno al pubblico (al contrario di essere protetta o privato) perché questo è ciò che garantisce la funzionalità accessibile alle altre classi.

Prima di andare oltre, come potrebbe apparire un'interfaccia in un progetto WordPress? Ecco un esempio di un progetto a cui sto lavorando:

Il codice sopra dovrebbe essere chiaro a quale scopo serve, soprattutto dato il commento che si trova sopra l'interfaccia.

Come tutti sappiamo, WordPress può registrare e accodare due tipi di risorse: fogli di stile e file JavaScript.

Dal momento che entrambi sono risorse, sarebbe ragionevole pensare che quando creiamo classi per la gestione di fogli di stile o la gestione di JavaScript, generalizziamo come un'interfaccia di risorse, a destra?

Inoltre, sappiamo che vogliamo inizializzare il file usando un metodo init in modo da poter agganciare la funzione di accodamento specificata all'appropriata funzione dell'API di WordPress. In alternativa, potrebbe esserci qualche altro lavoro che vorresti fare, e se questo è il caso, allora potresti voler aggiungere un'altra firma di metodo all'interfaccia.

In ogni caso, qualsiasi classe che implementa questa interfaccia dovere fornire funzionalità per i seguenti metodi. Quindi, come sarebbe una classe che implementa questa interfaccia?

Ecco un esempio molto semplice di una classe che aggiunge fogli di stile all'area di amministrazione di WordPress:

Adesso Come questo è istanziato e applicato tramite PHP oltre lo scopo di questo tutorial. Lo vedremo in abbondanza quando inizieremo a refactoring il nostro autoloader. 

Ma il punto che sto cercando di mostrare è che un'interfaccia definisce i metodi pubblici che una classe deve implementare. Non definisce l'implementazione, ma garantisce che un certo insieme di funzioni esisterà e sarà pubblicamente accessibile alle classi di terze parti.

Il principio della singola responsabilità

Una delle sfide nel parlare del principio di responsabilità singola è che spesso è stato frainteso a significare qualcosa come:

Una classe (o una funzione o una routine) dovrebbe fare una sola cosa.

Ma questo è un po 'fuorviato, non è vero? Voglio dire, anche un semplice ciclo for fa più di una cosa: inizializza un valore, lo confronta con i valori, e quindi itera il valore quando il corpo del ciclo è completo.

Invece, il principio afferma quanto segue:

Una classe dovrebbe avere solo una ragione per cambiare.

Poiché molti di noi sviluppatori fanno leva su Google per aiutarci nel nostro lavoro quotidiano, penso che sia importante capire la fonte di questa idea. Cioè, questo è venuto da Uncle Bob Martin, come è casualmente noto, o Robert Martin, che ha scritto un certo numero di libri di programmazione di primo livello.

L'idea che una classe abbia una sola ragione per cambiare porta con sé tutta una serie di implicazioni, non è così? Ecco un esempio che viene in mente dal nostro autoloader così com'è oggi.

Rivediamo il codice (e so che non è una classe, è una funzione, ma il principio è applicabile):

 0; $ i--) // Legge il componente corrente della parte del file. $ current = strtolower ($ file_parts [$ i]); $ corrente = str_ireplace ('_', '-', $ corrente); // Se siamo alla prima voce, allora siamo al nome del file. if (count ($ file_parts) - 1 === $ i) / * Se 'interface' è contenuta nelle parti del nome del file, quindi * definire il $ file_name in modo diverso in modo che sia caricato correttamente. * Altrimenti, basta impostare $ nome_file uguale a quello della struttura del nome * della classe. * / if (strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interface')) // Prendi il nome dell'interfaccia dal suo nome qualificato. $ interface_name = explode ('_', $ file_parts [count ($ file_parts) - 1]); $ interface_name = $ interface_name [0]; $ file_name = "interfaccia- $ interface_name.php";  else $ file_name = "class- $ current.php";  else $ namespace = '/'. $ corrente. $ Namespace;  // Ora crea un percorso per il file usando l'associazione al percorso del file. $ filepath = trailingslashit (dirname (dirname (__FILE__)). $ namespace); $ filepath. = $ nome_file; // Se il file esiste nel percorso specificato, quindi includerlo. if (file_exists ($ filepath)) include_once ($ filepath);  else wp_die (esc_html ("Il file che tenta di essere caricato in $ filepath non esiste."));  

C'è Un sacco di cose che accadono all'interno di questa funzione. Guardandolo da un livello elevato, possiamo vedere che sta facendo quanto segue:

  • Determina se PHP sta cercando di invocare il codice in questa funzione.
  • La funzione determina se stiamo caricando un'interfaccia o una classe.
  • Il caricatore automatico tenta quindi di includere il file o genera un errore.

Se una classe dovrebbe avere solo una ragione per cambiare, ci sono tre ragioni sopra (e questo è solo ad un livello alto) in cui questa singola funzione potrebbe cambiare. Inoltre, il codice potrebbe essere più chiaro, pure.

Non sono uno che evita i commenti al codice, ma ci sono molte spiegazioni nel codice qui sopra. Ed è bello quando inizi a scrivere un autoloader, ma quando ti stai dirigendo verso un territorio più avanzato come quello che siamo, allora non sarà più difficile mantenere le architetture più rigorose.

Portare i due insieme

È qui che le interfacce e il principio della responsabilità unica possono arrivare a funzionare a braccetto.

Proprio come un'interfaccia fornisce un insieme di firme di funzioni (o di un contratto) per ciò che i suoi implementatori forniranno, può garantire che qualsiasi classe che implementa tale interfaccia aderisca strettamente a ciò che definisce.

Ma questo solleva una domanda interessante: dovremmo avere più interfacce? E la risposta è che dipende dalla natura della soluzione che stai cercando di creare. 

Nel nostro caso, penso che abbia senso. 

Dopotutto, stiamo cercando di esaminare un nome di classe in arrivo e determinare se si tratta di un'interfaccia o di una classe, o se merita di generare un errore. Inoltre, stiamo cercando di garantire che il file corretto sia incluso nel resto del sistema.

Ma questo è oltre l'argomento di questo particolare tutorial e dovremo esplorare in modo più approfondito quando arriva il momento di scrivere più codice.

Conclusione

A questo punto, abbiamo coperto i concetti necessari in modo che possiamo iniziare a refactoring il nostro autoloader. Cioè, introdurremo un'interfaccia, assicurandoci che il nostro codice aderisca ad essa, e quindi faremo in modo che la nostra classe (o le nostre classi) ei loro rispettivi metodi rispettino il principio di responsabilità singola.

Inoltre, ci assicureremo che continui a funzionare bene nel contesto del plugin, sia adeguatamente documentato e che segua gli standard di codifica di WordPress.

Nel frattempo, se sei interessato a leggere di più sulla programmazione orientata agli oggetti nel contesto di WordPress, puoi trovare tutti i miei tutorial precedenti sulla mia pagina del profilo. Sentiti libero di seguirmi sul mio blog o seguimi su Twitter, dove spesso parlo di entrambi.

Come sempre, se stai cercando altre utilità che ti aiutino a costruire il tuo set crescente di strumenti per WordPress o codice di esempio per studiare e diventare più esperto in WordPress, non dimenticare di vedere cosa abbiamo a disposizione nel mercato Envato.

Detto questo, il prossimo tutorial della serie sarà molto più pratico. Cioè, scriveremo codice, rifattorizzeremo il codice esistente e applicheremo tutto ciò che abbiamo imparato in questo tutorial. Fino ad allora, non esitare a lasciare un feedback nei commenti.

risorse

  • Spazio dei nomi e plugin per autoloader
  • Namespace
  • Caricamento automatico
  • interfacce
  • L'API del plugin WordPress
  • MAMP 4
  • Principio della singola responsabilità