GenericDynamicSpxForm e WebSimplexTabs

Spesso per rendere una maschera (Form) più compatta si distribuiscono i controlli su più pannelli o View sovrapposti, selezionabili attraverso delle linguette o Tabs.

Il Framework Simplex offre una collezione di User Controls denominata WebSimplex. Tra i controlli di questa collezione vi è WebSimplexTab che implementa un gruppo di linguette (Tabs) associato ad un controllo MultiView: selezionando una linguetta è possibile portare in primo piano il corrispondente pannello-contenitore View della MultiView associata.

Interagire con un controllo ASP.NET MultiView non è facile, specialmente per quanto riguarda la lettura dei dati contenuti nei controlli della maschera che non si trovano nella View in primo piano. Se non si fa attenzione è possibile leggere dei valori null sebbene, interagendo con il controllo MultiView, tutti i suoi controlli risultino visibilmente popolati. Questo perché i controlli MultiView e View sono di tipo “server” ed i campi della View in primo piano, cioè quella visibili a video, sono gli unici effettivamente disegnati dal browser; gli altri semplicemente non esistono (in realtà vengono conservati in un’area denominata ViewState che altro non è che una stringa compressa binaria che viene passata dal browser al server nel corpo della richiesta http come valore di una coppia chiave-valore).

In molti hanno riscontrato (e risolto) questa issue (vedi gli approfondimenti in fondo all’articolo).

Questa issue si risolve abbastanza facilmente usando gli strumenti del Framework Simplex. La tecnica è questa:

  1. Immediatamente prima che venga variata la visualizzazione della View in primo piano, a seguito della selezione di un’altra linguetta (Tab), il contenuto dei suoi controlli viene copiato nell’oggetto di classe SQLTable che usiamo per la persistenza dei valori.
  2. Quando infine viene salvato nel database l’oggetto di classe SQLTable che usiamo per la persistenza dei valori, vengono copiati nell’oggetto solo quegli attributi che corrispondono ai controlli della View in primo piano, gli altri no.

Per copiare nell’oggetto SQLTable solo i valori dei controlli della View che sta per lasciare il primo piano, come indicato nel precedente punto 1, è sufficiente definire il metodo gestore dell’evento BeforeTabChange del controllo WebSimplexTabs, dichiaralo come delegato di tipo WebSimplex_BeforeTabChangeHandler e registrarlo.

Ecco fatto.

In pratica.

Se questo è il metodo, definito in una maschera derivata dalla classe GenericDynamicSpxForm, che dovrà gestire l’evento BeforeTabChange:

protected void selectionChangeOnTab(Object p_sender, EventArgs p_e)
{
        WebSimplex.WebSimplexTabs _trgt = (WebSimplex.WebSimplexTabs)p_sender;
        MultiView _mw = null;
        View _vw = null;

        if (_trgt != null)
        {
            _mw = _trgt.AssociatedMultiView;
            if (_mw != null)
            {
                _vw = _mw.Views[_mw.ActiveViewIndex];
                if (_vw != null)
                {
                    copyValues(TBL_UNDER_FORM, _vw.ID, "System.Web.UI.WebControls.View");                        
                }
            }
        }
}

in fase di caricamento (Page_Load) della maschera tale metodo gestore dovrà essere dichiarato come delegato e registrato, appunto, come gestore dell’evento BeforeTabChange.

protected override void Page_Load(object sender, EventArgs e)
{
            base.Page_Load(sender, e);
            #region DELEGATO DI GESTIONE DEI TABS
            WebSimplex.WebSimplexTabs _wst = (WebSimplex.WebSimplexTabs)R_Dynamic.FindControl("R_DynamicTABS");
            if (_wst != null)
            {
                // _wst.ChangeTab += new WebSimplex_ChangedTabHandler(this.selectionChangeOnTab);
                _wst.BeforeTabChange += new WebSimplex_BeforeTabChangeHandler(this.selectionChangeOnTab);
            }
            #endregion
// ... altro ...
}

