Come separare la logica della mia applicazione in una dipendenza quando è accoppiato alla struttura dei dati?

3

Sto per iniziare la prototipazione di un'applicazione web simile a un quiz che mette alla prova le metodologie di valutazione dei test e ho un'interessante domanda architettonica.

Ogni quiz dato a un utente deve utilizzare una metodologia impostata per assegnarlo un punteggio (ad esempio calcolo delle formule, punteggio numerico destro, marcatura negativa, ecc.). Un quiz consiste in una serie di domande, poste una per una, il cui punteggio viene calcolato dopo ogni risposta alla domanda. Il punteggio del quiz dell'utente, tra le altre cose, viene utilizzato per selezionare la successiva domanda di difficoltà appropriata per il progresso dell'utente, da un pool di domande teoricamente infinite.

Al di là delle metodologie di punteggio utilizzate per calcolare il punteggio, l'aspetto "domanda successiva" del programma sarà piuttosto complesso; è strettamente accoppiato con la struttura dei dati (ad esempio, un utente dovrà rispondere a una medium -difficoltà domanda da X argomento ... e più criteri).

Vorrei separare la logica delle metodologie di scoring e l'aspetto "domanda successiva" dell'applicazione per mantenere semplice l'applicazione web. La libreria potrebbe accettare un insieme di input (ad esempio l'insieme di domande a cui l'utente ha risposto) e la metodologia da utilizzare per calcolare il punteggio corrente e selezionare la domanda successiva. Se apporto modifiche al codice della libreria che influisce sul calcolo del punteggio, il database presenta dati non corretti. Potrei ricalcolare tutti i punteggi dopo aver influito su tale cambiamento, ma ciò potrebbe causare confusione agli utenti che hanno già ottenuto i loro punteggi finali (questa è solo una speculazione, non so come sarà "aperto" un progetto).

Il problema è che la logica è, per quanto ho mappato finora, strettamente accoppiato alla struttura dei dati (ad esempio una domanda ha un elenco di argomenti, che potrebbero essere utilizzati per scegliere la domanda successiva) . Non solo, ma i risultati forniti dalla libreria devono essere memorizzati dal database per i test in corso e completati.

Vorrei anche rendere la logica dell'applicazione open source per scopi accademici, quindi separarla in una dipendenza renderebbe questo un po 'più semplice (non voglio necessariamente aprire l'applicazione web sorgente).

Come posso disaccoppiare questi dati dalla logica dei componenti in modo che io possa separarli come dipendenza?

Se necessario, posso eseguire una whiteboard sulla struttura e sugli obiettivi generali dell'applicazione e aggiornare la mia domanda per rendere più chiara la descrizione del mio problema.

    
posta Chris Cirefice 25.07.2016 - 07:41
fonte

4 risposte

2

Se questo problema fosse puramente in memoria, useremmo le tecniche OOP. Tuttavia, dato che stai provando a ottenere risultati di punteggio persistenti e probabilmente svilupperai nuovi metodi di punteggio e finder di domande successive che coinvolgeranno nuovo codice e riavvierai il tuo server, sembra indicato uno schema che si applica al tuo livello di persistenza.

Fondamentalmente, devi sviluppare e acquisire alcuni metadati per mantenere le cose dritte nel tuo database. Un pezzo di questi metadati è un'astrazione per il controllo delle versioni dei metodi di punteggio. E un altro è per catturare le dipendenze che i metodi della prossima domanda hanno.

Ad esempio, suggerirei uno schema di versioning immutabile, in cui è possibile fare riferimento al metodo di punteggio dalla coppia: nome e numero di versione e, ogni volta che si introduce un nuovo metodo di punteggio o una modifica del metodo di punteggio, si introduce un nuovo nome o utilizzare un numero di versione più grande. Pertanto, abbiamo un'astrazione stabile per l'identificazione di un metodo di punteggio, che ci consente di fare riferimento a più metodi di punteggio contemporaneamente.

Rendendosi conto che il tipo di output del metodo di punteggio può variare (ad esempio, dal singolo punteggio numerico su alcune scale, a più punteggi su più scale), potresti anche sviluppare uno schema per fare riferimento a quel tipo di punteggio (tipo di output del metodo di punteggio) .

Devi anche sviluppare un'astrazione per identificare le dipendenze per i cercatori di domande successive. Suggerirei di acquisire il set di metodi di punteggio richiesti e un insieme di tipi di output del metodo di punteggio per ogni finder di domande successive. (Al momento non sembra esserci un requisito per mantenere queste informazioni nel database, quindi c'è una grande varietà di metodi disponibili per catturare questo, che vanno dai dati memorizzati nel codice all'iniezione di dipendenza per la manipolazione esterna.)

Poiché sembra che tu non voglia che i punteggi degli utenti cambino dopo il primo rapporto, dovrai persistere positivamente solo il punteggio originale come riportato all'utente, o il metodo di punteggio originale (in modo che tu possa rigenerare quel punteggio per mostra all'utente).

