Come progettare "Guida dell'utente configurabile"

5

Sto lavorando all'applicazione Windows Form. Recentemente, ho ricevuto nuovi requisiti che non so come affrontare.

  1. Gli utenti dell'applicazione avranno uno dei due ruoli: Amministratore o Utente .
  2. L'amministratore può impostare un elenco di istruzioni da eseguire quando si verificano situazioni diverse.
  3. Gli utenti normali (ruolo utente ), visualizzeranno una finestra popup con le istruzioni successive da eseguire per una situazione specifica.

Le istruzioni configurate da Amministratore sono come guida o guida per utenti normali e principianti. Quindi sanno cosa fare dopo senza disturbare il supervisore ( Admin ).

Ad esempio, la mia applicazione ha due pulsanti: Pulsante 1 e Pulsante 2. Amministratore può inserire questa istruzione:

  • Se il pulsante 1 ha fatto clic = > Messaggio: "Fare clic sul pulsante 2"
    • Se il pulsante 2 ha fatto clic su == > Messaggio: "Invia email a xxx"
  • Se il pulsante 2 ha fatto clic su & & ora > mezzogiorno = > Messaggio: "Fai clic sul pulsante 1 per primo"
  • Se il pulsante 2 ha fatto clic su & & time < = mezzogiorno = > Messaggio: "Invia email a yyy"
  • ...

Voglio solo dare un semplice esempio per chiarire le cose, ma, in realtà, devo gestire centinaia di casi per coprire tutte le situazioni. Stavo pensando di creare una tabella di database contenente due colonne: Conditions e Message . Tuttavia, non riesco a vedere:

  1. Quale elenco di condizioni che un amministratore può vedere durante la configurazione
  2. Come combinare e salvare queste condizioni
  3. Come abbinare la colonna di stringa Conditions a un caso specifico in fase di esecuzione

    Qualche idea o suggerimento su come affrontare questo requisito?

posta Mhd 24.04.2017 - 18:22
fonte

3 risposte

3

Per condizioni complesse, potrebbe essere una buona idea progettare una lingua specifica per il dominio . Questo non ha bisogno di essere molto complesso, puoi provare se puoi soddisfare i tuoi requisiti usando

  • alcune funzioni atomiche (come "Button ('buttonTag'). IsClicked ()", "CurrentTime () > 'hh: mm'")
  • operatori booleani (AND, OR, NOT)
  • alcuni operatori di confronto per valori temporali o altri numeri
  • parentesi

Ora le tue condizioni saranno semplicemente un elenco di stringhe e potrai combinarle con i relativi messaggi come coppie di stringhe.

What list of conditions an Admin can see while configuring

Nella forma più semplice, l'amministratore ha solo un controllo editor di testo per l'inserimento delle condizioni (e dei relativi messaggi). Puoi mostrargli una finestra di supporto in cui può scegliere i tipi di condizioni atomiche disponibili per il modulo specifico.

How to combine and save these conditions

L'amministratore li combina come preferisce e vengono salvati come un elenco ordinato di coppie di stringhe (una stringa per la condizione e una per il messaggio).

How to match the Conditions string column to a specific case at run-time

Questa è la parte più difficile - è necessario creare un interprete per la condizione DSL (che è, per semplici DSL, più facile come potrebbe sembrare a prima vista, per esempio qui ). Ogni volta che si verifica un evento in cui una delle condizioni potrebbe essere soddisfatta, eseguire l'interprete sull'elenco completo delle condizioni, valutarle una dopo l'altra e non appena la prima condizione corrisponde, mostrare il messaggio correlato.

Sicuramente dovresti collegare il tuo interprete a tutti gli eventi cliccati sul pulsante del tuo modulo (che in realtà è piuttosto semplice in Win Form, dato che .NET supporta eventi multi cast e puoi facilmente iterare su tutti i controlli di un modulo). Nel caso in cui sia necessario consentire condizioni che vengono attivate solo a tempo, potrebbe essere necessario eseguire l'interprete anche automaticamente ogni minuto. A seconda degli altri eventi atomici (come un evento in cui un controllo ottiene l'attenzione) potresti anche collegarti a tutti questi altri eventi.

