Dove devo mettere un metodo che restituisce un elenco di voci attive di una tabella?

5

Ho una classe denominata GuestbookEntry che esegue il mapping alle proprietà che si trovano nella tabella del database denominata "guestbook". Molto semplice!

In origine, avevo un metodo statico chiamato getActiveEntries() che recuperava una matrice di tutti gli oggetti GuestbookEntry . Ogni riga nella tabella del guestbook era un oggetto che è stato aggiunto a quell'array. Poi mentre imparavo a progettare correttamente le classi PHP, ho imparato alcune cose:

  1. I metodi statici non sono desiderabili.
  2. Separazione delle preoccupazioni
  3. Principio di responsabilità singola

Se la classe GuestbookEntry dovrebbe essere responsabile solo della gestione delle singole voci del libro degli ospiti, dove dovrebbe andare questo metodo getActiveEntries() ?

Aggiornamento:

Sto cercando una risposta che rispetti i principi degli acronimo SOLID e che permetta di testare le abilità. Ecco perché voglio stare lontano dalle chiamate statiche / funzioni standard.

DAO, repository, ...? Per favore, spiega come la tua spiegazione farà parte di "Dove trovare PER DUMMI" ...: -)

    
posta darga33 04.11.2012 - 02:26
fonte

6 risposte

0

Questo caso d'uso richiede un oggetto di accesso ai dati (DAO) , che gestisce la responsabilità del recupero di oggetti dal sottostante archivio dati.

Ad esempio, puoi definire un GuestbookEntryDao con metodi come getById(...) , getActiveEntries(...sort options...) , ecc.

Modifica: in risposta al tuo commento:

GuestbookEntryDao sarebbe un'interfaccia, implementata infine da una classe MySqlGuestBookEntryDao o giù di lì. Il punto è che puoi in seguito cambiare le implementazioni (rilascia una classe FlatXmlGuestBookEntryDao ) senza influire sul resto dell'app.

GuestbookEntry sarebbe non estendere GuestbookEntryDao , e IMHO dovrebbe non dipendere da questo (anche se alcune persone non sono d'accordo): dovrebbero essere completamente separati, perché ci sono 2 responsabilità separate in gioco (il modello e le responsabilità di accesso ai dati).

Il risultato è che, da qualche parte nella tua app, avrai un processo di alto livello che rappresenta un caso d'uso della tua applicazione che potrebbe sembrare qualcosa di simile (pseudo-codice):

function browseGuestBook() {

    // ... determine which entries to retrieve ...

    // retrieve entries
    entries = guestBookEntryDao.getActiveEntries(...);

    // store entries in output model
    // (this part may vary wildly depending on your app)
    guestbookBrowserOutput.entries = entries;

    // ...

}

Le classi in cui risiedono tali funzioni / processi sono solitamente chiamate servizi in design basato sul dominio ( Mi riferisco a un servizio a livello di applicazione in questo caso, non un servizio di dominio). Questo oggetto dipenderà da GuestbookEntryDao per recuperare le voci necessarie; GuestbookEntry non sa GuestbookEntryDao esiste.

Ciò riguarda anche l'iniezione di dipendenza e la fornitura di oggetti con i riferimenti di cui hanno bisogno per svolgere il loro lavoro - niente di più e niente di meno - ma questo è un argomento diverso ...

    
risposta data 04.11.2012 - 05:25
fonte
1

Dove hai imparato che i metodi statici non sono desiderabili? Ho una domanda per te: quante tabelle guestbook hai? Ovviamente, hai solo 1.

A volte ha molto senso usare una semplice vecchia funzione o un metodo statico per eseguire operazioni meta che sono un "livello superiore".

Alcuni sostengono una classe GuestbookEntryCollection che gestisce un insieme di oggetti GuestBookEntry , ma ...

... qui è dove entrano in gioco il purismo e il pragmatismo.

Se tutto ciò di cui hai bisogno è una lista di oggetti GuestBookEntry , allora metti quel codice in un callable (che si tratti di una funzione o di un metodo statico), e chiamalo semplicemente.

Hai bisogno di funzionalità avanzate, come la creazione di una query personalizzata, l'ordinamento, il filtraggio, ecc ...? Forse questo garantisce una classe separata per gestirlo.

Qual è la differenza tra oggetti e funzioni? Gli oggetti possono mantenere uno stato individuale, mentre le funzioni sono senza stato. Se stai eseguendo operazioni funzionali e non hai lo stato da gestire, allora le funzioni sono fantastiche!

Ecco un'altra cosa da considerare ... In PHP, le funzioni devono essere incluse manualmente prima che possano essere utilizzate, ma le classi hanno la capacità di autoload.

include('/path/to/function.php')
$x = GuestbookEntryList()

vs.

$x = GuestbookEntry::GetList()

vs.

$x = new GuestbookEntryCollection()

Spunti di riflessione:)

    
risposta data 04.11.2012 - 03:41
fonte
0

