2013-03-14 10 views
8

Attualmente ho un'applicazione abbastanza grande scritta interamente con PHP procedurale. Sto cercando di migliorare la mia esperienza di PHP e ricodificare la maggior parte della mia applicazione utilizzando tecniche orientate agli oggetti.Conversione di PHP procedurale in PHP orientato agli oggetti

Ci sono molte aree in cui OOP può aiutare a ridurre la quantità di codice e renderlo più facile da leggere. Tuttavia, ho alcune domande.

1) È a mia conoscenza che una classe viene utilizzata come progetto per qualsiasi numero di oggetti, ma una classe rappresenta solo un oggetto, mai più di uno. Quindi una classe potrebbe rappresentare un giocatore, ma mai più giocatori.

2) Dal momento che avrà un bel paio di classi diverse per includere, devo usare una classe "Loader" per caricare tutti loro utilizzando spl_autoload_register o faccio uso solo spl_autoload_register nelle file di programma per la mia applicazione?

Edit: Quindi il mio caricatore automatico sarebbe una classe che ho poi creare un'istanza per avviare il caricamento automatico o semplicemente un file PHP con la funzione e l'spl_autoload_register che vorrei includere per evitare di ripetere lo stesso codice in più file ?

3) Alcune delle mie classi dipendono da altre classi. Non l'ho mai incontrato prima, quindi sinceramente non conosco la risposta. Se includo tutte le classi nel mio file di programma principale, ma la classe del mio lettore non è non include la classe che deve funzionare, la classe del giocatore funzionerà poiché il programma principale ha incluso la classe da quale giocatore dipende?

Edit: Quindi, anche se una classe può istanziare un oggetto di tipo Player, e la classe Player non è direttamente incluso da questa classe, che continuerà a funzionare perché la classe controller non comprende la classe Player?

4) Ci sono diversi casi in cui dovrò lavorare sugli oggetti che sto creando. Mi chiedo come dovrei farlo. Ad esempio, nella mia lezione di giocatore, a volte ho bisogno di inviare qualcosa da un giocatore all'altro giocatore. Quindi, devo implementare un metodo statico nella classe Player che prende due giocatori come parametri e fa il trasferimento o faccio qualcos'altro?

Modifica: Ok, quindi evitare i metodi statici. Ora ho un problema serio: ho metodi che vengono eseguiti più volte nella mia applicazione, ma non li posso implementare come metodi statici. Dovrei implementarli come metodi di istanza? Ad esempio, l'invio da un giocatore all'altro. Vorrei creare un metodo di istanza che prende un oggetto Player e invia a o da esso?

5) Ho un sacco di metodi che non appartengono veramente a nessuna istanza di una classe, né sono veramente appropriati come metodi statici. Dovrebbero essere dichiarati nella loro stessa classe come metodi statici come comuni o simili? Che cosa è fatto in pratica in questa situazione?

Modifica: Questi metodi appartengono allo specifico file dell'applicazione per il quale vengono utilizzati o possono essere memorizzati nel proprio file "functions.php"?

6) Mi piacerebbe imparare come utilizzare gli spazi dei nomi, ma il mio codice non verrà mai utilizzato da altri e non userò mai il codice di nessun altro nella mia applicazione. Gli spazi dei nomi sono un'aggiunta inutile nella mia applicazione o sarebbe una buona idea imparare a usarli? Indipendentemente da ciò, un'applicazione ha uno spazio dei nomi (il nome dell'applicazione?) O ogni classe appartiene al proprio spazio dei nomi?

7) Infine, è comune avere una classe per le connessioni al database e anche una classe per i metodi di rete? La mia applicazione ha bisogno di entrambi. Penso che il problema principale che sto avendo con la conversione del mio codice nell'uso di tecniche orientate agli oggetti è determinare quali metodi mettere dove, come al momento sono tutti in un unico file monolitico.

Grazie per l'aiuto e l'approfondimento che puoi fornire.

risposta

2

1) E 'la mia comprensione che una classe è utilizzata come modello per qualsiasi numero di oggetti, ma qualsiasi classe rappresenta solo un oggetto, mai più di uno. Quindi una classe potrebbe rappresentare un giocatore, ma mai più giocatori.

In genere, si avrà anche classi che rappresentano collezioni di oggetti, per esempio una classe "Players" che possono essere utilizzati per recuperare un singolo giocatore dalla raccolta di tutti i giocatori:

$players = new Players(); 
$john = $players->findByName("john"); 

2) Dal momento che avrò un bel paio di classi diverse per includere, fare io uso un "Loader "classe per caricarli tutti usando spl_autoload_register o semplicemente utilizzo spl_autoload_register nei file di programma per la mia applicazione?

Questo dipende in gran parte dalla complessità del progetto. Una semplice funzione di caricamento automatico sarà in genere sufficiente ma è possibile dare un'occhiata allo Zend Framework Autoloader class.

3) Alcune delle mie classi dipendono da altre classi. Non l'ho mai incontrato prima, quindi sinceramente non conosco la risposta. Se includo tutte le classi nel mio file di programma principale, ma la mia classe di giocatore non include la classe che deve funzionare, la classe del giocatore funzionerà dal momento che il programma principale ha incluso la classe da quale giocatore dipende?