Infine, il gestore dell’evento _Click() che salva l’oggetto TBL_UNDER_FORM di classe SQLTable dovrà eseguire quanto spiegato nel precedente punto 2.

        protected override void R_Salva_Click(object sender, EventArgs e)
        {
            //WRITE YOUR CODE FROM HERE

            #region SALVATAGGIO PRENDENDO I DATI DAI TABs
            try
            {
                MultiView _mvw = (MultiView)searchControl(R_Dynamic, "R_DynamicMultiView", "System.Web.UI.WebControls.MultiView");
                View _vw = null;
                //<added @MdN: 30/11/2020>
                if (_mvw != null)
                {
                    _vw = _mvw.Views[_mvw.ActiveViewIndex];
                    if (_vw != null)
                    {
                        this.copyValues(TBL_UNDER_FORM, _vw.ID, "System.Web.UI.WebControls.View");
                    }
                }
                //</added @MdN: 30/11/2020>

                TBL_UNDER_FORM.save(true);
            }
            catch (simplex_ORM.Spx_ORMMessage _ORMM)
            {
                // Messaggio di errore
            }
            #endregion

            Session.Add(MyName, TBL_UNDER_FORM);
           
            // Operazioni conclusive
        }

Questo è quanto.

Per approfondire sul controllo MultiView: https://docs.microsoft.com/it-it/dotnet/api/system.web.ui.webcontrols.multiview?view=netframework-4.8

Per approfondire sul controllo View: https://docs.microsoft.com/it-it/dotnet/api/system.web.ui.webcontrols.view?view=netframework-4.8

Per approfondire sulle issues del controllo MultiView: http://codeverge.com/asp.net.custom-server-controls/multiview-in-compositecontrol/91887

https://forums.asp.net/t/2056315.aspx?Howto+keep+state+in+User+Controls+in+a+MultiView

Per approfondire sulla ViewState: https://www.aspitalia.com/articoli/asp.net/viewstate.aspx

02/12/2020

Michele de Nittis

Variabili di sessione

In Simplex lo stato dell’applicazione viene conservato nella Session. In questa sezione le variabili di sessione più usate.

Generali

APPLICATION

Contiene un oggetto di classe GeneralApplication.GeneralApplication, o di una sua classe derivata, che rappresenta l’istanza corrente dell’applicazione. La classe incapsula tutte le informazioni che sono funzionali all’esecuzione dell’applicazione come, a titolo indicativo e non esaustivo, le connessioni ODBC, alcuni parametri “chiave”, l’utente corrente, etc. Generalmente viene memorizzata nell’attributo MyApp.

R_BreadCrumbs

Contiene un controllo ascx di classe WebSimplexBreadCrumbs che consente di visualizzare i passi di navigazione finora compiuti. Cliccando su uno dei passi si ritorna sulla relativa pagina. Il controllo è sempre il medesimo oggetto.

UNIF_User

Contiene l’oggetto di classe UNIF_User che rappresenta l’utente corrente, cioè quello che impiega l’istanza corrente dell’applicazione.

GenericSpxForm1.Panel_MessageBox.Visible

Contiene il valore booleano di visibilità della “finestra” che mostra un messaggio all’utente.

CALLING-PAGE

Contiene il “nome” della pagina che ha chiamato la pagine corrente. Nel framework Simplex il “nome” di una pagina coincide con il suo “Titolo”.

Specifiche (MyName + “_” + variabile)

Queste variabili di sessione hanno come prefisso il nome della pagina/maschera seguito dal carattere separatore “_”, come ad esempio MaskNameName_MYERRORS. Il nome della pagina/maschera è contenuto nell’attributo MyName.

_MYERRORS

Contiene la lista dei messaggi, cioè oggetti di classe Simplex_ORM.Spx_ORMMessage o di una classe derivata.

_FORMSTATE

