Progettare un modello

1

Sono uno sviluppatore PHP e cosa fanno gli sviluppatori PHP? Loro creano framework, quindi sto facendo il mio modo con il mio piccolo progetto di framework mvc e mi sono imbattuto in un problema di design su cui vorrei avere delle opinioni.

Per i miei modelli ho scelto di prendere il percorso degli oggetti dati (se questa è la terminologia corretta), non un grande fan del record attivo. In sostanza esiste un modello di gateway che gestisce la persistenza e il modello è solo lì per contenere i dati.

Il problema è, come faccio a ottenere questi dati nel modello.

Attenzione: questo comporta internals PHP e la mia ossessione performance

Questo è quello che avevo inizialmente.

abstract class Model {
    public function __construct(array $data = []) {
        foreach($data as $key => $value) $this->$key = $value;
    }    
}

Dopo aver scritto quel codice, il mio disturbo legato alle prestazioni ha iniziato a calare e ho pensato che questa iterazione fosse completamente superflua e potrei sostituirla con un incarico.

abstract class Model {
    public $props;
    public function __construct(array $data = []) {
        $this->props = $data;
    }    
}

L'esecuzione di benchmark in entrambi i casi ha giustificato il mio ragionamento in quanto il primo si è rivelato fino a 20 volte più lento (a seconda delle dimensioni di $data ), quindi naturalmente ho deciso che avrei continuato con il singolo incarico. p>

Non passò molto tempo prima che questo introducesse un nuovo problema: come diavolo accederò alle proprietà. Non posso andare a chiamare $model->props['property'] per un sacco di motivi - prima è brutto, secondo non riesco a ottenere il completamento del codice su questo e più il codice è aperto a errori come qualcuno (in futuro mi denigrerà) chiamando $model->props = 'not so smart assignment' e poi comincerò a ricevere errori dappertutto. Quindi ho pensato che dovevo proteggere questa proprietà e dare il giusto accesso ad essa, come con getter e setter:

abstract class Model {
    protected $props;
    public function __construct(array $data = []) {
        $this->props = $data;
    }

    public function __get($name) { ... }
    public function __set($name, $value) { ... }
}

Ma non ci vuole un genio (ovviamente, io) per rendermi conto che chiamare queste funzioni direttamente sarà molto più veloce che avere PHP a capire cosa sto cercando di fare e chiamarle per me, così ho lasciato cadere la magia parte e lascia solo i metodi get() e set() . Ora ho risolto il problema relativo all'accesso a props ma non ho risolto il problema riguardante il completamento del codice e il ragazzo che sarebbe un doloroso refactoring, se mai dovessi farlo, in futuro. Inoltre ho deciso di confrontare quale sarebbe stata la differenza tra l'accesso alla proprietà di un oggetto direttamente invece di ottenerlo da props con get() , risultati: la funzione di chiamata è 6 volte più lenta dell'accesso diretto.

In pratica, come vedo la decisione che devo prendere ora devo scegliere tra l'assegnazione dei dati del modello lento e il recupero dei dati del modello lento.

C'è qualcosa che mi manca, sono aperto a qualsiasi tipo di suggerimento.

    
posta php_nub_qq 05.03.2017 - 22:06
fonte

1 risposta

1

Per prima cosa, il modello di cui stai parlando non è la M in MVC. Il modello non è un modello di database che rappresenta una tabella, il modello è l'intera infrastruttura contenente (nella maggior parte dei casi) la logica aziendale, il modello è:

  • classi di servizio,
  • entità,
  • oggetti del dominio,
  • aiutanti ...

Sapendo che gli oggetti PHP non sono realmente oggetti ma mappe hash, in modo simile agli array PHP, che in realtà non sono affatto matrici, la tua micro-ottimizzazione non ha molto senso. Il problema con le applicazioni di oggi è raramente il 1e-6 s necessario per recuperare una proprietà, i problemi si verificano su una scala molto più ampia:

  • SQL scritto male,
  • I / O eccessivo,
  • viaggi non necessari per integrare servizi (cloud, database, ...),
  • ecc.

L'utilizzo dei metodi magic __get e __set ha un impatto così basso che in realtà non è necessario fornire metodi personalizzati che facciano la stessa cosa.

Ma per quanto riguarda il completamento e il refactoring dell'IDE?

L'onnipotente phpDoc ci ha offerto due fantastiche opzioni:

  • @property ,
  • @property-read .

Entrambi sono anteposti a una classe, con la seguente sintassi:

@property/@property-read <data_type> <property_name>
eg. @property int $Number

Gli IDE moderni, come PHPStorm o NetBeans, supportano queste annotazioni e ti forniranno correttamente il completamento automatico se dichiari correttamente le annotazioni.

Finché non si accede a una proprietà che non è stata dichiarata utilizzando l'annotazione @property o @property-read , es. dovresti costringerti a dichiarare tale proprietà prima di accedervi, puoi rifattorizzare il tuo codice usando gli strumenti di refactoring di IDE.

E se ciò non soddisfa le tue esigenze, elimina completamente la classe Model , ma al momento non fornisce assolutamente nulla e usa invece le classi regolari . Renderà molto più chiaro l'intento del codice, che ogni nuovo sviluppatore che verrà al progetto apprezzerà molto di più di un sacco di magia per l'astrazione del linguaggio, proprio perché PHP ti permette di farlo.

Il mio contributo personale, se il framework che stai creando non è altro che uno scopo di apprendimento, stai meglio usando qualcosa che è già stato creato e dimostrato funzionale.

Anch'io sono caduto nell'inferno della creazione di un framework, pensando Ho bisogno di un framework per questo, e se ne avessi bisogno in un altro progetto, fondamentalmente copiando ciò che qualcun altro aveva già fatto e usando il framework creato in circa esattamente un progetto.

    
risposta data 05.03.2017 - 22:49
fonte

Leggi altre domande sui tag