Business Logic vs Presentation / View Logic

1

Spesso mi interrogo su dove mettere la logica che organizza i dati su una vista che non è necessariamente una logica di business in un'architettura a 3 strati (DAO, Business, View).

Metto un esempio per essere più chiaro:

Ho un'interfaccia utente nella mia applicazione che mostra i ticket in sospeso e i ticket con risposta in due schede diverse. Per ottenere i dati dal database, faccio una singola query. Poiché non esiste una logica aziendale, restituisco l'intera lista al Controller (Visualizza) e la separo in due elenchi per passare al modello di visualizzazione.

Dovrei separare questo nel livello aziendale? O è corretto separare nel controller, poiché la logica è collegata a quella singola UI?

    
posta Migore 17.07.2014 - 03:12
fonte

3 risposte

3

Mi piace dove stai andando con questa curiosità, quindi vado a far apparire qualcos'altro che vedo.

Per seguire non solo "Separation of Concerns", ma anche "Persistence Ignorance", è quasi sempre un'Idea molto cattiva per consentire al tuo strato UI di chiamare nel tuo business / data side con un "Get All" (O anche chiudi) metodo. Mi rendo conto che potrebbe esserci un vincolo o due come Where UserId == LoggedInUser , ma è ancora troppo vicino.

La ragione è che, all'improvviso, hai sviluppatori UI intelligenti che utilizzano il metodo "Ottieni tutti" e eseguono la logica di business / accesso ai dati sull'interfaccia utente per separare le informazioni, selezionare e filtrare, ecc.

Anche se dici a te stesso che non succederà mai, o che sarai l'unico nei prossimi 100 anni a toccare questo codice e Prometti a te stesso non lo farai mai, tu ancora non dovrebbe aprire l'interfaccia utente a tale potenza.

Ora immagina che in futuro un singolo Controllo dell'interfaccia utente debba visualizzare SEMPRE i biglietti con risposta (o in attesa). Cosa fai adesso? Devi "Ottenere tutti" ed eseguire la logica di filtraggio nell'interfaccia utente?

Non l'avrei nemmeno inserito nella Business Logic. Si tratta della separazione dei dati. Dovresti avere query più limitate possibili nel tuo livello di accesso ai dati ed esporre solo i risultati richiesti alla tua business logic. La tua logica aziendale in questo caso potrebbe essere solo un wrapper per restituire un risultato di accesso ai dati, ma va bene. È responsabilità della BLL determinare l'oggetto Persistenza e instradare le chiamate.

Ora, se hai bisogno di un elenco sul lato dell'interfaccia utente che mostri "Tutti" i ticket per un utente, potrebbe essere prudente avere il metodo "Ottieni tutto" in cui l'unico filtro è l'ID utente. Tuttavia, potrebbe essere più prudente combinare le query in sospeso e quelle con risposta. Perché?

Che cosa succede se in futuro aggiungi un elemento "Eliminato", "Rimosso", "In-Flux", "Nuovo" o qualsiasi altro tipo di stato? Ora devi riscrivere il codice perché tutto ciò che volevi fare è mostrare una lista combinata di domande in sospeso e risposte.

Quindi dai alla tua interfaccia utente meno controllo su elenchi massicci, e invece permetti di recuperare solo le informazioni limitate di cui ha bisogno e alterare / combinare da lì.

    
risposta data 15.10.2014 - 21:54
fonte
0

Se ho una definizione di modello denominata Ticket, allora inserirò la funzione di livello di classe in quella classe per fornirmi una raccolta di istanze di Ticket.

Esempio:

class Ticket
    # these are class level function, you call them like this
    # array_of_pending_tickets = Ticket.pending_tickets(2)
    def self.pending_tickets(category_id)
        # do the query to get pending tickets here
        # and return an array of new Ticket instances
    end
    def self.answered_tickets(category_id)
        # do the query to get only answered tickets here
        # and return an array of new Ticket instances
    end
    # this is an instance level function, you call it like this
    # ticket_im_working_on = array_of_pending_tickets[0]
    # ticket_im_working_on.mark_as_answered('hello world')
    def mark_as_answered('comment')
        # the instance of the Ticket class should have some
        # kind of internal instance variable like @id that 
        # you can use to modify the database
    end
end

Una volta definito il modello in questo modo, si utilizza il controller per eseguire la funzione del modello corretta (ad esempio, se si dispone / sospendi / category_1 come url, analizzarlo nel controller e quindi ottenere la variabile), quindi una volta ottenuti i dati è necessario utilizzare la vista per visualizzarli (utilizzando un ciclo sull'array da Ticket.pending_tickets (1)).

    
risposta data 17.07.2014 - 05:57
fonte
0

Considera T-SQL. Puoi interrogare un database usando qualunque cosa abbia senso le clausole.

Non vedo alcun motivo per cui il livello del database non possa eseguire query in base a criteri. Non costruirò il semplice filtraggio come un mix di logica aziendale e logica del database. Se ottieni una separazione di preoccupazioni solo per lanciare prestazioni fuori dalla finestra, non c'è vittoria.

    
risposta data 15.09.2014 - 17:18
fonte

Leggi altre domande sui tag