Nel precedente tutorial, abbiamo trattato una serie di concetti, che saranno necessari per comprendere appieno ciò che stiamo facendo in questo tutorial.
Nello specifico, abbiamo trattato i seguenti argomenti:
In alcune serie, è facile saltare le esercitazioni che non si possono costruire l'una sull'altra; tuttavia, questa serie non è destinata ad essere così. Invece, è pensato per essere letto in ordine sequenziale, ed è pensato per costruire sul contenuto di ogni tutorial precedente.
Detto questo, presumo che tu sia coinvolto.
Anche se potrei averlo menzionato nel primo tutorial, mi piace ancora assicurarmi che siamo tutti sulla stessa pagina per quanto riguarda ciò che stiamo facendo in ogni tutorial e con quale software avremo bisogno.
Quindi in questo tutorial, il piano è il seguente:
In definitiva, non scriveremo tanto codice in questo tutorial, ma ne scriveremo alcuni. È, tuttavia, un tutorial pratico in quanto stiamo eseguendo analisi e progettazione orientata agli oggetti. Questa è una fase necessaria per molti progetti su larga scala (e qualcosa che dovrebbe accadere per progetti su piccola scala).
Se hai seguito, dovresti averlo già impostato. Ma per essere sicuri, ecco la versione breve di tutto ciò di cui hai bisogno:
Con tutto ciò che è in atto, siamo pronti a lavorare sul codice condiviso nel tutorial precedente. Quindi iniziamo.
La prima cosa che vogliamo fare è analizzare lo stato attuale del nostro autoloader. Potrebbe sembrare un sacco di codice da incollare in un singolo blocco di codice, ma questo di per sé ci mostra che abbiamo del lavoro da fare.
Detto questo, ecco lo stato attuale del nostro autoloader:
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."));
A questo punto, ricorda che il principio di responsabilità unica afferma quanto segue:
Una classe dovrebbe avere solo una ragione per cambiare.
Al momento, non abbiamo nemmeno una classe, per non parlare di più metodi individuali che hanno un solo motivo per cambiare.
E anche se potrebbe aver senso interrompere questo metodo di caricamento automatico in metodi individuali più piccoli, partiamo da un livello più alto e iniziamo a pensare a un caricatore automatico in termini di un'interfaccia. Quindi approfondiremo la creazione di una classe (o classi).
Ricorda dal tutorial precedente che un'interfaccia è definita dal manuale PHP come segue:
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.
Dato il codice e le definizioni di cui sopra, pensiamo a ciò che un autoloader deve fare da una prospettiva più modulare. Nello specifico, suddividiamolo in punti che rappresentano ciò che potrebbe essere sufficiente per cambiare. No, non possiamo usare tutti questi punti, ma è per questo che si chiama analisi. Lavoreremo sul design più tardi.
Il codice esegue quanto segue:
$ class_name
è un nome di variabile povero).Quindi, il codice sopra fa nove cose-cioè, ha almeno nove motivi per cambiare, prima che sia terminato il suo lavoro.
Questo dovrebbe essere ovvio, ma questa particolare funzione è un esempio perfetto che possiamo refactoring per dimostrare l'analisi orientata agli oggetti, la progettazione, le interfacce e l'implementazione.
E questo solleva una domanda: dove iniziamo??
A questo punto, è giusto dire che possiamo iniziare a fare analisi orientate agli oggetti, cioè guardando a quali classi potenziali possiamo avere e come interagiscono, dato tutto ciò che abbiamo elencato sopra. Ricorda, vogliamo anche che il principio della responsabilità unica ci aiuti a guidarci nel nostro processo decisionale.
A questo punto, non siamo terribilmente preoccupati di come le classi comunicheranno tra loro. Invece, siamo più concentrati sulla creazione di classi che hanno una sola ragione per cambiare.
Detto ciò, fornirò una serie di classi che penso possano funzionare. Prima di andare oltre, guarda cosa abbiamo fatto e prova a creare la tua lista personale. Quindi possiamo confrontare le note.
Tieni presente che potresti avere un'idea migliore rispetto a quanto elencato di seguito, oppure puoi prendere qualcosa di diverso da ciò che abbiamo condiviso. Indipendentemente da ciò, questo è un esercizio di apprendimento. Stiamo tentando di migliorare il nostro codice, la nostra organizzazione e, in definitiva, diventare dei programmatori migliori.
Dato quello che ho elencato sopra, ho creato le seguenti classi:
E questo è tutto. Ora le classi di terze parti nel nostro plugin devono solo conoscere la classe del caricatore automatico, ma il caricatore automatico avrà bisogno della conoscenza di un'altra classe, e altre classi avranno bisogno della conoscenza di altre classi ancora.
Là siamo modi per gestirlo (usando i contenitori per le dipendenze, ma questo va oltre lo scopo di questo progetto). Ma quello che cercheremo di fare attraverso il nostro codice è minimizzare il numero di classi che conoscono l'un l'altro.
A questo punto, diversi sviluppatori, aziende, agenzie e team avranno un approccio diverso a come progettano il sistema su cui stanno lavorando.
Uno dei modi più comuni per fare ciò è usare qualcosa chiamato un diagramma UML. Anche se è utile, non è qualcosa che vale la pena fare nell'ambito di questo tutorial perché richiederà un intero tutorial per spiegare tutti i pezzi.
Quindi, ai fini del nostro tutorial, e dal momento che stiamo lavorando con una quantità così piccola di codice, cercheremo di eliminare il modo in cui ognuna delle classi precedenti potrebbe funzionare prima di implementarle. In questo modo, avremo un'idea di come possiamo organizzare il nostro codice.
Nota che non ci sarà ancora il namespace di questo codice, e nessuno di questo codice dovrebbe essere implementato o testato ancora su WordPress. Ne parleremo nel prossimo tutorial.
Iniziamo con Autoloader
e lavora da lì.
Ricorda, questa classe è responsabile per includere il file necessario. Questo è il file che verrà registrato con spl_autoload_register
funzione.
namespace_validator = new NamespaceValidator (); $ this-> file_registry = new FileRegistry (); load di funzione pubblica ($ filename) if ($ this-> namespace_validator-> is_valid ($ filename)) $ this-> file_registry-> load ($ filename);
Si noti che questa classe dipende da NamespaceValidator
e il FileRegistry
classe. Vedremo ognuno di questi in modo più dettagliato in un solo momento.
Questo file controllerà il nome file in ingresso e determinerà se è valido. Questo viene fatto guardando lo spazio dei nomi nel nome del file.
Se il file fa in effetti appartengono al nostro spazio dei nomi, quindi possiamo supporre che sia sicuro caricare il nostro file.
FileInvestigator
Questa classe sta facendo un bel po 'di lavoro, anche se parte di essa viene eseguita tramite metodi di supporto molto semplici e molto piccoli. Durante il corso dell'esecuzione, esamina il tipo di file che è passato.
Quindi recupera il nome file completo per il tipo di file.
get_file_name ($ file_parts, $ current, $ i); if (count ($ file_parts) - 1! == $ i) $ filepath = trailingslashit ($ filepath); restituisce $ filepath; funzione privata get_file_name ($ file_parts, $ current, $ i) $ filename = "; if (count ($ file_parts) - 1 === $ i) if ($ this-> is_interface ($ file_parts)) $ filename = $ this-> get_interface_name ($ file_parts); else $ filename = $ this-> get_class_name ($ current); else $ filename = $ this-> get_namespace_name ($ current); return $ filename; private function is_interface ($ file_parts) return strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interface'); private function get_interface_name ($ file_parts) $ interface_name = explode ('_', $ file_parts [count ($ file_parts) - 1]); $ interface_name = $ interface_name [0]; return "interface- $ interface_name.php"; private function get_class_name ($ current) return "class- $ current.php" ; private function get_namespace_name ($ current) return '/'. $ current;Se c'è un file che può essere refactored un po 'di più, allora è questo. Dopo tutto, tenta di determinare se stiamo lavorando con una classe, un'interfaccia o una classe. Una fabbrica semplice potrebbe essere più adatta a questo.
Quando arriva il momento di implementare il nostro codice, forse lo rifatteremo ulteriormente. Fino ad allora, questo è un progetto preliminare che potrebbe funzionare abbastanza bene.
FileRegistry
Questo utilizzerà il percorso file completo e includerà il file; in caso contrario, utilizzerà l'API di WordPress per visualizzare un messaggio di errore.
class FileRegistry private $ investigator; funzione pubblica __construct () $ this-> investigator = new FileInvestigator (); load di funzione pubblica ($ filepath) $ filepath = $ this-> investigator-> get_filetype ($ filepath); $ filepath = rtrim (plugin_dir_path (dirname (__FILE__)), '/'). $ Percorsofile; if (file_exists ($ filepath)) include_once ($ filepath); else wp_die (esc_html ('Il file specificato non esiste.'));Un'altra alternativa all'utilizzo dell'API di WordPress è rappresentata dal lancio di un messaggio di eccezione personalizzato. In questo modo, saremmo in grado di separare o disaccoppiare completamente il nostro codice da WordPress.
Ancora una volta, questo codice è un riporto dal caricatore automatico iniziale. Durante l'implementazione, possiamo cambiare anche questo.
Conclusione
Bene, quindi abbiamo esaminato il codice esistente per il nostro autoloader e quindi abbiamo eliminato un potenziale codice che è possibile utilizzare in base ad analisi e progettazione orientate agli oggetti.
La soluzione su cui stiamo lavorando è più gestibile di quella che abbiamo? Assolutamente. Funzionerà nel contesto di WordPress e del nostro plug-in esistente? Non lo sapremo fino a quando non inizieremo a collegarlo al nostro plug-in.
Come accennato in precedenza, ci sono ancora alcune aree in cui potremmo eventualmente refactoring questo codice. Se riscontriamo questo tipo di problemi quando implementiamo il nostro codice nella versione finale del nostro plugin, daremo un'occhiata a questo.
In ogni caso, il codice che abbiamo ora dovrebbe essere più leggibile (anche se abbiamo ancora DocBlocks e alcuni commenti in linea da introdurre) e più manutenibile e ancor più verificabile.
Con tutto ciò detto, spero che questo ti abbia dato un'idea su come prendere un metodo lungo e suddividerlo in classi più orientate allo scopo. Certo, avere classi multiple potrebbe sembrare strano all'inizio, ma questo non significa che sia una brutta cosa. Avere più file (e quindi classi) con meno codice di un file con un sacco di codice è meglio.
Abbracciare la natura controintuitiva della programmazione orientata agli oggetti in questo senso. Nel prossimo tutorial, ritorneremo al nostro plug-in e lavoreremo per implementare una variante del codice sopra. Probabilmente eseguiremo il debug di alcuni di essi. Dopotutto, raramente lo facciamo bene la prima volta
Fino ad allora, 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 seguire il mio sul mio blog o seguimi su Twitter, dove spesso parlo di entrambi.
risorse