STRUTTURA DEL PROGETTO E DEL DATABASE

 

I codici sorgenti di Gea.Net sono disponibili a richiesta. Per maggiori informazioni su come riceverli consultare http://www.fborghi.it. 

I codici sorgenti sono stati scritti in Visual Basic .NET pertanto per poterli modificare è necessario installare sul proprio computer Visual Studio .NET 2003 Professional.

Le due cartelle dove sono posti i sorgenti sono ..\GEANET e ..\CLASSNET con le relative sottocartelle. E’ sufficiente copiare queste due cartelle sulla radice del proprio disco C o in altra posizione assicurandosi di posizionarle in modo che siano “sorelle” (es. C:\GEANET e C:\CLASSNET ). Di seguito riporteremo “..\” per indicare la cartella padre.

Sia GEANET che CLASSNET si compongono di diversi progetti che analizzeremo meglio in seguito e sono racchiusi nella solution ..\GEANET\GEANET.SLN.

Pertanto per accedere ai sorgenti, dopo aver aperto Visual Studio, dovrà essere aperto “Apri Progetto” nel menu “File”, selezionando il file ..\GEANET\GEANET.SLN

Le altre cartelle distribuite assieme ai sorgenti sono raccolte di software ed esempi e non sono legate all’applicazione.

Nella cartella principale si trova anche un file zippato GEANETS[versione].ZIP che contiene i files da ridistribuire agli utenti finali.

 

ClassNet

La cartella CLASSNET contiene alcuni progetti che possono essere riutilizzati anche per solution diverse. Essi sono ripartiti per macroarea e non conoscono in alcun modo quella che è l’attività di business. Allo stesso modo NON conoscono il database e le form del progetto principale. Per mantenere portabili questi progetti non deve essere utilizzato al loro interno un riferimento diretto agli oggetti del progetto principale ma nel caso usare una classe generica o usare tecniche di reflection per accedervi.

 

Le sottocartelle di CLASSNET sono i progetti di cui esso si compone :

 

GeaNet

La cartella GEANET contiene i progetti che rappresentano l’attività vera e propria di Gea.Net.

I progetti che lo compongono sono :

 

Il seguente schema dovrebbe rendere più chiara la struttura e le dipendenze dei progetti

Per completezza dovrebbero essere inclusi nello schema precedente anche i moduli ClsB_BaseUC e ClsB_BaseUC_Gruppi. Queste due librerie sono utilizzate nello stile WPF a completamento di Cls_BaseForm .

 

Struttura del Database 

La struttura del database è piuttosto spartana. Nella sua configurazione di base non sono contenute relazioni, viste o stored procedure. Questa scelta rende portabile il database su qualunque piattaforma anche se il software è testato con SQLServer e Access. Se si vuole migrare ad un database diverso sarà sufficiente intervenire sul modulo Dbfunct della classe ClsB_Base che racchiude ogni funzione basilare di accesso al database ( apertura delle connection, gestione dei dataset, datareader, ecc. ).

Durante la stesura dell’applicazione si è tentato di utilizzare solo comandi SQL standard per rendere agevole la portabilità anche a database meno strutturati, tuttavia potrebbe essere necessario rivedere alcuni comandi nel momento in cui si volesse migrare a database diversi da SQLServer e Access. 

Naturalmente questa scelta strutturale estremamente semplice penalizza le prestazioni della applicazione. Per rendere più performante il software si consiglia di integrare stored procedure rivedendo alcuni metodi interni alle classi di business.  

La struttura delle tabelle rispecchia a grandi linee la struttura delle classi concentrando all’interno di una unica classe eventuali tabelle master-details. Per aiutare la comprensione si è fatto uso di prefissi per cercare di organizzare logicamente le tabelle anche se non esiste un disegno di relazioni per non compromettere la portabilità del database.

La scelta progettuale di non rendere vincolante un particolare database ha comportato che non fossero utilizzati campi identità o tipi di campi proprietari come i campi oggetto.

 

Componenti dell’applicazione

In questa sede è difficile poter analizzare in dettaglio ogni singola funzione. Lo scopo che ci si prefigge con questa breve guida è di dare una infarinatura sui componenti del software e l’utilizzo che ne viene fatto. Il dettaglio sulle modalità operative delle singole funzioni, quando non espressamente palese, è documentato all’interno del codice stesso con esempi sull’utilizzo.