Naturalmente, c'è spazio per ottimizzazioni, è possibile escludere gli eventi di clic dei pulsanti che non sono presenti nell'elenco corrente di condizioni finora. È possibile eseguire in anticipo l'analisi (e il controllo della sintassi) delle condizioni, quando l'amministratore inserisce la condizione e memorizzare l'albero sintassi astratto, quindi quando si tratta di interpretare le condizioni, il programma non deve ripetere l'analisi.

    
risposta data 24.04.2017 - 21:52
fonte
0

Un database è una buona idea. Tuttavia, preferirei un semplice file XML, che farà il lavoro.

Informazioni sulle condizioni: forse il Regex aiuterà, ma io non la penso così. Inoltre, non conosco alcuna soluzione integrata adatta, quindi creerò la mia:

  • Crea una serie di classi, usando l'ereditarietà: CCondition della classe base, CTimeCondition derivata e simili.
  • Crea un CMessage di classe, che contiene i dati / testo da visualizzare e un elenco di condizioni. Nuova CCondition può essere aggiunta alla lista, quelli esistenti possono essere rimossi.
  • Avrai bisogno di una GUI per questo: crea un controllo utente UC-A, che contiene un elenco (di tabella con 2 colonne) dei messaggi. Quando viene selezionato un messaggio, mostra il testo e l'elenco di condizioni in un altro controllo utente UC-B, che è stato inserito in UC-A. Quando selezioni una condizione, mostra il suo contenuto in UCCondition.
  • Come le classi ereditate di CCondition, creerei un corrispondente set di UC, uno per ogni classe di condizione.
  • Aggiungi un metodo di creazione (modello di progettazione di fabbrica) in entrambe (U) CCondition, crea un EnumType all'interno di CCondition. Un valore enum di quell'EnumType viene quindi passato a create (), che restituisce la CCondition del tipo desiderato.
  • ...

Salvataggio in / caricamento da XML:

  • Vorrei aggiungere LoadFromXml () e SaveToXml () in ogni CCondition e in CMessage. (È così che leggo / scrivo dati di classe da / a Xml).
  • Basta scrivere l'intero XML in ogni operazione di salvataggio.

Questo è un approccio molto modulare (uno dei principi della programmazione orientata agli oggetti, che mi piace di più!), che ha molti elementi che puoi riutilizzare in altre situazioni.

Sentiti libero di chiedere altri consigli.

Modifica n. 1 La connessione tra queste condizioni e le azioni dell'operatore potrebbe essere, che l'azione dell'operatore (o qualsiasi tipo di evento nel programma) è una delle condizioni all'interno di CMessage.
Detto questo, penso che vorrei rinominare CMessage in CReaction e aggiungere una CAction (che è l'azione dell'utente o l'evento del programma).
I dati possono essere organizzati in molti modi diversi:

  • CReaction, contenente CAction e un elenco di condizioni.
  • Azione, tenendo premuto CReaction e un elenco di condizioni.
  • Dizionario di CAction (chiave) e CReaction (valore), ma questo limiterebbe a un mapping 1-a-1 tra CAction e CReaction. In alternativa metti un elenco di CReaction come valore nel dizionario ...
  • ... Qualunque sia la tua esigenza.

Quando si preme un pulsante o si verifica un altro evento, chiamare la funzione

  • consente di scorrere l'elenco delle CAle per trovare le voci pertinenti
  • quindi controlla tutte le condizioni di tutte le voci trovate
  • ed esegue tutti i CReaction della CAction con condizioni corrispondenti.
risposta data 24.04.2017 - 18:53
fonte
0

Da quanto ho capito, non hai bisogno di una struttura di scripting, hai solo bisogno di un dizionario di messaggi di suggerimento e una riga di hard code per ogni step / junction dell'utente nella tua applicazione. Come nel gestore di eventi click di button1, si chiama PresentHint che appare nel dizionario se è disponibile un suggerimento (la chiave potrebbe essere "Button1Clicked"). Se lo è, presenterà il suggerimento all'utente.

Come memoria, un file di testo normale con coppie chiave-valore farebbe. Xml sarebbe più flessibile, tuttavia, potresti voler aggiungere attributi al tuo oggetto suggerimento più tardi.

    
risposta data 27.04.2017 - 23:24
fonte

Leggi altre domande sui tag