2009-05-29 10 views
7

Supponiamo di disporre di 3 livelli: interfaccia utente, azienda, dati.Il livello aziendale dell'applicazione dovrebbe poter accedere all'oggetto Session?

È un segno di progettazione scadente se il livello aziendale deve accedere alle sessioni? Qualcosa non sembra giusto. Ci sono delle linee guida da seguire specificamente su misura per l'app web?

io uso C# 2.0 .net

+0

Grazie per tutte le risposte. La principale preoccupazione che ho notato è la capacità di "cambiare" il livello aziendale, se necessario. La mia app funzionerà SEMPRE sul web, quindi Session sarà SEMPRE pertinente, fino a quando la sessione sarà obsoleta, quindi non è una preoccupazione qui. – sarsnake

+0

quindi nessun test unitario? – Robert

+0

Stai dicendo che questa sarà sempre una pagina web è un dettaglio di implementazione ... non dovrebbe essere preso in considerazione nella progettazione. – CSharpAtl

risposta

1

La mia sensazione è che il livello aziendale sia l'unico posto in cui inserire i dati della sessione perché è parte della logica. Se lo si inforna nel livello di presentazione, se si cambia la posizione in cui sono archiviati i dati (si dice, non si desidera più utilizzare lo stato di sessione), effettuare una modifica è più difficile.

Quello che vorrei fare è che per tutti i dati è lo stato di sessione, vorrei creare una classe per incapsulare il recupero di quei dati. Ciò consentirà modifiche future.

Modifica: l'interfaccia utente deve essere utilizzata solo per: 1. Chiamare al livello aziendale. 2. Interagisci con l'utente (messaggi ed eventi). 3. Manipolare l'oggetto visivo sullo schermo.

Ho sentito persone considerare l'accesso ai dati di sessione come parte del livello dati e questo è semantico e dipende da ciò che si considera il livello dati.

+7

Ho sempre pensato al livello aziendale come a una serie di funzionalità per risolvere il "problema effettivo dell'utente". Ad esempio, supponiamo di creare un'applicazione per convertire i file .doc in .pdf. Si desidera fornire questo come un'app della riga di comando (1 utente alla volta) e un'app Web (molti utenti alla volta). Una buona incapsulamento consentirebbe di rilasciare completamente lo stesso livello di logica aziendale in entrambi. Non vedo come ciò funzionerebbe con un oggetto Session all'interno, poiché non è applicabile all'implementazione della riga di comando. – AndreiM

+0

tehblanx, guarda il mio commento al corpo della domanda. la mia app non verrà mai eseguita da nessuna parte ma da una pagina Web. – sarsnake

+0

Questo è il dettaglio dell'implementazione ..... non il design .... – CSharpAtl

3

Smells divertente per me. Forse hai bisogno di un livello di presentazione per gestire la sessione e qualsiasi altra informazione di stato?

+1

+1, trovo che progettare un livello di visualizzazione senza stato con un livello di presentazione stateful promuova la separazione di _business logic_ dalla _presentation logic_. L'ultimo dei quali dovrebbe essere l'unica logica a conoscenza della sessione. –

+0

questo è un modo per farlo, Michael. – sarsnake

+0

in realtà è quello che avevo in mente inizialmente. – sarsnake

0

Se si mantengono i tre livelli elencati, il livello 'Business' sarebbe probabilmente il più adatto per gestire gli oggetti Session.

Poiché una sessione ha più a che fare con il framework reale che unisce l'applicazione insieme che con qualsiasi logica di business, è possibile creare un livello di controllo che traduca i dati dall'oggetto Session agli input dei dati aziendali al livello aziendale.

3

Penso che la logica di business non dovrebbe essere legata a una scelta di presentazione, e se Session vive in quel livello sarà legato.

3

ritengo l'uso non necessario di sessione per essere un odore di codice in generale, spesso querystrings, biscotti e ViewState sono lighterweight e hanno una migliore 'portata'

Quanto al ruolo di sessioni in un business di livello, dipende da quello architettonico guru stai leggendo in questo momento Se il livello della logica di business è un posto per codice indipendente dall'interfaccia utente, la Sessione non è una cosa da introdurre nel livello aziendale.