Si ricorda che le librerie presenti in ClassNet sono astratte e possono essere utilizzate in progetti diversi. Non troverete e non dovete inserire riferimenti espliciti al database o all’applicazione in uso. Ogni nome (connectionstring, nome di tabelle e di campi) deve essere agganciato dall’esterno come parametro o proprietà o acquisito da file di configurazione esterno.

Per le librerie di seguito, l’ordine di presentazione grafica è alfabetico per consentire una più facile ricerca, mentre la descrizione operativa è in ordine di importanza del componente.

 

ClsB_Base 

 

ClsB_Base.dll è la libreria base della solution. Viene utilizzata in tutti i progetti e contiene classi e moduli di uso comune.

 

Global (Modulo)

E’ un modulo che contiene una serie di utility di basso livello. Tra questi rivestono particolare importanza le funzioni di conversione (con prefisso Conv) che permettono di convertire variabili tra tipi diversi con la certezza di gestire e risolvere le eccezioni. Particolarmente importanti anche le funzioni di binding (Prefisso BindControl) che eseguono bind con gestione delle eccezioni tra i diversi tipi di controlli e le variabili. Qui si trovano altre funzioni di uso comune per l’arrotondamento, il controllo di congruità di codici, inizializzazioni e settaggi, gestione ed invio di email, gestione delle date e campi note, ecc. 

GlobalF35 (Modulo)

E’ un modulo che contiene una serie di utility di basso livello simile a Global tuttavia contiene funzioni disponibili solo con .NET Framework 3.5 . La creazione di un secondo modulo si è resa necessaria per garantire la compatibilità di Global con versioni precedenti.  

DbFunct (Modulo)

Dbfunct è l’unica porta di accesso al database. Tutte le classi che vedremo di seguito passeranno dalle funzioni di DbFunct per colloquiare con la base dati. Tutte le classi (connection, DataReader, DataAdapter, ecc.) sono astratte. Questa scelta riveste particolare importanza perché consente di agganciare un nuovo database con estrema facilità.

Questo modulo è in grado di riconoscere il tipo di database dalla connectionstring ed in base a questa operare di conseguenza.

La funzione più importante è ExecuteSQL che esegue un comando (SELECT, INSERT, UPDATE o DELETE). Se il comando e' sotto transazione Command e Connessione sono importate dall'esterno. Usa ExecuteNonQuery per avere maggior velocità o ExecuteReader per ritornare un dataReader (Select o Stored Procedure). Il parametro RigheTrattate passato ByRef ritorna il numero di Righe oggetto di modifica/cancellaziome

I diversi database possono avere differenze sintattiche. Anche le funzioni di generazione delle stringhe e conversione tra tipi sono contenute in DbFunct. 

IO (Modulo)

IO permette la gestione di files e cartelle (generazione, copia, cancellazione, verifiche, ecc.).

Gestisce la serializzazione, l’upload e il dowload di files, la lettura e scrittura di file di testo. 

Form (Modulo)

Questa modulo contiene funzioni di base che consentono di gestire le winform e le pagine web.

Particolarmente importanti le funzioni SetForm e SetPage che uniformano i controlli presenti sulle pagine. In realtà SetPage può essere visto come un doppione dei file CSS. 

DbClass (Classe)

DBClass e' una classe che permette il caricamento da data di un record, lo puo' gestire e riscrivere. Tutte le classi di business gestite nell’applicazione saranno ereditate da DbCless. Pur non essendo una regola possiamo dire che una sottoclasse corrisponde ad una tabella importante del database. DbClass permette di gestire le classi master/datails come ad esempio documento/righe documento. DbClass  si avvale della classe DbClass_Module per le stampe delle schede.

DBClass puo' operare autonomamente ma puo' anche collaborare con DBMaster, che vedremo in seguito, per gestire le proprietà ricavate dalla classe.  

DbReader (Classe)

DBReader consente la scansione di una tabella, query, stored procedures, ecc. in modo veloce e con scorrimento solo in avanti e senza la gestione di cursori. Non e' permesso il riposizionamento e la modifica dei dati (per questo c'e' DBMaster) 

DbMaster (Classe)

DBMaster è figlia di DbReader e ne eredita le funzioni me può operare autonomamente e può anche collaborare con