Contiene lo stato della maschera. Lo stato della maschera è un oggetto di classe SimplexFormDictionary che è una collezione di elementi (SimplexFormEntry) aventi tre attributi principali: ID che corrisponde all’ID di un controllo web della pagina aspx, Text che è il valore di quel controllo e ctrlType che è il nome del “tipo” di quel controllo. Lo stato della maschera viene copiato in un oggetto SimplexFormDictionary mediante il metodo SimplexForm.saveFormState() e referenziato dall’attributo locale MyFormState. Tale metodo infatti, oltre a creare  l’oggetto di classe SimplexFormDictionary  che conserva lo stato attuale della maschera, lo referenzia mediante l’attributo MyFormState. Comunemente lo stato della maschera viene prelevato nel gestore R_Salva_Click(). Se usato, lo stato della maschera può essere recuperato dalla sessione nel metodo preloaEnvironmente() invocando il metodo SimplexForm.loadFormState(). Lo stato della maschera può essere mostrato nei controlli della maschera stessa invocando uno degli overload del metodo SimplexForm.show().

if (MyFormState != null)
    show(MyFormState, "R_Dynamic", "System.Web.UI.WebControls.PlaceHolder", null);

Aggiornamenti

30/04/2020: creazione articolo.

Simplex_ORM

Simplex_ORM è una libreria di classi che offre il servizio di gestione dell’interazione con il database di supporto all’applicazione.

Le classi raccolte nella libreria sono:

simplex_ORM.GenericObject Classe generica da cui derivano tutte le altre classi quali: – Columns; – Table; S
simplex_ORM.Column Classe che rappresenta una colonna di una tabella. S
simplex_ORM.Table Classe che rappresenta una tabella. S
simplex_ORM.Catalog Classe astratta che rappresenta il catalogo ad un database. Deve essere implementata una classe di questo tipo per ogni tecnologia Database. A
simplex_ORM.iLookupBrowser Interfaccia dell’oggetto LookupBrowser che consente di ottenere, data una chiave, il relativo valore. I
simplex_ORM.Spx_ORMMessage Messaggio per comunicare situazioni anomale. S
simplex_ORM.SQLSrv.SQLCatalog Implementazione di Catalog per la tecnologia MS SQL Server. D
simplex_ORM.SQLSrv.SQLColumn Implementazione di Column per la tecnologia MS SQL Server. D
simplex_ORM.SQLSrv.SQLTable Implementazione di Table per la tecnologia MS SQL Server. D
simplex_ORM.SQLSrv.SQLLookupBrowser Implementazione di SQLLookupBrowser per la tecnologia MS SQL Server. D
simplex_ORM.SQLForeignKey Classe che rappresenta un vincolo di integrità referenziale S 

Legenda

S Classe o Superclasse
D Classe derivata
I Interfaccia
A Classe astratta

La superclasse Catalog e le sue derivate conservano le connessioni con il catalogo del database e gestiscono la corrispondenza dei tipi .NET con i tipi di dati del database.

La superclasse Column e le sue derivare rappresentano una colonna di una tabella. Un oggetto di classe Column (o di una sua classe derivata)  effettua una lettura del catalogo per estrarre informazioni relative ad una data colonna di una data tabella. Tale oggetto, poi, usa le informazioni ricavate dal catalogo (es. nome, tipo di dato, se la colonna è chiave primaria, se ammette valori nulli, se è autoincrementante, se ha un valore di default, etc.) per accedere alle informazioni contenute in quella colonna nell’ambito di un particolare record della tabella data. La superclasse Column, inoltre, fornisce alcuni metodi di utilità statici e pubblici che consentono, tra le altre cose: di determinare il tipo di una stringa; di convertire una data in formato SQL-92 e viceversa.