Ad esempio, in un'app Console, un'app Web ASP.NET, un servizio Windows e un'app Windows Form - solo ASP.NET ha una sessione.

Detto questo, essere in grado di supportare più UI è una funzione altamente sopravvalutata e non ci vuole una previsione perfetta per stimare se porterete mai la vostra app a un'interfaccia utente diversa. Se sei assolutamente sicuro che la tua logica verrà eseguita solo in un'applicazione ASP.NET da ora e per sempre, allora va bene.

Un'eccezione sarebbe il test dell'unità. nUnit test runner costituisce un'interfaccia utente diversa ed è difficile simulare richiesta, risposta, sessione, applicazione, ecc.

5

No. Se si dispone di un livello "Controller", è necessario accedervi. Ottieni ciò che ti serve dalla Sessione e consegnalo al tuo livello aziendale.

0

Penso che dipenda dall'utilizzo, ma sì, abbiamo accesso alla sessione dal nostro livello aziendale tutto il tempo. Anche qui c'è un argomento "purezza contro realtà".

Ad esempio, nella nostra applicazione abbiamo un database per client, ma una base di codice. Quindi abbiamo le informazioni del cliente nella sessione per ogni utente. Certo, potremmo quindi estrarre i dati dalla sessione nel livello Web e quindi trasferirli al livello aziendale. Naturalmente, il livello aziendale non se ne preoccupa, ma è necessario dal livello dati per connettersi al database corretto. Quindi il livello aziendale dovrebbe passare al livello dati. Sembra un sacco di parametri che passano senza buoni motivi commerciali. Nel nostro caso il nostro livello dati controlla l'oggetto di sessione per la stringa di connessione e viene eseguito da lì. Abbiamo codificato intorno al problema di non avere la sessione se non è una web app (e abbiamo servizi di Windows e applicazioni helper exe) come segue:

protected virtual string GetConnectionString() 
{ 
string connectionString; 
string connectionStringSource; 

//In app.config? 
if (ConfigurationManager.AppSettings[_ConnectionStringName] != null && 
    ConfigurationManager.AppSettings[_ConnectionStringName] != "") 
{ 
    connectionString = ConfigurationManager.AppSettings[_ConnectionStringName]; 
    connectionStringSource = "Config settings"; 
} 
//Nope? Check Session 
else if (null != HttpContext.Current && null != HttpContext.Current.Session && 
    null != HttpContext.Current.Session[_ConnectionStringName]) 
{ 
    connectionString = (string)HttpContext.Current.Session[_ConnectionStringName]; 
    connectionStringSource = "Session"; 
} 
//Nope? Check Thread 
else if (null != System.Threading.Thread.GetData(
     System.Threading.Thread.GetNamedDataSlot(_ConnectionStringName))) 
{ 
    connectionString = (string)System.Threading.Thread.GetData(
      System.Threading.Thread.GetNamedDataSlot(_ConnectionStringName)); 
    connectionStringSource = "ThreadLocal"; 
} 
else 
{ 
    throw new ApplicationException("Can't find a connection string"); 
} 

if (debugLogging) 
    log.DebugFormat("Connection String '{0}' found in {1}", connectionString, 
      connectionStringSource); 

return connectionString; 
} 
0

Accedere alla sessione dal livello di attività è sicuramente un odore di codice.

Se è necessario 'passare' il livello aziendale come indicato, il livello di presentazione o il controller è tutto ciò che deve preoccuparsi di ciò che è la variabile di sessione.

Ad esempio, si supponga di voler utilizzare un set di oggetti per una variabile di sessione e un altro per un'altra variabile. Il controller potrebbe chiamare un livello di servizio e passare la variabile. Il livello di servizio restituirebbe quindi l'oggetto business appropriato.

Il livello aziendale non conosce nulla sulla sessione nello stesso senso in cui il livello di presentazione non ha alcuna conoscenza aziendale su come ci si connette al DB.

+0