DBClass per gestire le proprietà della classe.  

DataGridManager (Classe)

DataGridManager consente la gestione dellle classi linkate a DataGridView fornendo dei metodi per le operazioni piu' usate sulla griglia. Il costruttore linka un DataGrid ad un oggetto DbMaster o DbClass. Sostanzialmente la possiamo vedere come una classe che si occupa di fare binding tra DbClass e ClsB_BaseForm.SuperDataGridView.

Questa classe è utilizzate nella gestione dei dettagli agganciati a classi DbClass o nella presentazione dei dati nella form di elenco. 

Printer (Classe)

L’utilizzo delle stampanti in Vb.Net/C# non è così banale come in Visual Basic. Printer cerca di rendere semplice l’accesso e la gestione delle stampanti. L’utilizzo di Printer permette di fare stampe grafiche e stampe di testo, cioè comporre e stampare righe come si faceva su sistemi operativi privi di driver.

Le stampe grafiche di base possono riportare testo, immagine, codice a barre, linee e rettangoli. Ogni oggetto può essere definendo un punto (X e Y in cm) di inizio e di fine.

Per le stampe in formato PDF o RTF deve essere utilizzato PrinterDoc (figlio di Printer) compreso in ClsB_Office 

Errore (Classe)

Le eccezioni sono gestite nella classe errore. Le eccezioni sono tracciate in ordine di evento sul file  ..\bin\DATI\Log\ErrorLog_[data].txt 

Log (Classe)

Le operazioni eseguite dagli utenti sono gestite nella classe Log e tracciate in ordine di evento sul file  ..\bin\DATI\Log\InfoLog_[data].txt 

Translater (Classe)

Si occupa della gestione delle traduzioni delle label presentate a video o in stampa. Si appoggia ad un file XML gestito in “Gestione Tabelle” che contiene una riga per ogni termine o frase e una riga per ogni lingua. 

XML_Table e XMLXPathReader (Classe)

XML_Table permette di gestire una o piu tabelle su dataset. XMLXPathReader serve per poter effettuare delle query o sort XPath su un documento XML.

 

ClsB_BaseForm, ClsB_BaseUC, ClsB_BaseUC_Gruppi

 

ClsB_Base.dll è la libreria base per la gestione delle form. Viene utilizzata in tutti i progetti che hanno interfaccia winform. Contiene form madri e controlli utente utilizzate nelle form figlie.

Le form presenti nell’applicazione sono uniformi nella gestione e nei metodi. Infatti, ad eccezione delle form più banali,  ereditano tutte da GestForm o BaseForm. 

GestForm (Classe)

GestForm e' la form genitrice delle form di gestione. GestForm generalmente genera form che gestiscono le classi di business (ogni form figlia si occupa di gestire una classe) ma si presta anche a gestire tabelle senza che sia definita una specifica classe.

Contiene metodi per creare un nuovo oggetto, aprirne uno esistente, salvare l’oggetto, cancellarlo, stamparlo. Mette a disposizione menu che possono essere integrati. Queste funzioni di base naturalmente vengono arricchite con funzioni specifiche dalle clessi filglie ma l’importante in questa sede è avere funzioni astratte che possano essere ereditate ed utilizzate da tutte.

All’interno della libreria troviamo UTIL01 e TableManager che sono due esempi di classi figlie di GestForm. UTIL01 permette di gestire i dati anagrafici dell’azienda e di salvarli su file config.xml. TableManager è più complessa perché interagisce con il database dovendo mantenere un grado di astrazione. Per fare questo i riferimenti alle tabelle e ai campi da gestire arrivano dall’esterno sotto forma di classi o di semplici array. 

BaseForm (Classe)

GestForm e' la form genitrice delle form di presentazione. Anche in questo caso possiamo agganciare alla form figlia una classe di business che rende estremamente veloce la creazione di selezioni anche complesse.

Contiene un metodo per eseguire un’operazione (solitamente la presentazione di una griglia ma altre volte la chiamata a metodi). Mette a disposizione menu che possono essere integrati. Queste funzioni di base vengono arricchite con funzioni specifiche dalle clessi figlie. 

CollectionManager (Classe)