Ecco come lo farei. Per i dati di riga basta utilizzare gli array, quindi:

$entry = array(
    'entry_id' => '23',
    'user_id' => '4',
    'creation_date' => '2012-11-03',
    'content' => 'blah blah.');

Le chiamate al modello di database restituiranno i dati delle righe nel formato sopra riportato - questo è anche il modo in cui i plug-in del database PHP restituiscono i dati in modo da non dover fare nulla. Quindi per ottenere i dati basta avere un oggetto modello:

class EntryModel {
    public function getEntries() {
        //
    }

    public function getEntry($entryID) {
        //
    }
}

Quindi, come puoi vedere, non importa se stai ricevendo una singola voce o un gruppo di voci: basta che il tuo metodo restituisca il set di dati desiderato.

    
risposta data 04.11.2012 - 04:08
fonte
0

Dal momento che probabilmente stai cercando un tipo di risposta purism e non si tratta solo di cosa potrebbe funzionare, allora Guestbook non dovrebbe nemmeno dipendere da un database.

Piuttosto, hai Guestbook , hai Database e hai GuestbookGateway . Il gateway recupera le righe dal database sotto forma di oggetti PHP e quando qualcosa deve essere modificato, il gateway ha un metodo save che accetta un Guestbook . Questa è una vera separazione delle preoccupazioni.

L'ORM può portare a molti problemi dall'accoppiamento stretto su cui si basa. Ho avuto a che fare con alcuni di loro in passato, e non era carino. Tuttavia, va notato che per molte applicazioni (in particolare le applicazioni Web che di solito funzionano allo stesso modo), l'ORM è abbastanza buono.

    
risposta data 04.11.2012 - 06:14
fonte
0

Personalmente andrei a fare una lezione, 'Guestbook', che contiene l'array di GuestbookEntries e avere la funzione come membro di quella classe. La funzione può ancora restituire una serie di voci come desiderato.

    
risposta data 05.11.2012 - 01:37
fonte
0

Se capisco la tua domanda, giusto ...

stai cercando il posto "corretto" per mettere il metodo getActiveEntries (). Perché da un punto di vista "di OO-Design" vuoi aderire ai principi di:

  • Separazione delle preoccupazioni
  • Principio di responsabilità singola

(FYI: non ho mai sentito evitare la statica, quindi l'ho saltata)

La causa del tuo "problema" :

Ogni singola voce dovrebbe preoccuparsi solo di se stessa e solo di se stessa. Pertanto non può essere responsabile di una "raccolta" di voci.

I principi che hai menzionato sopra sono principi orientati agli oggetti. Le soluzioni per problemi che coinvolgono i principi OO richiedono la creazione di molti oggetti e di molte classi in modo che insieme funzionino come soluzione.

Ora se il metodo "getEntries" non può entrare nella classe DAO (Data Access Object) è

... potrebbe entrare in un tipo di fabbrica di classe. Una fabbrica è responsabile della "creazione" di oggetti. Si potrebbe sostenere che una Factory for GuestBookEntries ha 2 metodi: createEntryFromId (int $ entryId) e createActiveEntries ().

... potrebbe andare in un tipo di classe di controller. Come la fabbrica sopra, appena nominata diversamente. Il tipo di classe del controller può fare qualsiasi cosa, anche più di una fabbrica. Se hai bisogno di qualcosa come "verify ()" o "isDirty" per il tuo GuestBookEntry, la fabbrica non sarebbe di nuovo il posto dove mettere quei metodi. Le fabbriche sono preoccupate solo della creazione (hanno il dovere di garantire la creazione o fallire rapidamente) dove il tipo di classe di controller può eseguire metodi verify () o isXYZ () senza danneggiare il loro "scopo".

... alla fine non importa ciò che chiami "it". Ma avrai bisogno di un'altra "classe / oggetto" per assumerti la responsabilità di ripristinare una raccolta di GuestBookEntries attivi. Molto probabilmente questa classe utilizzerà la singola classe GuestBookEntry che hai già.

Quando si arriva a implementare i metodi che interagiscono tra loro (la nuova classe e il GuestBookEntry), si può usare array () come contenitore per trasportare oggetti GuestBookEntry. È possibile creare un contenitore speciale "digitato" che garantisce di trasportare solo oggetti GuestBookEntry, ma questo dipende ancora da voi. (Inoltre, ancora un'altra decisione in merito alla progettazione, hehe)

Per riassumere:

Crea un'altra classe con la responsabilità di recuperare "raccolte di GuestBookEntries in base al loro stato (attivo / inattivo)" che utilizza (composizione) la tua classe GuestBookEntry esistente.

    
risposta data 06.11.2012 - 11:55
fonte

Leggi altre domande sui tag