È possibile scegliere di memorizzare in genere i risultati del metodo di calcolo del punteggio, ma rendersi conto che utilizzando lo schema di versione immutabile, è possibile lanciare questa cache e rigenerare secondo necessità. Se hai salvato i risultati nella cache, essi sarebbero della coppia: risultato e (riferimento o identità di) metodo di punteggio per ogni risposta data.

Avrai bisogno di un manager in grado di generare i risultati del punteggio richiesti per un determinato finder di domande successive, se non il caching, e se il caching, può rilevare l'assenza di determinati risultati del metodo di punteggio, e generare & cache quelli prima di utilizzare il finder.

    
risposta data 25.07.2016 - 22:06
fonte
0

La tua logica funziona sui dati, se non ha funzionato su nulla, sarebbe inutile.

Quindi la tua logica sarà abbinata ai tuoi dati; ma ciò non significa che debba essere accoppiato al formato esatto dei tuoi dati.

Ad esempio, ci sono molti diversi tipi di liste: matrici di oggetti, elenchi di numeri collegati, ecc. Per evitare che l'elaborazione orientata alle liste diventi troppo accoppiata all'implementazione di un elenco, il linguaggio Java rende List un'interfaccia. La logica quindi funziona sull'interfaccia Elenco, nascondendo i dettagli di come l'elenco viene implementato dalla logica.

Quindi la logica (algoritmo) funziona su un elenco generalizzato, con qualche implementazione specifica dell'elenco che viene aggiunto al mix più tardi.

Esistono altre tecniche, un modello di visitatore è un po 'più astratto rispetto all'esempio di elenco precedente, ma consente anche strutture di dati più complicate (come gli alberi).

Si noti che in un ambiente di programmazione orientato agli oggetti, la convinzione fondamentale è che i dati e la logica che sono "locali" per un'idea sono accoppiati insieme nella stessa classe. Consideralo attentamente, perché mentre approcci come quelli menzionati sopra a volte sono necessari, non dovrebbero mai essere la prima scelta per aggiungere la logica ai dati in un ambiente orientato agli oggetti. La prima scelta in un ambiente orientato agli oggetti consiste nell'aggiungere un metodo all'oggetto.

    
risposta data 25.07.2016 - 08:27
fonte
0

Penso che potrebbe essere utile implementare i requisiti con una fabbrica di classi statiche e diversi provider di classi per "impostare la metodologia per valutare".

La fabbrica si occuperà di selezionare il fornitore giusto in base a qualche scelta, ad esempio la complessità del quiz (basso, medio, alto, ecc.), i fornitori si preoccuperanno di eseguire i calcoli previsti.

Per fare ciò, è necessario progettare un'interfaccia con i metodi minimi per calcolare i punteggi, penso che dovrebbero essere necessari solo due metodi (ad esempio calculateScore() e getScore() , o meglio una proprietà Score ), quindi potresti implementare quanti provider della tua metodologia calcolare il punteggio come desideri, avendo come input es. una serie di risposte al quiz e la risposta giusta per ogni domanda di quel determinato quiz.

Quindi, il provider può elaborare quei dati per fare un calcolo del punteggio e assegnare un dato con il punteggio (decimale o una matrice di int).

Nel tuo codice cliente, puoi ottenere staticamente il giusto riferimento al fornitore chiamando la fabbrica con il cryterion di scelta (tipo di enumerazione) e assegna la sua interfaccia, quindi chiama il metodo calculateScore passandogli una matrice di risposte dei clienti e risposte giuste e poi ottenere il punteggio dalla proprietà dell'interfaccia.

Infine, potresti andare avanti con il tuo metodo "domanda successiva" ..

    
risposta data 25.07.2016 - 12:39
fonte
0

Il tuo progetto è un mostro di dati e come tale devi pensare prima in termini di progettazione del database. Sì, finirai per utilizzare un database.

  • La tua app sarà basata sui dati.
  • Penso che dovresti modellare attentamente un database.
  • Prendi tutto il tempo necessario in questo passaggio.
  • Converti la logica in dati in modo che il tuo codice sia così semplice come potrebbe essere.
  • Modella argomenti di database, difficoltà, criteri, domande, regole, tabelle decisionali, ecc.
  • Memorizza anche le formule in modo che il tuo codice possa applicarle. Dovresti essere in grado di modificare le formule in una tabella e il tuo codice non dovrebbe interrompersi.
  • Il tuo codice dovrebbe fare come i dati gli dice di fare.
  • Prima fai un ER concettuale e discuterlo MOLTO. Ottimizzarlo. Fai brain storming. Tracciala in un grande formato e falle rivedere da designer di database esperti.

Solo dopo averlo fatto, avrai un'idea migliore di quali strutture di memoria utilizzerai e inizi a modellare il tuo design OO.

Bottom-line:

Non pensare ancora al disaccoppiamento. Metti troppa intelligenza e dati in tabelle, tabelle decisionali, ecc. Così il tuo codice farà come il tuo database gli dice di fare.

    
risposta data 25.08.2016 - 01:17
fonte