La form figlie di GestForm che si occupano di presentazione, alla richiesta di selezione, presentano una form che chiede i dati che si vogliono visualizzare. Questa form è la CollectionManager. Il popolamento della CollectionManager deriva da una collection popolata dalle classi di business. 

Search (Classe)

La form Search permette di ricercare una registrazione conoscendo parte del codice o parte della descrizione di una riga o eventualmente altri campi a scelta dello sviluppatore. Search viene chiamata soprattutto da LinkTable o da SuperDataGridView ma può essere utilizzata in diversi punti dell’applicazione. 

GrigliaTC (Classe)

La form GrigliaTC gestisce la griglia Taglie e Colori. Viene chiamata da LinkTable o da SuperDataGridView. 

SuperDataGridView e SuperDataGrid (Classe User Control)

La gestione di DataGridView e DataGrid (fino al framework 1.1) non è particolarmente semplice per il numero di metodi e proprietà che queste mettono a disposizione. Soprattutto il binding proposto da questi controlli non è particolarmente funzionale e non riesce a gestire query complesse e con diversi join.

SuperDataGridView e SuperDataGrid consente di superare questi problemi fornendo metodi ben definiti per le operazioni piu' usate sulla griglia. Lavorano in stretto rapporto con ClsB_Base.DataGridManager e di consegunza gestiscono i dettagli presenti nelle classi di business.

SuperDataGridView e SuperDataGrid permettono anche una presentazione veloce e automatica nella presentazione dei dati nella form di elenco.

Il menu di contesto mette a disposizione funzioni per la stampa e l’esportazione della griglia in formato XML, HTML e Excel. 

LinkTable (Classe User Control)

Lo user control LinkTable permette di agganciare un codice e una descrizione di una tabella. Naturalmente LinkTable è una classe astratta pertanto i nomi dei campi e delle tabelle sono proprietà che devono essere caricate dall’esterno. 

SuperListView (Classe User Control)

Si presenta come SuperDataGridView ma a differenza di questa è di sola lettura. In realtà il componente di base è notevolmente diverso infatti la presentazione avviene su una ListView. In diverse funzioni dell’applicazione SuperListView e SuperDataGridView sono previsti entrambi quindi sono intercambiabili ma le caratteristiche sono leggermente diverse.

Si consiglia di utilizzare SuperListView quando si vuole creare una form più leggera, se i dati riportati non sono bindati direttamente da una tabella, quando si vogliono presentare griglie con presentazioni grafiche differenti per cella. Alcune di queste possibilità si possono ottenere anche con SuperDataGridView ma la quantità di lavoro di sviluppo richiesto è maggiore. 

SuperTextBox (Classe User Control)

Utilizzare questo componente invece di TextBox quando si deve inserire nomi di file, indirizzi email, siti web, ecc.

Sono permesse la ricerca e la presentazione dell’oggetto inserito. 

SuperRadioButton (Classe User Control)

Permette di estendere l’oggetto Radio Button affinché vada in binding con variabili di tipo integer.

UC_DatiAnag (Classe User Control)

Tra le strutture presenti in ClsB_Base.Global troviamo DatiAnag che contiene le proprietà dei dati anagrafici (ragione sociale, indirizzo, città, ecc.). Questo controllo permette il binding con variabili di tipo DatiAnag.

 

ClsB_BaseUC, ClsB_BaseUC_Gruppi (LIBRERIE)

Le librerie ClsB_BaseUC e ClsB_BaseUC_Gruppi contengono user control simili a quelli della libreria ClsB_BaseForm con nomi leggermente diversi (di solito la classe ha lo stesso nome con il prefisso UCWPF_).

Come si può avere intuito le funzionalità sono le stesse dei controlli precedentemente trattati ma sono usate per lo stile WPF (Windows Presentation Foundation).

Fin dove possibile anche il nome dei controlli, delle proprietà, dei metodi e degli eventi è stata mantenuta. Questo aiuta lo sviluppatore anche e soprattutto nell’utilizzo degli user control in form (stile FORM) e window (stile WPF) che hanno la stessa funzione.

Anche in questo caso la creazione di librerie separate si è resa necessaria per garantire la compatibilità di ClsB_BaseForm con versioni precedenti.

La creazione di due assembly diversi è stata dettata dall’esigenza di raggruppare in un assembly a parte (ClsBUC_Gruppi) user control che contengono altri user control.  

 