vedere il mio commento: il passaggio non è un problema, ma capisco il punto. è una questione di purezza contro realtà. – sarsnake

0

L'oggetto di sessione è legato a un'implementazione specifica dell'interfaccia utente, quindi avere un livello aziendale morto per la sessione è un odore.

Inoltre, probabilmente dovresti essere in grado di testare l'unità del tuo livello aziendale - come hai intenzione di farlo se ci sono dipendenze su una sessione?

5

Sigh.

L'ampio consenso sarà no; il livello aziendale e il controller/livello web dovrebbero essere mantenuti in modo diverso, perché sono preoccupazioni separate.

Il fatto è che sembri etichettare questa come una questione di "purezza contro realtà" che è incredibilmente miope e leggermente antipatica. Sfida anche il punto di porre la domanda; se non hai intenzione di considerare le opinioni che vengono presentate, allora perché sollecitarle?

È vero che separare le cose un po 'più attentamente in anticipo richiede uno sforzo più immediato, più tempo e, in definitiva, può costare un po' di più. È anche vero che potresti non essere in grado di percepire alcun beneficio immediato dal farlo. Tuttavia, una serie di storie di singhiozzo condivise da un numero enorme di programmatori per diversi decenni suggerisce che, ove possibile, la cosiddetta "purezza" riduce il dolore quando, cinque anni dopo la linea; Perbacco; devi davvero ridiscendere e fare un po 'di refactoring, e non è remotamente piacevole a causa di tutte le fessure attraverso le quali le tue responsabilità si stanno infiltrando.

Un modo leggermente migliore di immaginare i livelli di un'applicazione Web potrebbe essere la presentazione, l'interazione, le regole e i dati aziendali; da cima a fondo. I tuoi dati sono il database, l'accesso ai dati, ecc. E le regole aziendali impongono ulteriori vincoli su quei dati, gestiscono l'offerta, il calcolo, ecc.L'interazione quindi si dirama tra il livello di presentazione (che in pratica è l'interfaccia utente) e la logica aziendale, eseguendo i casi d'uso che guidano l'applicazione.

Fino a questo punto, l'interfaccia utente è irrilevante; non importa se l'utente inserisce, ad esempio, i dati dei clienti in un'applicazione della riga di comando o naviga in un modulo Web di più pagine con i dati memorizzati nella sessione. Diciamo che prendi quest'ultimo; attaccare un front-end web su di esso. Ora quello che ti interessa è scrivere codice relativamente semplice per gestire il recupero dei dati richiesti e presentarli all'utente. Il punto è, la tua applicazione web; il front-end, che è l'intera interfaccia utente; sessioni e tutto Solo nel momento in cui sei pronto a dire "hey, inseriamo i dati dei clienti nel database" vai e invoca quei livelli di servizio così amorevolmente creati, passando ogni bit di informazione che la tua applicazione web ha nascosto; l'input dell'utente, il nome dell'utente che effettua la modifica; tutta quella merda. E il tuo livello di servizio si occupa di esso. O, in alternativa, le femmine perché hai dimenticato un campo obbligatorio.

Poiché hai separato in modo pulito le cose, il coraggio della tua applicazione può, come altri hanno suggerito, essere rimodellato (o "preso in prestito") da utilizzare in qualsiasi altra applicazione, e il livello di servizio rimane, apolide, pulito, e pronto a gestire le cose. E fa la tua convalida, e così la tua convalida è costante ovunque. Ma non sa chi ha effettuato il login nel front-end web, o l'applicazione console, o l'applicazione rich client fancy in esecuzione su un terminale, e non gli interessa, perché quel dettaglio è importante solo per quelle applicazioni.

È necessario aggiungere una nuova regola di convalida? Nessun problema; fare in modo che il livello di servizio esegua la convalida e gestire i problemi dell'interfaccia utente secondo necessità più in alto nella catena. Hai bisogno di cambiare il modo in cui viene calcolato qualcosa? Cambia quello al livello aziendale. Nient'altro deve essere influenzato.

+0

Totalmente d'accordo qui. Il livello di servizio è fondamentale per la manutenibilità. –

Problemi correlati