La superclasse Table e le sue derivate rappresentano una tabella. Un oggetto di classe Table (o di una sua classe derivata), tuttavia, può contenere soltanto un record  alla volta di quella tabella. Al momento è stata implementata solo la classe SQLTable, che deriva dalla Table ma è specifica per il sistema MS SqlServer. La classe SQLTable presenta metodi per il caricamento di un record dal database (load()), per la modifica di un record (update(), save()), per la creazione di un record (insert(), save()), per la lettura dei valori delle colonne (getVaue()) del record, per l’aggiornamento dei valori delle colonne (setValue()) del record. Il metodo save() identifica automaticamente se un record debba essere creato o aggiornato. Nel primo caso invoca insert(), nel secondo invoca update(). Dalle versioni  successive alla v. 1.1.0.9 la classe SQLTable offre un metdo che consente di ottenere un valore stringa in corrispondenza di una colonna numerica che rappresenta una chiave verso una tabella di lookup o di decodifica: decodeColumn().

Referencing_Referenced_Tables

Ad esempio:

  1. Caricare il record Key:=1 della tabella Referencing.

simplex_ORM.SQLSrv.SQLTable _record = simplex_ORM.SQLSrv.SQLTable.createSQLTable(MyODBCConnection, “Referencing”);

_record.setValue(“ID”, “1”);

_record.load();

  1. Per ottenere il valore del campo “Field 3”

_record.getValue(“Field3”);

che è uguale a 2.

  1. Mentre per ottenere il corrispondente valore decodificato:

_record.decodeColumn(“Referencing”, “Referenced”);

che è uguale a “Text 1”.

L’esempio mostra un’altra particolarità della classe Table e delle sue derivate: non è possibile istanziarne un oggetto con l’operatore new ma si deve usare il metodo statico createObject() a cui passare due parametri: una connessione ODBC aperta ed il nome della tabella con cui l’oggetto ORM deve interagire.

La classe LookupBrowser e le sue derivate rappresentano un meccanismo veloce per consultare una tabella come se fosse una hash table. Questo oggetto si crea a partire da un’istanza della classe Table da consultare, specificando la colonna che rappresenta il campo chiave e la colonna che rappresenta il campo valore. Richiamando quindi il metodo getValue() specificando la chiave si ottiene il corrispondente valore.

Data la seguente tabella, si mostri il contenuto dei primi 10 record col seguente frammento di codice:

LookupTable_WITHOUT_BORDERS

public static void Main(string[] args)

{
           testLookupBrowser();

}

public static void testLookupBrowser()
{
           String MyConnStr = null; <<<<<<<<<<<<<<
           String MyTabName = null;
           SQLTable _MyTable;
           SQLLookupBrowser _lkp = null;
           System.Data.Odbc.OdbcConnection _conn = null;
           MyConnStr = MyConnStr = “Driver={SQL Native Client};Server=UTENTE-PC\\SQLEXPRESS;Trusted_Connection=No;Database=Naponos;Uid=******;Pwd=******“;
           MyTabName = “LK_STATO”;
// apertura – opening

              _conn = new OdbcConnection(MyConnStr);
              _conn.Open();

         // istanziamento dell’oggetto ORM corrispondente ad LK_STATO

           _MyTable = simplex_ORM.SQLSrv.SQLTable.createSQLTable(_conn, MyTabName);

 // creazione del lookupBrowser

            _lkp = _MyTable.getLookupBrowser(“STATO”, “DESCRIZIONE”);

           if (_lkp != null)
           {
               for (int _t = 0; _t < 10; _t++ )
               {
                   System.Console.Out.WriteLine(“Alla chiave: ” +  _t + “ corrisponde la descrizone: ” + _lkp.getValue(_t));
               }
           }
           _conn.Close();
       }

Il risultato dell’elaborazione è il seguente.

SIMPLEX_ORM_TEST

Come si vede per le chiavi mancanti il metodo non ha risposto con una eccezione ma ha restituito un valore null.

La classe ForeignKey e le sue derivate, infine, forniscono oggetti che semplicemente consentono di ottenere informazioni sui vincoli di integrità referenziale tra due tabelle a tempo di esecuzione. Di seguito un esempio:

try

{
   MyCat = new SQLCatalog(MyConnStr);
    MyCat.openCatalog();
    MyTable = MyCat.createTable(MyTabName);  
    MyFK = MyTable.getForeignKey(MyColumnName);

    if (MyFK == null)
              System.Console.Out.WriteLine(“La colonna non ha vincoli”);
    else
     {
      System.Console.Out.WriteLine(“La colonna HA il vincolo ” + MyFK.ConstraintName + “ di ” + MyFK.ColumnsCount + ” colonne.“);
     }
     System.Console.Out.WriteLine(“— DESCRIZIONE —-“);
     if (MyFK != null)
      {
          for (int t = 0; t < MyFK.ColumnsCount; t++)
           {
               System.Console.Out.WriteLine(“La colonna ” + MyFK.ReferencingTable.Name + “.” + MyFK.ReferencingColumns[t] + “ fa riferimento a –> ” + MyFK.ReferencedTable.Name + “.” + MyFK.ReferencedColumns[t]);
           }
      }
      else
           {
               System.Console.Out.WriteLine(“— NESSUN VINCOLO —-“);
           }
       }
catch (Spx_ORMMessage E)
       {
        System.Console.Out.WriteLine(E.ToString());
        ToInsert = true;
       }
System.Console.Out.WriteLine(“ — END — : ” + DateTime.Now.ToString());

Simplex FORM

Simplex FORM è una libreria di classi a supporto delle funzionalità che stanno alla base di tutte le maschere applicative che è possibile costruire con il framework Simplex.

Le classi sono:

  1. SimplexBreadCrumb: è la classe a supporto del controllo web che mostra l’attuale albero di navigazione tra le maschere di un’applicazione. Un oggetto della classe rappresenta un ramo di navigazione percorso.
  2. SimplexBreadCrumbs: Classe che rappresenta una collezione di oggetti di classe SimplexBreadCrumb, cioè l’albero di navigazione vero e proprio.
  3.  SimplexForm: Classe base (o superclasse) dalla quale derivano tutte le maschere del framework Simplex. E’ una specializzazione della classe Page appositamente progettata per operare con gli oggetti delle classi della libreria simplex_ORM. Le informazioni gestite da una maschera derivata da SimplexForm possono risiedere o in un oggetto ORM (vedi simplex_ORM) se è prevista la loro conservazione in un database, o in un oggetto di classe SimplexFormDictionary qualora debbano semplicemente essere riutilizzate nella maschera stessa o in un’altra maschera. Nel paragrafo che segue verrà approfondita questa classe.
  4. SimplexFormDictionary: Classe Dictionary (implementa IDictionary, IEnumerable) che colleziona triplette di informazioni (ID, Text, Type) che rappresentano rispettivamente l’ID di un controllo web, il valore della proprietà Text di tale controllo web ed una stringa che descrive il tipo di tale controllo web. Le triplette possono, ovviamente, essere usate anche per memorizzare qualsiasi tipo di informazione come in una normale collezione Dictionary.

Classe SimplexForm (Approfondimento)

GenericSpxForm
La classe SimplexForm è la classe base per l’interfacciamento cioè è la classe base per il modello code-behind delle maschere del framework Simplex. Deriva da Page ma non è dotata di elementi grafici o di un proprio codice aspx. La classe supporta, attraverso la variabile di riferimento notevole TBL_UNDER_FORM, un oggetto di classe Simplex_ORM.Table e fornisce metodi per caricare lo stato dell’oggetto da un record di una tabella, mostrare a video nella maschera lo stato dell’oggetto, modificare lo stato dell’oggetto secondo quanto inserito nella maschera, salvare in un record di una tabella lo stato dell’oggetto.

