vendredi 17 septembre 2010

Creational Pattern (2)

2) Builder

Le builder est utilisé pour créer un objet complex indépendamment de sa représentation. Ainsi on pourra créer le même processus de construction pour générer des représentations différentes.

Cas d'utilisation:
Le ReaderRTF : le reader RTF parse un fichier RTF et traduit les formattages, soit il n'y a pas de formattage (plain-text), soit il faut les afficher en Html, Latex, ...

Dans ce cas de figure deux operations apparaissent : le parsing et l'affichage.
Nous allons donc créer deux classes:
La classe Director qui contient l'algorithme de parsing du fichier RTF
Et une classe Builder (abstraite) qui contient les méthodes d'affichage (ex: ConvertCharacter, ConvertFont, ConvertParagra...)
Les autres classes builder vont dériver de celle-là, exemple : ASCIBuilder, HtmlBuilder ou LatexBuilder (ConcreteBuilder). Les méthodes de la classe abstraites seront outrepassées et permettront d'afficher le document RTF, soit en text, soit en html ou soit en représentation graphique.

L'avantage du système est que le parsing peut générer plusieurs représentation, toutefois, il est aussi possible de changer l'algorithme de parsing et de ré-utiliser la même représentation.

Exemple du labyrinthe:
L'abstract builder contiendra les méthodes: BuildRoom, BuildDoor. Les concrete builder implémenteront concrètement la création des Room et des Door.
La classe MazeGame contiendra l'algorithme de création (Director) et définira quel room et quelles portes créer afin de générer un labyrinthe complexe.
L'abstract class builder contiendra une fonction GetMaze qui renverra le labyrinthe. La classe MazeBuilder sert donc uniquement à créer, elle renvoit ensuite l'instance de l'objet crée dans ce cas ci un objet de type Maze.

Application dans TrialXS:
Le pattern utilisé dans l'export crée en 2002, à l'époque, je ne savais pas quel nom leur donner c'est pourquoi la dénomination peut paraître étrange.
Le but de l'export est d'extraire des données relatives aux patients et de les exporter dans différents (text, SAS ou CDISC).

L'Export est composé d'une classe d'extraction des données appelée:
TPatientItemProvider (Director)
Cette classe contient toute la mécanique d'extraction des CRF relatifs aux patients, chaque fois qu'un CRF existant est complété elle appelle la méthode CollectData de la classe builder.
Si il s'agit d'un nouveau CRF non existant, on appellera la méthode : CollectStructure qui construira un nouveau CRF.

La méthode CollectData fait partie de la Classe TFormExport. Cette classe est l'abstract builder.
Différent builder en dérivent, tels que TFormSASExport, TFormFlat ou TCDISCExport. Cette classe n'est pas vraiment un abstract builder puisqu'elle est déjà le produit en tant que tel. Pour réaliser le pattern on aurait dû avoir une clasee TFormBuilder.getFormExport qui aurait renvoyé les TFormExport crées.

A la fin de la construction, le composite produite sera une liste de CRF défini dans une structure particulière (soit de simple fichier texte, soit des fichiers text avec un fichier de définition, soit une structure xml).

Autres exemples: TCVisitPlanBuilder: Cette classe construit un visit plan théorique en tenant compte des visites model et des visit instances. Encore une fois, il s'agit d'un cas particulier car le Director et le Builder sont aggrégés dans la même classe. Mais l'idée reste la même assurer la création d'un objet complexe à partir d'une autre classe.

Un pattern de type Builder génère en général un Composite.

mercredi 15 septembre 2010

Creational Patterns

1) Abstract factory :

Utilisé pour gérer de multiples look & feel ou source de données, on évite de créer des instances d’une classe particulière directement dans l’application. On passe par une classe intermédiaire qui se charge de créer les objets pour nous.

Nous allons appliquer ce pattern à TrialXS. Supposons que nous voulions rendre l’application indépendante du type de server de base de données (ce qui complique la tâche). Nous allons considérer deux server de base de données SQL Server et Oracle.

Exemple :
// Abstract Factory
TDBObjectFactory=class
function CreateProject :TProject;virtual;
function CreatePatient;TPatient;virtual;

End;
// Abstract Product
TDBObject=class
Procedure get;virtual;
Procedure Save;virtual;
Function createsql:string;virtual;
End;
TProject=class(TDBObject)
property BaseLine : integer read fBaseLine;
end;
TPatient=class(TDBObject)
end;
// Concrete Product
TSqlProject=class(TProject)
Function createsql:string;override //Contient le sql de creation de l’objet pour Sql server
Function Save ;override ;
Function get ; override ;
End ;
// Concrete product
TOraProject=class(TProject)
Function createsql:string;override //Contient le sql de creation de l’objet pour Oracle
Function Save ;override ;
Function get ; override ;
End ;
// Concrete Factory
TSqlObjectFactory =class(TDBObjectFactory)
Function CreateProject ;override; // Retourne un objet TSqlProject
function CreatePatient;override;
End;
// Concrete Factory
TOraObjectFactory=class(TDBObjectFactory)
function CreateProject ;override; // retourne un objet TOraProject
function CreatePatient;override;
End;