Sì. Tuttavia, con l'autoloading non è necessario preoccuparsi di questo. Se non si utilizza il caricamento automatico, è consigliabile includere le classi richieste nel file che definisce la classe (utilizzando require_once() per evitare di includere lo stesso file più di una volta).

4) Ci sono più casi in cui dovrò lavorare sugli oggetti che sto creando. Mi chiedo come dovrei farlo. Ad esempio, nella mia lezione di giocatore, a volte ho bisogno di inviare qualcosa da un giocatore all'altro giocatore. Quindi, devo implementare un metodo statico nella classe Player che prende due giocatori come parametri e fa il trasferimento o faccio qualcos'altro?

I metodi statici sono quasi sempre l'approccio sbagliato. I metodi normali appartengono a un'istanza (cioè il giocatore specifico) e i metodi statici appartengono alla classe, cioè l'idea generale di un giocatore. Se avete bisogno di trasferire roba da un giocatore all'altro, perché non implementare questa come questo:

class Player { 
    public function transferMoney(Player $recipient, $amount) { ... } 
} 

$tom = new Player("tom"); 
$marc = new Player("marc"); 

$tom->transferMoney($marc, 500); 

5) Ho un sacco di metodi che in realtà non appartengono a qualsiasi istanza di una classe, né sono davvero appropriati come metodi statici. Dovrebbero essere dichiarati nella loro stessa classe come metodi statici come comuni o simili? Che cosa è fatto in pratica in questa situazione?

Non riesco a rispondere ragionevolmente a questo. Tuttavia, ci sono ancora semplici funzioni in PHP che sembrano essere il metodo migliore per questi casi. Tuttavia, se fai bene OOP, molto probabilmente non incontrerai mai simili problemi. Di solito è un problema con il tuo design di classe che ti fa sembrare che questi metodi non appartengano a nessun oggetto.

6) Mi piacerebbe imparare come utilizzare gli spazi dei nomi, ma il mio codice non verrà mai utilizzato da altri e non userò mai il codice di nessun altro nella mia applicazione. Gli spazi dei nomi sono un'aggiunta inutile nella mia applicazione o sarebbe una buona idea imparare a usarli? Indipendentemente da ciò, un'applicazione ha uno spazio dei nomi (il nome dell'applicazione?) O ogni classe appartiene al proprio spazio dei nomi?

Gli spazi dei nomi sono fantastici, ma il codice probabilmente andrà bene senza di loro. Poiché gli spazi dei nomi possono essere nidificati, di solito si dispone di uno spazio dei nomi di primo livello e di un sottotitolo per componente.

7) Infine, è comune avere una classe per le connessioni al database e anche una classe per i metodi di rete? La mia applicazione ha bisogno di entrambi. Penso che il problema principale che sto avendo con la conversione del mio codice nell'uso di tecniche orientate agli oggetti è determinare quali metodi mettere dove, come al momento sono tutti in un unico file monolitico.

Questo dipende da come si modella la situazione attuale. Se la connessione al database e la "rete" sono due cose diverse per te, due sono le strade da percorrere.

+0

Grazie per il tuo post! Il tuo # 1 e # 4 * davvero * ha aiutato a chiarire le cose! Una collezione di giocatori ha sicuramente un senso per la mia applicazione e anche l'utilizzo di metodi di istanza per trasferire elementi ha perfettamente senso. Seguirò i consigli di tutti e starò molto lontano dai metodi statici. –

4

1) È a mia conoscenza che una classe viene utilizzata come progetto per qualsiasi numero di oggetti, ma una classe rappresenta solo un oggetto, mai più di uno. Quindi una classe potrebbe rappresentare un giocatore, ma mai più giocatori.

Una classe non rappresenta nulla perché, come hai affermato correttamente, è solo un progetto per qualsiasi numero di oggetti. Puoi avere più istanze (oggetti) della stessa classe che rappresentano più giocatori.

2) Dal momento che avrò alcune classi molto diverso per includere, devo usare una classe "Loader" per caricare tutti loro utilizzando spl_autoload_register o faccio uso solo spl_autoload_register nelle file di programma per la mia applicazione?

Senza sapere cosa intendi per "file di programma per la mia applicazione", dico di sì. Usa un caricatore automatico, perché funziona e non devi preoccuparti di fare require_*.

3) Alcune delle mie classi dipendono da altre classi. Non l'ho mai incontrato prima, quindi sinceramente non conosco la risposta. Se includo tutte le classi nel mio file di programma principale, ma la mia classe di giocatore non include la classe che deve funzionare, la classe del giocatore funzionerà dal momento che il programma principale ha incluso la classe da quale giocatore dipende?

Non si desidera caricare tutte le classi, ma solo quelle che si intende utilizzare. Che di nuovo non è qualcosa di cui ti devi preoccupare quando usi un caricatore automatico. Ma sì, una volta caricata una classe, può essere un'istanza per tutta l'applicazione.

Normalmente si vorrebbe avviare l'autploader nel bootstrap phase of the application.

