Cercando di implementare il codice del metodo pre / post: meglio usare i metodi o una classe genitore?

4

Sto trovando difficile inquadrare questa domanda quindi ... Voglio eseguire codice sia prima che dopo un metodo eseguito in PHP. Ci sono, per quanto ne so, due modi per implementarlo:

Metodo uno: metodi pre e post

class Model
{
  function find($id)
  {
    $this->_precode();
    // ... do stuff
    $this->post_code();
  }
}

Aggiungi le chiamate a _precode() e _postcode() a ciascun metodo in cui ho bisogno di questa funzionalità.

Metodo 2: __call e denominazione del metodo

class Model extends PrePost
{
  function prepost_find($id)
  {
    // ... do stuff ...
  }
}

class PrePost 
{
  function __call($method,$param) 
  {
    $method = "prepost_$method";
    // .. precode here ..
    $result = $this->$method($param);
    // .. postcode here ..
  }
}

Questo dipende dal nominare un metodo in un modo specifico nella classe ereditaria. C'è un modo preferito per farlo? Il metodo di chiamata può essere fatto per gestire solo i suoi casi specifici e persino rimandare alla chiamata di una classe figlia, se ce n'è una.

Non sto cercando opinioni; Sto cercando di scoprire se ci sono validi motivi per scegliere un modo piuttosto che un altro.

    
posta Will 13.11.2012 - 19:27
fonte

1 risposta

7

In realtà ci sono molti più modi di quello che pensi.

Metodo di chiamata magica

Questo è il codice per me. Non è difficile da seguire e, come mostrato, apre alcuni possibili problemi di codifica per i chiamanti esterni della classe. Se chiamo $ model- > something (), e non esiste, proverà a eseguire prepost__something () in modo errato. La magia è generalmente difficile da seguire e può darti delle condizioni inaspettate.

Metodi di chiamata esplicita

L'esplicito è sempre migliore, ma non quando interrompe il flusso principale del tuo metodo. Inoltre, quanto spesso stai facendo questo? In 1 classe? 10? 100? Se si tratta di qualcosa che si sta ripetendo molto, allora dovresti esaminare completamente un altro metodo.

La grande domanda è quale tipo di funzionalità si nasconde in quelle funzioni pre / post ... è correlata? È qualcosa come la registrazione, il debug, ecc. Che non è affatto correlato, ma deve essere eseguito lì?

Event Driven

Se non sono correlati, il percorso migliore è un sistema basato su eventi. Questo è molto comune nelle applicazioni / framework più popolari (ben scritti, comunque).

class Model
{
  function find($id)
  {
    $this->dispatcher->dispatch("model.find.pre", $event = new PreFindEvent($id));

    // do whatever with $event->getId()

    $this->dispatcher->dispatch("model.find.post", new PostFindEvent($id, $result));
    return $result;
  }
}

Ciò richiede che tu passi un componente del dispatcher di eventi nella tua classe (iniezione di dipendenza) e colleghi manualmente tutte le classi attivate nel dispatcher di eventi. Tuttavia, è possibile attivare il comportamento in classi molto concise che modificano la funzionalità prima / dopo che si sta andando. Questo può essere molto prolisso, ma è testabile e consente di scrivere codice molto modulare. Scopri il componente EventDispatcher di Symfony per ulteriori esempi, sebbene molti altri fornitori offrano funzionalità simili.

Se è troppo verboso per te, e vuoi qualcosa di un po 'più radicale, c'è anche

Programmazione orientata agli aspetti

Se vuoi implementare la funzionalità cross-cutting (ex, logging) tra diversi metodi, allora questa è un'opzione molto utile. Tuttavia, il supporto PHP non è eccezionale (è richiesta un'estensione sperimentale o integrazione del framework).

Ti consente di attivare dinamicamente il codice in vari punti dell'applicazione SENZA dover aggiungere esplicitamente i punti di aggancio nel codice. Qualcosa di simile,

aop_add_before('some_function', 'run_this');

Probabilmente, questo rende l'esecuzione del codice molto difficile da seguire, ma ti permette di fare cose molto interessanti senza tutta la complessità aggiuntiva della programmazione basata sugli eventi. Se usi qualcosa come un contenitore per le dipendenze, anche l'aggiunta di AOP potrebbe essere possibile, anche se dipende molto dagli strumenti che usi.

Conclusione

Queste sono le opzioni. Consiglierei event-based in quanto sembra essere lo standard della comunità in PHP. (Symfony, Zend, ecc.) AOP è meglio supportato in altri linguaggi (nativamente), ed è un po 'hacky in PHP al momento.

In ogni caso, ti stai dirigendo sempre più verso l'iniezione di dipendenza, e potrebbe essere una lattina completamente nuova di worm da aprire per prima.

Spero che questo aiuti. Non c'è una risposta giusta: dipende sempre dagli strumenti attuali e dal dominio problematico.

    
risposta data 13.11.2012 - 19:55
fonte

Leggi altre domande sui tag