image gauche

logo Clairinfo

image droite


Version du : 30/01/2007

TUTORIAL PARADOX POUR WINDOWS

Leçon 1 - Introduction

Présentation :

L'objectif de ce tutorial est de construire une application de qualité professionnelle en Paradox pour windows. Ce premier volet va consister à présenter les fonctionnalités attendues du logiciel et à aborder la phase d'analyse pour ce qui concerne l'organisation des données et des traitements. La connaissance d'un autre système de base données ou d'un langage de programmation constituerait un plus non négligeable mais ce tutorial devrait être accessible au néophyte.

Les fonctionnalités attendues :

Nous ne voulons pas faire trop simple afin d'éviter la frustration inévitable qui survient avec les tutoriaux simplistes qui se contentent de présenter les fonctionnalités les plus évidentes. C'est pourquoi nous allons prendre le cas d'une application classique de gestion commerciale en limitant quelque peu l'étendue des possibilités !

- Gestion de clients (3000 clients prévus)
- Gestion de produits (5000 produits prévus)
- Gestion de factures (10000 factures par an prévues)

1 client peut avoir N factures, chaque facture comporte N lignes , chaque ligne de facture concerne un et un seul produit. Nous supposerons que la TVA est globale à chaque facture et non liée à chaque produit.

Le logiciel devra fonctionner en réseau et 10 utilisateurs sont susceptibles d'utiliser l'application.

Cet exemple va nous permettre de comprendre les possibilités d'une base de données comme Paradox capable de lier des tables (des fichiers) entre elles de façon transparente pour l'utilisateur et capable de fonctionner en réseau sans gros problème pour le programmeur.

Etape 1 - Choix de l'outil de développement :

Pourquoi prendre Paradox plutôt que tel ou tel autre outil ?

- Parce que Paradox est un outil de développement très puissant mais facile à utiliser y compris pour un néophyte.