4) Ci sono più casi in cui dovrò lavorare sugli oggetti che sto creando. Mi chiedo come dovrei farlo. Ad esempio, nella mia lezione di giocatore, a volte ho bisogno di inviare qualcosa da un giocatore all'altro giocatore. Quindi, devo implementare un metodo statico nella classe Player che prende due giocatori come parametri e fa il trasferimento o faccio qualcos'altro?

Evitare l'uso di metodi statici in OOP PHP. Non è quasi mai necessario. Potresti pensare di avere un'altra classe che si comporta come un gruppo di giocatori che si occupa di "inviare dati" da un giocatore a un altro.

Quindi non importa dove il file con la classe è incluso finché ciò accade prima di tentare di istanziarlo.

5) Ho molti metodi che non appartengono realmente a nessuna istanza di una classe, né sono realmente appropriati come metodi statici. Dovrebbero essere dichiarati nella loro stessa classe come metodi statici come comuni o simili? Che cosa è fatto in pratica in questa situazione?

Anche in questo caso, non utilizzare metodi statici. Se li usi in qualche altra classe, stai solo rendendo difficile testare le tue classi e introdurre dipendenze nascoste. Nella mia esperienza lo quasi non ha mai un solo metodo da qualche parte per qualcosa. Forse i metodi stanno facendo troppo.

Ma è difficile da dire semplicemente leggendo la domanda. Forse puoi dare un esempio in un commento?

6) Mi piacerebbe imparare come utilizzare gli spazi dei nomi, ma il mio codice non verrà mai utilizzato da altri e non userò mai il codice di nessun altro nella mia applicazione. Gli spazi dei nomi sono un'aggiunta inutile nella mia applicazione o sarebbe una buona idea imparare a usarli?

Il namespace in PHP riguarda la strutturazione. Anche se nessun altro userà il tuo codice, non dovrai preoccuparti di usare lo stesso nome per una classe da qualche parte. Che avverrà quando l'applicazione si ingrandirà piuttosto prima che dopo.

Indipendentemente da ciò, un'applicazione ha uno spazio dei nomi (il nome dell'applicazione?) Oppure ogni classe appartiene al proprio spazio dei nomi?

Seguo spesso PSR-0 quando si tratta di spazi dei nomi.

7) Infine, è comune avere una classe per le connessioni al database e anche una classe per i metodi di rete? La mia applicazione ha bisogno di entrambi. Penso che il problema principale che sto avendo con la conversione del mio codice nell'uso di tecniche orientate agli oggetti è determinare quali metodi mettere dove, come al momento sono tutti in un unico file monolitico.

Basta tenere il Single Reponsibility Principle in mente e, in generale, SOLID.

Inoltre consiglio vivamente di guardare these e continuare a guardarli finché non lo capisci.

+0

Grazie per il tuo eccellente post. Ho apportato alcune modifiche per chiarire le mie domande. Puoi dare un'occhiata? :) –

+0

Questo è un metodo semplice che uso attualmente. Non ha molto senso creare una classe solo per un metodo, quindi a che cosa appartiene? 'public function getCurrentTime() {return round (microtime (true) * 1000); } ' –

+1

Non penso che creerei un metodo per qualcosa di semplice penso. – PeeHaa

1
  1. Un PlayerCollection sarebbe una classe valido. Naturalmente un oggetto di esso è una raccolta di più giocatori.

  2. Utilizzare spl_autoload_register, punto. È preferibile seguire lo standard PSR-0 e utilizzare qualsiasi caricatore automatico compatibile con PSR-0 (ad esempio Symfony Loader)

  3. Funzionerà. Ma dal momento che usi un caricatore automatico (vedi 2.) Non devi preoccuparti di includere le classi per tutto

  4. L'invio di un messaggio dal giocatore 1 al giocatore 2 è facilmente tradotto nel chiamare un metodo del giocatore 2 nel giocatore 1. Tuttavia, "inviare cose" e "lavorare" sugli oggetti "potrebbe significare molte cose quindi la risposta è: dipende. Ma in generale è un buon consiglio per evitare i metodi statici.

  5. Questo suona molto come il pensiero procedurale. Mi spiace ma non posso darti una risposta argentea qui, dovrai apprendere e comprendere i principi del design orientato agli oggetti per applicarli. C'è una certa letteratura standard e molte risorse utili sul web. Anche l'apprendimento tramite l'esempio può essere utile (guarda altre applicazioni OO e framework open source)

  6. "una applicazione ha uno spazio dei nomi (il nome dell'applicazione?) O ogni classe appartiene al proprio spazio dei nomi?" - la risposta è nel mezzo. I namespace sono utili per raggruppare insieme cose che funzionano insieme e sono utili indipendentemente da chi userà o vedrà il codice.

  7. Prima regola del design orientato agli oggetti: una classe, una responsabilità.

+0

Grazie per il tuo post. Ho apportato alcune modifiche alla mia domanda per riflettere sulle tue risposte. Il tuo # 1 ha davvero chiarito le cose per me. Non avrei mai pensato che una collezione di giocatori sarebbe stata molto utile, ma ha senso che possa essere fatta se ne hai un'esigenza specifica. –