TBL_UNDER_FORM è solo uno degli oggetti che formano lo stato di una maschera del framework Simplex. Il caricamento dello stato di una maschera avviene in fase di caricamento della maschera mediante il metodo preloadEnvironment() che è il primo metodo invocato dal gestore di evento Page_Load().

Nelle versioni più recenti è stata aggiunta la variabile notevole MAIN_UNDER_FORM che fa riferimento all’oggetto Simplex_ORM.Table supportato da un’eventuale maschera chiamante.

In Simplex lo stato di una maschera viene conservato principalmente in sessione. L’uso del ViewState per questo scopo è marginale (e desueto, cioè è presente solo nelle prime versioni di Simplex_FORM).  La Collection Session viene, quindi, usata per la conservazione dello stato e per il passaggio di informazioni ed oggetti tra la maschera chiamante e la maschera chiamata. Non solo. Ogni maschera di Simplex può accedere alle informazioni generali dell’applicazione attraverso un oggetto di classe GeneralApplication conservato in sessione. L’oggetto Session, quindi, è un oggetto fondamentale per il funzionamento di un’applicazione realizzata con Simplex.

SimplexForm non ha una propria visualizzazione e pertanto non è previsto che si possano aggiungere controlli web al suo interno. Per creare una maschera basata su SimplexForm è necessario usare una sua sottoclasse. La sottoclasse di derivazione diretta è GenericSpxForm, argomento di un dedicato articolo.

Storia delle Versioni

Versione Data Modifiche Dll Help Sorgente
v.1.2.0.3 26/05/2018 – Corretto il BUG su getElement()

– Cambiato il tipo restituito dal metodo “this[String p_Key]”.

Download

Gli elementi del framework: Le Regole

Affinché un’applicazione sviluppata con Simplex funzioni devono essere rispettate alcune regole di progettazione e di implementazione:

  1. [MUST]: Il database deve essere progettato in modo consistente, cioè in terza forma normale e con tutti i vincoli intrarelazionali ed interrelazionali implementati mediante i costrutti del modello relazionale (ad esempio per il modello relazionale devono essere definiti tutte le chiavi primarie, tutti le chiavi esterne ed i vincoli di integrità referenziale, tutti gli indici ed i vincoli di unicità necessari).
  2. [MUST]: Ogni tabella del database deve essere dotata delle colonne necessarie per determinare quando un record è stato creato (colonna DATA_SYS) e chi lo ha creato (colonna USR), quando un record è stato modificato (colonna DATA_UM) e chi lo ha modificato (colonna USR_UM), quando un record è stato cancellato logicamente (colonna DATA_DEL) e chi lo ha cancellato (di nuovo colonna USR_UM).
  3. [MUST]:Il database deve SEMPRE avere le Tabelle che verranno illustrate in un apposito paragrafo.
  4. [SHOULD]: Ogni operazione significativa dovrebbe essere tracciata nella tabella dei logs. Gli errori e le eccezioni gestite pure dovrebbero essere tracciate nella tabella dei log.
  5. [SHOULD]: Ogni classe, ogni metodo, ogni attributo, ogni proprietá dovrebbe essere adeguatamente commentata.
  6. [MUST]: Il passaggio delle informazioni tra una maschera e la successiva (anche se stessa) deve essere effettuato ricorrendo alla Session. Le informazioni di funzionamento di un’applicazione devono essere incapsulate in apposite classi. Le istanze di tali classi devono essere disponibili ai diversi moduli dell’applicazione nella sessione attiva.
  7. [SHOULD]: Le regole business dovrebbero essere implementate al livello della gestione dei dati, cioè nel DBRMS, mediante elementi di programmabilitá quali stored procedures, trigger, etc. Quando possibile ed utile sarebbe opportuno gestire in anticipo le violazioni delle regole business o a livello di presentazione mediante regole di validazione dei dati immessi o a livello di applicazione mediante apposite classi di controllo.
  8. [SHOULD]: l’applicazione web dovrebbe essere sviluppata con il criterio modulare. Nel progetto dell’applicazione .NET i sorgenti di ogni modulo applicativo dovrebbero risiedere in una sottocartella dedicata.;
  9. [SHOULD]: i nomi di ogni oggetto del database (tabelle, colonne, vincoli, stored procedure) ed ogni classe dell’applicazione dovrebbero essere semantici, cioè in  qualche modo significativi ed intellegibili.
  10. [SHOULD]: le maschere direttamente derivate dalla classe Page dovrebbero essere evitate.
  11. [SHOULD]: Ogni programma realizzato con Simplex dovrebbe essere composto da funzioni applicative, ossia moduli applicativi specifici per ogni aspetto applicativo gestito dal programma.
  12. [MUST]: Ad ogni maschera dell’applicazione DEVE corrispondere uno ed un solo record della tabella UTILS_Menu, anche se non è raggiungibile da alcun menu.

