2009-02-17 13 views
52

Sono bloccato in un problema di progettazione strano,Tavolo unico eredità e dove usarlo in Rails

Sto lavorando su due tipi di profili Models,

  • Profilo utente (appartiene a utente)
  • altri che sono mantenere in loco come "bot" (non appartiene a nessuno)

Il comportamento OO tipico di questi due tipi di profili è stessa ma solo le importanti attributi/proprietà sono comuni (i più importanti 5-6 in numero), altre proprietà come "interessi ecc." (quasi 10-15 proprietà) non sono disponibili per i profili bot

Il codificatore che ha lavorato a questa versione precedente ha creato modelli/controllori separati per profili bot/Profili utente che creano una grande ridondanza ovunque e anche come ci si aspetta che sia difficile da mantenere, scrivere test, ecc. Ho voluto ASCIUGARLA, almeno per risolvere alcuni/tutti questi problemi di ridondanza.

Qualcuno ha suggerito l'ereditarietà singola tabella come soluzione

Qualcuno ha suggerito Utilizzare Associazioni polimorfiche, invece.

qual è l'approccio migliore. Quando usiamo effettivamente STI?

Il mio pensiero è che STI viene utilizzato al meglio quando gli attributi sono uguali per i modelli e differiscono nel comportamento.

Pensieri su cosa posso fare?

risposta

34

La caratterizzazione di STI è utile soprattutto quando gli attributi sono gli stessi, ma il comportamento differisce da "a destra", ma forse un po 'limitante. Mi piace usare STI quando esiste, come suggerisce il nome, una chiara relazione di ereditarietà stile OO, piuttosto che la relazione in stile database tra oggetti di tipi diversi.

Se esiste un codice comune tra i robot e gli utenti, direi che STI sembra un vincitore. Se ci sono solo alcuni attributi comuni, probabilmente è meno applicabile ma vale comunque la pena provarci.

Sono una persona piuttosto sperimentale, quindi la mia raccomandazione è di provarla. Separa il tuo codice e rifatta i modelli in una relazione STI. Guarda se fa veramente asciugare le cose, o semplicemente scambia una serie di mal di testa per qualche altro problema.

Una cosa che penso non vedrai molto vantaggio è l'esaurimento dei controller. Nella mia esperienza, i modelli STI non si traducono spesso in controller simili. Ma sarebbe un'altra cosa da sperimentare. A volte c'è una vittoria, a volte non c'è.

+0

Ho intenzione di sperimentare con STI, penso. Ma quali sono i problemi che potrei affrontare se ho solo alcuni attributi comuni? –

+1

Un altro modo per gestire i controller è di sottoclassi, come i modelli ... refactoring per rendere condivisibili i metodi comuni tra loro. –

+0

@Andrew: IME, che non funziona quasi altrettanto bene come la sottoclasse per i modelli, tranne nel caso CRUD (relativamente raro) di scaffold per bare bare. – womble

5

Probabilmente userei STI o nessuna funzionalità speciale. Potresti essere in grado di chiamare tutto un profilo e sapresti se era un "bot" se il suo utente era zero. È anche possibile memorizzare un campo "tipo" senza utilizzare STI.

Certe cose sarebbero influenzare la mia decisione di utilizzare STI:

  • Se c'è specifico-bot logica
  • quanti bot ci sono rispetto a profili di utenti (piccolo numero di bot significa STI è OK - un sacco di i robot e io potremmo conservarli altrove)

Il motivo per evitare STI a volte può essere d'intralcio. Ad esempio può essere abbastanza fastidioso cambiare un oggetto da un tipo all'altro (un Bot in un profilo in questo caso). A volte un semplice campo di "tipo" è migliore.

Vale la pena notare che probabilmente si vorrà una classe di base comune se si utilizza STI. Quindi potresti volere Profile, BotProfile e UserProfile. I nomi dipendono da te. :)

+0

Sono d'accordo, stavo pensando a un approccio simile. –

+2

Basta chiedersi, perché è noioso cambiare un oggetto da un tipo all'altro? bot.becomes (Profilo) è piuttosto chiaro e facile ... –

+0

@andrew: non ero a conoscenza di #become, ma questo in realtà non cambia il tipo di oggetto, solo il suo nome di classe, e in realtà non ha nulla a che fare con STI . – wuputah

4

Un tozzo di Rails STI: la maggior parte dei plug-in (e così via) non la supporta completamente. Ti troverai a rattoppare molti di quelli comuni.

+0

Hai avuto problemi con STI e activeadmin? – JohnMerlino

29

ho scritto un articolo su questo argomento, tra cui alcuni suggerimenti per lavorare con STI:

Single Table Inheritance in Rails

In breve: ci deve essere una chiara relazione di ereditarietà OO-style tra gli oggetti (come eloquentemente dichiarato da womble), non solo alcuni dati condivisi. Se non esiste una gerarchia di classi naturale e ovvia, un progetto STI può diventare difficile da mantenere man mano che l'applicazione si evolve.

In secondo luogo, è necessario considerare se è importante avere tutti i dati in una tabella. Con le associazioni polimorfiche, le query del database diventeranno più complesse e probabilmente più lente. Se stai pianificando di elencare tutti gli oggetti sul sito (ad esempio, in una tabella), allora STI potrebbe essere la strada da percorrere.

In terzo luogo, assicurarsi che le classi figlio non contengano troppi attributi univoci. Con tutti i dati in una tabella, non vuoi molte colonne non globali. Non solo occupano spazio (non è una preoccupazione importante), ma rendono la struttura dei dati confusa. Se hai colonne "speciali" dovresti spiegarle esplicitamente nel tuo codice.

Infine, se si utilizza STI, si consiglia vivamente di utilizzare un singolo controller per tutti i modelli figlio. La funzione principale di un controller è quella di fornire accesso agli oggetti, e se gli oggetti devono essere accessibili in modi molto diversi, allora STI potrebbe non essere stata la scelta di progettazione corretta per cominciare.

Controlla il mio articolo (link sopra) per alcuni consigli più utili.