Tabella Enum vs Lookup vs Enum reflection vs State pattern
-
03-07-2019 - |
Domanda
Il software che costruirò coinvolgerà " applicazione " passare da uno stato diverso molto. Alcune attività possono essere eseguite in base allo stato in cui si trova un'applicazione. Stavo pensando di usare enum come status
public class Application
{
public int Id {get;set;}
public Status {get;set;}
}
public enum Status
{
[Description("New")]New = 1, [Description("Closed")]Closed = 2
}
Ma poi ho pensato che forse è bene usare la tabella di ricerca nel database poiché lo stato viene aggiornato / riordinato abbastanza spesso
table status (id int pk, desc string, sort_order int)
table application (id int pk, status_id int fk)
Nel mio caso devo fare cose come
if (application.Status == Status.New)
{ //do something }
else if (application.Status == Status.Closed)
{ //do other things }
Penso che il caso precedente sia più facile da fare con enum. Tuttavia, quando si tratta di aggiornare l'ordinamento o la descrizione dello stato, sarà piuttosto difficile.
Dovrei usare la riflessione per creare dinamicamente enum in base ai valori della tabella di ricerca? O dovrei usare il modello di stato? Il problema che vedo con enfection refection è l'impatto sulle prestazioni. E il modello di stato può produrre molto codice ridondante.
Cosa ne pensi? Grazie in anticipo!
Soluzione
Creerei una classe Status che contiene le differenze e le chiamerei. Quindi (in Python):
class StatusZero(object):
def call_me(self, app):
print 'Hello, from ' + app.name
return db.prepare_specific_status_zero_request()
class StatusOne(object):
def call_me(self, app):
print 'Hi, from ' + app.name
return db.prepare_specific_status_one_request()
states = { 'status_zero' : StatusZero(), 'status_one' : StatusOne() }
class Application(object):
name = 'My App'
status = states['status_zero']
def change_state(self, state):
status = state
def call_me(self):
state_key = self.status.call_me(self)
self.change_state(states[state_key])
Veloce, facile da mantenere la funzionalità suddivisa in compartimenti e con un ragionevole modello di ereditarietà tra gli stati è possibile condividere le funzioni che non differiscono.
Altri suggerimenti
Non dovresti cospargere il tuo codice con questo segno di spunta ovunque
if (application.Status == Status.New)
{ //do something }
else if (application.Status == Status.Closed)
{ //do other things }
Invece, usa il modello di stato. Cambia lo stato ogni volta che cambia la modalità dell'applicazione e inoltra tutte le tue chiamate ai metodi dello stato. Avrai un codice molto più pulito e più facile da mantenere.
Per quanto riguarda la modifica dello stato, ciò non ha nulla a che fare con il modello di stato. Quindi puoi usare qualunque approccio sia elegante.
la mia comprensione è che il modello di stato è abbastanza buono per le sole esecuzioni dell'interfaccia utente o solo in memoria, dove nella mia situazione quando si recuperano i dati dalla tabella dell'applicazione, ci deve essere ancora un'istruzione if else per determinare su quale oggetto eseguire il cast.
public AbstractApplication convert_db_application_to_object(obj db_application)
{
AbstractApplication app;
if (db_application.Status == (int)Status.New)
app = application_factory.create(application_state_new);
else if(db_application.Status == (int)Status.Closed)
app = application_factory.create(application_state_closed);
return app;
}
Non la vedo come una soluzione elegante poiché ho ancora bisogno di una tabella enum o di ricerca per salvare lo stato dell'applicazione nel database