- Parce que Paradox , construit autour du moteur de base de donnée de Borland (BDE , "Borland Database Engine"), fonctionne parfaitement en réseau pour un petit groupe d'utilisateurs comme nous l'envisageons (cf analyse des points faibles de l'outil plus bas)

- Parce que de ce fait, il est possible de conserver son interface utilisateur en Paradox tout en migrant ses données dans un SGBD ("Système de Gestion de Base de Données") de type client serveur plus robuste aux pannes et plus performant en cas de connexions très nombreuses. Paradox peut attaquer nativement ou via ODBC (interface d'accès standardisée au base de données) les principales bases de données existantes : Oracle, MS-SQLServeur, Interbase , MySQL... Cette ouverture de Paradox, exceptionnelle, en fait un excellent "couteau suisse" pour l'administrateur de bases de données confronté à des systèmes différents. Il sait tout faire ou presque : extraire des données, les présenter, les manipuler, les convertir, les importer etc... Les temps de réponse sont eux aussi exceptionnels.

- Parce que le logiciel Paradox sous licence Corel est aujourd'hui distribué avec un runtime gratuit qui permet de déployer une application Paradox sur N postes clients sans verser de redevance à Corel. Le runtime , c'est un sous ensemble des fonctionnalités de Paradox permettant d'exécuter une application construite avec Paradox mais pas de la modifier. Les fonctionnalités telles que : appels de boites de dialogue de Paradox, création et modification d'état, création intuitive de fiches ou de requêtes, experts utilisateur etc... ne sont pas disponibles dans le runtime. Toutes les fonctionnalités programmables en OPAL (langage de Paradox) ou via des composants externes (Dll, ActiveX...) seront accessibles dans le runtime.

- Parce que Paradox inclut un générateur d'états extraordinaire qui permet, sans une ligne de code, de réaliser tous type d'éditions très simplement. Il suffit d'avoir testé d'autres outils du marché pour comprendre le caractère génial de Paradox sur ce plan !

- Parce qu'aucun autre outil à notre connaissance ne permet de développer aussi rapidement, avec aussi peu de code une application aussi performante et fiable , y compris en réseau.

- Parce que, contrairement à certains outils concurrents, les versions windows de Paradox offrent une compatibilité ascendante. La version 10 de Paradox (2002) est capable d'exécuter le code de Paradox 1.0 (1993) ! C'est un point très important pour préserver son investissement.

- Parce qu'une version de Paradox (Paradox 9) fonctionne sous Linux.

- Parce que le prix de l'outil Paradox est dérisoire , autour de 150 € pour Paradox 10 pour windows !
(Très précisément 30 € HT pour obtenir le CD "starter Kit" et 112 € HT pour une licence Paradox...)

Cet outil a-t-il malgré tout des faiblesses ?

Oui (quel outil n'en a pas ?). Aussi faut-il bien les examiner pour vérifier qu'elles ne sont pas pénalisantes pour votre application :

- Corel détient une licence de distribution exclusive sur Paradox mais pas sur le BDE propriété de Borland. Or Borland a semble-t-il décidé de placer le BDE en mode "maintenance", ne souhaitant plus investir dans ce produit. Ils ont aujourd'hui une offre concurrente qu'ils favorisent : dbExpress. Cela étant, tous les produits de Borland (Delphi, C++Builder) continue d'intégrer le BDE car, d'une part, un très grand nombre d'applications de part le monde utilisent le BDE et, d'autre part, dbExpress n'offre pas tous les services du BDE, loin de là. En l'état actuel ce n'est pas un obstacle pour notre application mais c'est une inquiétude réelle pour le futur. Comment le produit peut-il évoluer dans ces conditions ?

- Paradox est un outil "basé objet" et non "orienté objet". On ne peut pas construire de nouveaux objets en Paradox. On utilise ceux qui sont proposés et qui sont superbes et très efficaces. Pour l'utilisateur néophyte que nous visons, c'est plutôt une très grande qualité car le nombre d'objets à connaître est limité et donc rapidement on peut faire le tour de l'outil. Que le développeur confirmé se rassure, on peut étendre les possibilités de Paradox en intégrant des Dll (Dynamic Link Library, bibliothèque de code compilé que l'on peut lier à son application lors de l'exécution) , des activeX (des objets offrant une interface standardisée pour proposer leurs fonctionnalités, très répandus aujourd'hui.). Corel a même prévu un système pour intégrer des fiches Delphi (Delphi est un outil de développement, conçu par Borland, plus puissant mais plus complexe que Paradox) dans Paradox. Pour l'application que nous visons nous n'aurons pas besoin d'outils complémentaires.

- Paradox n'offre pas de possibilité d'héritage de fiche ou d'état. L'héritage consiste à créer une maquette de base puis à créer de nouveaux documents qui héritent de la maquette de base et qui bénéficient de tous les changements apportés par la suite à la maquette de base. C'est un plus certain en terme de maintenance d'application.

- Paradox n'offre pas une compilation native du code. De ce fait les performances sont inférieures à celles obtenues par un langage compilé (comme Delphi par exemple). Cela étant nous estimons pour notre part qu'avec les machines actuelles la différence de temps de traitement sera à peine perceptible pour l'utilisateur final sur une application de gestion comme celle que nous envisageons. Quant au souci légitime de protéger son code, Paradox offre la possibilité de "distribuer" les différents composants d'une application masquant ainsi tout le code source. Le fait que chaque écran (les "fiches" dans le langage de Paradox), chaque édition (les "états") soient enregistrés dans un fichier distinct devient en terme de maintenance un énorme avantage. Le client souhaite une modification de tel écran ou de telle édition ? Il suffira de lui transmettre uniquement les quelques fichiers modifiés et non un énorme exécutable qui engloberait tout.

Etape 2 - Analyse du problème :

Nous n'allons pas ici trop détailler les aspects théoriques à l'origine des base de données relationnelles. Notre volonté est de garder un langage clair compréhensible par tous et concret. Le lecteur soucieux de posséder ce bagage théorique pourra consulter avec profit un ouvrage consacré à la méthode MERISE par exemple qui constitue un grand standard à ce niveau (cf liens sur notre site).

Analyse des données :

Pour faire court, l'intérêt d'une base de données relationnelle comme Paradox est de stocker intelligemment les données afin d'éviter les redondances dans le fichiers , sources de problème de performance (fichier volumineux) et de maintenance (la modification de ces données dupliquées est problématique).

Pour prendre comme exemple notre application, il apparaît rapidement qu'une "facture" se décompose logiquement (au sens du stockage informatique) en au moins 2 ensembles distincts :

- L'en-tête de la facture qui va stocker outre le N° Facture, le TypeFacture (AVOIR ou FACTURE) la DateFacture, le CodeClient, la DateEcheance , le TauxTVA, le TotalHT, le TotalTVA et le TotalTTC

- Les lignes de facture qui vont stocker le N°Facture (pour faire le lien avec l'en-tête), le N°Ligne (pour identifier chaque ligne et choisir son ordre d'apparition), le CodeProduit, le LibelleProduit, la Qte, le PVUHT, le MontantHT.

Ne pas effectuer cette séparation amènerait irrémédiablement des problèmes majeurs pour notre application. Par exemple le développeur que voudrait stocker ses factures dans un seul fichier serait obligé de répéter pour chaque ligne de produit des informations comme la DateFacture ou le CodeClient , augmentant considérablement le poids des données et compliquant sérieusement la mise à jour d'une information. Changer le TauxTVA d'une facture nécessiterait alors de remplacer la valeur sur chaque ligne de la facture au lieu de ne la modifier que dans l'en-tête.

Il est parfois nécessaire de créer de toute pièce une entité supplémentaire pour résoudre un problème :

Imaginons que l'on veuille faire un export comptable de nos factures avec la règle classique de ventiler nos comptes de vente HT selon le type du client (vente France soumise à TVA, vente France non soumise à TVA, vente CEE non soumise à TVA, vente hors CEE non soumise à TVA). La façon classique de résoudre ce problème est de gérer les tables suivantes :

Client.db : CodeClient , NomClient , CodeTVA (1=Vente France avec TVA, 2=Vente France sans TVA, etc...) ...

Produit.db : CodeProduit , Designation...
(On ne peut pas simplement ajouter ici le N° Compte car il doit varier selon le type du client)

Du coup on crée une table de jointure qui permet de stocker intelligemment l'association :
Compte.db : CodeProduit , CodeTVA , N°Compte

L'erreur typique du débutant consiste à vouloir simplifier en faisant l'économie de la table Compte.db avec par exemple :

Produit.db : CodeProduit, Designation, N°Compte1,N°Compte2,N°Compte3...
où N°CompteX correspond au compte à utiliser pour CodeTVA X du client.

C'est une grosse erreur pour 2 raisons :

- Il faudra modifier la structure de la table Produit.db si l'on rajoute un jour un nouveau CodeTVA à gérer
- Pour parcourir les Comptes comptables d'un produit donné il va falloir aller tester chaque zone N°Compte1,2,3...
Donc en cas d'ajout de CodeTVa il faudra également modifier TOUS les programmes utilisant ces informations.

La règle à suivre est simple :

Pour une relation de 1 à plusieurs, 1 produit a plusieurs N°Compte, il faut impérativement gérer 2 tables.
Même si pour l'instant on ne gère par exemple que 2 comptes il faut séparer les tables.

Pour notre application on pourrait arriver aux tables suivantes :

Client.db : La table des clients

CodeClient : Identifiant unique
Nom
Adresse1
Adresse2
CodePostal
Ville
Notes

Produit.db : La table des produits

CodeProduit : Identifiant unique
Designation
Prix

NoPiece.db : Le dernier N° pièce utilisé
(nécessaire pour incrémenter le N°Facture par exemple)

NoID : Identifiant unique
NomPiece
NoPiece
TableControle (voir le tutorial 4 pour le fonctionnement)

Fact.db : Les en-têtes de factures

NoFact : Identifiant unique , incrémenté automatiquement
TypeFact : AVOIR ou FACTURE
DateFact
CodeClient
Nom
Adresse1
Adresse2
CodePostal
Ville
TauxTVA
TotalHT
TotalTVA
TotalTTC

FactD.db : Les lignes de factures

NoFact : Repris de la facture
NoLigne
CodeProduit
Designation
Qte
PUHT
MontantHT

Tva.db : Les taux de Tva

TauxTVA
LibelleTVA

Normaliser, puis dénormaliser ses données !

Un point important à comprendre pour l'analyse des données est le processus en 2 étapes :

- Dans un premier temps on "normalise" les données , c'est à dire qu'on essaie comme vu plus haut d'éviter toute redondance et de ne stocker que le strict nécessaire. Cette phase est souvent bien décrite dans la littérature.

- Dans un deuxième temps, on "dénormalise", c'est à dire qu'en prévision des traitements futurs , on accepte de ne pas optimiser le stockage des données pour favoriser les traitements futurs. Moins bien décrite, issue souvent de l'expérience du développeur, cette étape est très importante !

Examinons les choix effectués pour les tables Fact.db et FactD.db. Pourquoi par exemple stocker TotalHT, TotalTVA et TotalTTC dans l'en-tête de facture ? Après tout, en balayant les lignes on pourrait très bien retrouver ces chiffres. Pourquoi même stocker MontantHT dans la table FactD.db , le simple recalcul de Qte x PUHT devrait suffire ? Et bien parce que l'expérience montre que l'on va tout le temps avoir besoin de l'information MontantHT, TotalHT,TotalTVA et TotalTTC , soit lors de l'impression de la facture, ou du journal de ventes, ou encore lors du transfert comptable, ou bien lors des statistiques etc... En dénormalisant ainsi le stockage de nos factures nous nous simplifions grandement les traitements futurs et nous optimisons grandement les temps de ces mêmes traitements.

En outre , dans le cas d'une facture, document à valeur juridique, il convient de pouvoir réimprimer à l'identique toute facture stockée. Accepter de recalculer une facture lors de son impression, c'est accepter le risque d'un calcul différent lié par exemple à un processeur différent et ce risque n'est pas acceptable pour une facture.

Haut de page     Suivant

© Copyright 2000-2007 , Clairinfo ® , http://www.clairinfo.fr