ClsB_Sistema 

ClsB_Sistema.dll è la libreria che racchiude metodi e classi per interagire con il sistema e con Active Directory. Si tratta per lo più di best-practice piuttosto che di un ambiente strutturato e le funzioni che si trovano qui vengono utilizzate il più delle volte in ambienti di nicchia o in personalizzazioni. Tuttavia qui potete trovare parti di codici che risolvono con poco sforzo una particolare esigenza.

 

SysNet (Modulo)

Contiene alcune funzioni non accessibili dal framework per raccogliere informazioni sul sistema e sugli utenti. 

Zip (Modulo)

Permette di zuppare/unzippare files o cartelle. Il file zip generato può essere letto da applicativi come WinRAR o WinZip ma non da Windows. 

FtpCommand (Classe)

Gestisce la connessione con un sito FTP gestendo download, upload e lista dei file. 

Services (Classe)

Consente di verificare quali servizi Windows sono attivi. 

EventLog (Modulo)

Funzioni per la gestione degli eventi di log di Windows. 

Security (Modulo)

Contiene alcune funzioni per leggere identità, credenziali e firma digitale. 

ClsB_Office 

ClsB_Office.dll è la libreria che racchiude metodi e classi per interagire con file e strumenti di office automation. La parte del leone la fanno oggetti Micorsoft Office e PDF.

 

 

PrinterDoc (Classe)

PrinterDoc è figlia di ClsB_Base.Printer e ne eredita tutte le caratteristiche con la differenza che anziché generare una stampa, in output genera un file PDF o RTF. 

MSOffice (Classe)

Questa classe gestisce un file di Microsoft Office (Word, Excel o Project). Anche in questo caso più che di una classe strutturata possiamo vederla come una classe nata per gestire le singole esigenze. Pertanto potremo sostituire una parola in Word per avere un template da riutilizzare, potremmo leggere e scrivere celle in Excel o gestire i progetti inseriti in Micosoft Project. Per svolgere queste funzioni sono stati utilizzati gli oggetti di Micosoft Office ovvero OCX.

Per rendere la classe modificabile anche su PC che non abbiano Micosoft Office installato tutte le classi sono di tipo object. 

DocRtfPdf (Classe)

DocRtfPdf permette di generare un documento in formato Pdf o Rtf. Può essere generato un documento da un file XML o inviato un documento su webform. 

Zetafax (Classe)

Invia Fax attraverso ZetaFax Server con ZetaFax CommsEngine.

Per rendere la classe modificabile anche su PC che non abbiano ZetaFax installato tutte le classi sono di tipo object.e viene usato latebinding (CreateObject).

Per poter utilizzare queste funzioni l’utente deve aver acquistato le licenze di Zetafax.

Per inviare un allegato in formato PDF o DOC deve essere installato sul server la licenza di 'Document Conversion'.

 

ClsB_Gea e ClsB_GeaForm 

Le classi specifiche dell’applicazione sono composte di diverse decine di classi. La necessità di creare due librerie piuttosto che una sola è dettato dall’esigenza di rendere scalabile l’applicativo anche a servizi esterni o applicazioni WEB.

ClsB_Gea contiene tutte le classi di business, cioè classi astratte che non hanno alcuna relazione con l’intercaccia utente.  Di conseguenza è la libreria fondamentale e qui troveremo tutte le funzioni nevralgiche, strutturate per classi di appartenenza.

ClsB_GeaForm invece si occupa di relazionare le classi con l’utente, qui troviamo alcune form di uso comune o alcuni controlli utente. Naturalmente la maggior parte delle form si trovano nelle librerie specifiche (AIM_*). 

Trattare le diverse classi in dettaglio in questa sede sarebbe molto complicato. Basti sapere che l’uso che viene fatto delle diverse classi è esplicitato nel nome stesso e i metodi sono generalmente commentati all’interno del codice stesso.

Generalizzando possiamo dire che ogni classe ha un rapporto uno a uno con una tabella del database (o uno a molti nel caso di gestione master/detail come ad esempio ordine/righe ordini).

Allo stesso modo possiamo dire che di solito abbiamo un rapporto uno a uno tra la classe e la form che la gestisce pertanto nella maggior parte dei casi avremo un le game diretto tra le entità :