Dans l’initialisation de l’application

Var
ObjectFactory:TDBObjectFactory;
begin
If db_type=sql then
ObjectFactory:=TSqlObjectFactory.Create;
Else
ObjectFactory:=TOraObjectFactory.Create;
End;

Chaque fois que je crée un objet db dans l’application, je passerai par l’objet ObjectFactory. En faisant soit

Var
Project :TProject ;
begin
Project :=ObjectBuilder.CreateProject ;
Project.get;
end;

Ceci Va me donner un objet de type SqlProject ou OraProject suivant le type de serveur sql utilisé. Partout dans l’application j’utiliserai l’interface de TProject en me moquant de savoir si j’ai un OraProject ou un SqlProject puisqu’ils réalisent tous deux la même interface. Ce système, certe plus lourd à le mérite d’éviter les castings.

Cela signifie que le type de server sql est défini une fois, partout ailleurs dans l’application je me ficherais de savoir si j’utilise Oracle ou SQL Server puisque c’est l’instance de la classe TDBObjectFactory (ObjectFactory) qui appellera les bon constructeur de classe.
Mon application sera donc indépendante du server de base de donnée pour récupérer ses objets.
TDBObjectFactory ou TDBObject sont généralement considérées comme des classes abstraites ou des interfaces, elles ne peuvent pas être instanciée directement.

Avantage: permet de changer toute une famille de produit en une fois.
Inconvénient:Il n'est pas facile d'ajouter un nouveau produit, car il faut updater et créer plusieurs classes. (pas très flexible)

On utilise souvent l'abstract Factory avec le pattern Singleton, car on ne doit avoir qu'une instance de la Concrete Factory.

On appelle également ce pattern :Kit ou Usine (terme français pour Factory)

vendredi 10 septembre 2010

Validation des Systèmes Informatiques

Définition de la validation:

"Etablir des preuves documentées qui fournissent un haut degré d'assurance qu'un processus spécifique produira constamment a produit conforme à ses spécifications pré-déterminées et à ses attributs qualificatifs".

FDA, Guidelines on General Principle of Process Validation (1987)

D'une part, il faut distinguer validation d'un logiciel (Software Validation) et validation d'un système (System Validation). (Le logiciel n'étant qu'une composante du système).
On peut définir la validation d'un système comme étant une qualification qui vérifie les étapes du processus.
Dans le cas du développement on parle d'un processus comprenant: la collecte des requirements, la création des spécification fonctionnelles, les spécifications de Design, la construction du système.

IQ : Installation Qualification : vérifie que l'environnement est conforme aux system requirement définies dans la phase de Design.
(check list qui vérifie que l'équippement est conforme, que le logiciel est correctement installé et correctement configuré). Le système fonctionne.
OQ : Operational Qualification : vérifie que le système fait ce qu'il est censé faire (test scripts)
verifie la phase fonctionnelle (les spécifications fonctionnelles). Fait ce qu'il doit faire.
PQ :Performance qualification : vérfie que les system requirements (temps de réponse définit) sont corrects. L'utilisabilité pour le client. Ca fait ce que ça doit faire dans temps acceptables

Valider signifie produire ces trois documents décrivant l'IQ, l'OQ et le PQ. Ces documents sont bien sur les preuves énnoncées dans la définition.
La production et le contenu de ces documents est le noeud gordien du problème.

mercredi 8 septembre 2010

Cross Tab Queries en SQL Server 2005

Les cross tab queries sont souvent bien utiles pour présenter des synthèses de résultats par catégories par exemple (En statistique cela est très utile pour l'ANOVA ou les tests du khi carré sur des comptes variables binaires).

Certains informaticiens ont le réflexe de récupérer les données via un data set puis de les trier eux même sous formes de tableau, cette opération est souvent très couteuse alors que SQL Server 2005 nous offre la commande PIVOT.

Cette commande permet de créer un tableau de donnée en un clin d'oeil.

Voici un cas d'exemple

SELECT ID_Project, ID_FormModel, [1],[2],[3],[4],[5],[6] FROM
(select FM.ID_Project, FM.ID_FormModel, FI.FormStatus, 1 AS cnt from tblDMFormModel FM
LEFT OUTER JOIN tblDMForminstance FI on FI.ID_FormModel=FM.ID_FormModel) AS RawData
PIVOT (
SUM(cnt) FOR FormSTATUS IN ([1],[2],[3],[4],[5],[6])
) pvt
WHERE ID_Project=165

La première ligne formatte le tableau en affichant les deux colonnes non pivotables : l'id_project et le form model, les valeurs en gras indique les valeur du status des formes.

La seconde ligne construit le tableau des données brutes sur laquelle nous allons appliquer le pivot. (Le left outer join sert à récupérer tous les form modèles, même ceux qui n'ont pas de form instance). 1 indique que le form instance apparait une fois.
PIVOT fait pivoter les valeurs de rows autours de FormStatus en sommant les form instance pour obtenir les comptes.

Voilà, c'est peut-être pas super bien expliqué mais ça marche !