Introduzione al Framework Simplex

Il framework Simplex (brevemente Simplex) nasce con l’intento di rendere veloce ed omogeneo lo sviluppo di applicazioni web che fanno uso di un unico database.

L’impulso alla realizzazione del framework infatti deriva dalla necessitá di lavorare in una grande organizzazione dotata di molti programmi applicativi verticalizzati, cioè non cooperanti tra loro, sviluppati con diverse tecnologie, alcune delle quali tecnologicamente obsolete, e realizzati da team di sviluppatori che hanno impiegato ciascuno propri paradigmi e metodi. Questa condizione, unita alla mancanza di personale tecnico e di risorse sufficienti per la manutenzione e lo sviluppo innovativo, ha reso necessario la costruzione di uno strumento che consentisse lo sviluppo veloce di applicazioni web-based, che offrisse alcune funzionalitá di base, che raccogliesse l’esperienza maturata e la riproponesse per realizzare applicazioni modulari e facilmente manutenibili.

Le applicazioni sviluppate con il framework Simplex in modo corretto godono delle seguenti proprietà qualitative:

    1. Funzionalità: Dato che il framework si occupa di gestire correttamente le operazioni elementari CR.U.D., lo sviluppatore può dedicarsi alla realizzazione di funzioni il più possibile aderenti ai requisiti applicativi.
    2. Affidabilità: i modelli proposti dal framework sono operativamente collaudati e consolidati. Il rispetto delle best practies e delle regole che fanno parte del framework garantiscono un buon livello di recupero di informazioni a seguito di una perdita accidentale ed un buon grado di tolleranza agli errori.
    3. Correttezza e Robustezza: un programma realizzato con Simplex viene costruito partendo da Modelli applicativi ampiamente testati che forniscono un insieme di operazioni di base (creazione, modifica e cancellazione di record) che, se la progettazione del database rispetta i canoni e le regole previste, espletano correttamente il proprio compito intercettando e gestendo eventuali situazioni anomale.
    4. Manutenibilità: tutti i programmi realizzati con Simplex hanno la medesima struttura di base. Dunque é possibile individuare con facilitá i punti in cui introdurre codice correttivo o evolutivo. Inoltre il codice delle classi e dei modelli é commentato per facilitarne la comprensione. Tutti gli errori e le condizioni anomale, infine, vengono tracciate in una tabella dei logs in modo che sia possibile verificare le motivazioni per le quali l’applicazione presenta un eventuale comportamento non previsto.

Il framework Simplex è un insieme strutturato di elementi correlati tra loro. Tali elementi sono:

  1. Regole
  2. Classi
  3. Modelli
  4. Documenti
  5. Tabelle

Nei prossimi articoli verranno esaminati nel dettaglio gli elementi costitutivi del framework. Per usare al meglio il framework è necessario conoscere bene questi elementi e come ciascuno di essi si relaziona con gli altri.

Il framework puó essere usato sia intervenendo direttamente sul codice dei modelli TEMPLATE, sia attraverso un apposito programma applicativo denominato Simplex Form Builder, attualmente in fase di sviluppo.