Il binding tra queste entità avviene utilizzando classi e funzioni di ClsB_Base. Il binding tra tabelle e classi è gestito in TrattaListaCampi e in TrattaDettagliListaCampi di ClsB_Base.DbClass. Il binding tra Classe e Form è garantito dalla funzione AssociaControlli che si trova nella form e che riporta questa operazione a ClsB_Base.BindControl. 

Nella maggior parte dei casi le classi di business sono di primo livello ovvero sono direttamente figlie di ClsB_Base.DbClass ma in alcuni casi possono avere un ulteriore livello (ed esempio sia Ordini che Fatture sono figlie di Documenti che è figlia di DbClass). 

GEANET.EXE 

Questo è il progetto di avvio dell’applicazione. In realtà è un progetto piuttosto leggero e contiene solo la form di avvio e le funzioni di configurazioni ( il cui lavoro viene eseguito in ClsB_Base ).

Il progetto non contiene un riferimento diretto ai diversi moduli (AIM_*) come ci si potrebbe aspettare. I moduli vengono interrogati e invocati tramite reflection. Questo rende la gestione dell’applicativo più semplice e polimorfica.

Infatti a livello di sviluppo non abbiamo l’obbligo di integrare tutti i progetti che lo compongono che, si badi bene, non sono solo quelli comuni ma possono anche essere progetti di sviluppi verticali o personalizzazioni di un determinato utente.

Anche la gestione operativa ne trae vantaggio infatti è sufficiente eliminare una libreria di modulo senza rendere instabile l’applicazione. 

AIM_* 

Le librerie di modulo vengono chiamate per convenzione con il prefisso AIM. Esiste una libreria per ogni modulo gestito pertanto nella solution sono presenti diversi progetti AIM_*.

Le librerie di modulo sono generate in formato dll e non possono essere eseguite autonomamente ma devono essere invocate dall’esterno nel seguente modo :

Ogni progetto contiene un interfaccia che per convenzione si chiama [nome_progetto].vb che implementa iBF_AddInModule.

iBF_AddInModule contiene tre metodi fondamentali per colloquiare con l’esterno :

A questo punto abbiamo tutto ciò che ci serve per utilizzarla. 

La libreria si compone di normali form (stile FORM) e window (stile WPF) o classi secondo le specificità della classe stessa.

Oggetti del database 

Vale la pena spendere due parole anche per la struttura del database pur essendo abbastanza intuitivo l’uso delle tabelle.

La prima cosa da sapere è che le tabelle hanno un prefisso nel nome che ne identifica il gruppo di appartenenza.

Quindi :

·         AN : Anagrafiche clienti e fornitori

·         BO : Documenti di trasporto

·         CA : Risorse Umane (Presenze)

·         CE : Cespiti

·         CV: Risorse Umane (Curriculum)

·         FA : Fatture

·         FF : Documenti passivi

·         LS : Listini

·         MA : Magazzino

·         MC : Movimenti di contabilità

·         MM : Movimenti di magazzino

·         NO : Noleggio

·         OR : Ordini

·         PC : Piano dei conti

·         ST : Risorse Umane (Consuntivi presenze)

·         TA : Tabelle generiche

·         TU : Risorse Umane (Turni)

 

Si ricordi che nel pacchetto base non sono stati utilizzati altri oggetti oltre alle tabelle non disponibili in tutti i database (es. macro, relazioni, stored procedure, trigger ). Questa scelta va a discapito della velocità di esecuzione ma ha il vantaggio di non vincolare l’applicazione ad uno specifico database garantendone la scalabilità. Le relazioni tra tabelle è gestito a livello software e quindi bisogna fare particolare attenzione a questo aspetto durante lo sviluppo di nuove funzioni.

Qualora si realizzino funzione specifiche e personalizzazioni potrebbe essere vantaggioso usare oggetti più performanti confinandoli in librerie diverse da quelle comuni. In altri casi potrebbe essere conveniente sostituire alcune classi o funzioni che anziché puntare ad una tabella, acquisiscano i dati  da una stored procedure o da una vista.

Gli indici proposti sono ridotti al minimo ma per velocizzare alcune funzioni più ricorrenti potrebbe essere il caso di generarne altri.

Tutti questi aspetti devono essere analizzati secondo le esigenze e le richieste del cliente.