samedi 21 décembre 2002

Delphi 7 studio



Ce livre aborde la programmation sous Windows et Linux.

Ce livre ne touche pas uniquement à Delphi, on y aborde des sujets tels que l'ergonomie, uml... Delphi est mise en avant première à travers les nombreux concepts vus.

Même si ce livre est consacré à la version 7 de Delphi, il est fort utile pour les autres versions de Delphi. Comme la majorité des livres, il manque d'exemples approfondis et on survole parfois trop certains sujets.

Ce livre demeure tout de même la référence présentement des livres en français sur Delphi.

lundi 16 décembre 2002

Software Engineering: Theory and Practice




Ce livre introduit les concepts du génie logiciel. Le développement avec l'approche procédurale et orienté objet y sont discuté.

L'emphase du livre est mise sur la modélisation. Les concepts montrés sont appuyés par deux exemples: un système d'information et un système temps réel.

En plus de cet aspect, la planification et la gestion de projet y fait partie. L'analyse chez le client afin de pouvoir définir les spécifications, le design du système ainsi que les tests font partie des chapitres que couvre ce livre.

Un livre très complet qui permet de faire le pont entre la théorie et la pratique.

dimanche 8 décembre 2002

Html


HTML

Le HTML est lisible sur toute plateforme qui possède un navigateur internet. On peut ainsi dire la majorité. Il peut alors être intéressant d'utiliser cette compatibilité afin de toucher le plus de gens possible. Bien sûr il existe divers formats de type de fichier, mais il arrive trop souvent que le logiciel permettant de lire un type de ficher donnée ne se trouve sur la plateforme désiré, que le rendu n'est pas semblable d'un système à un autre ou que notre confidentialité est mise en doute.

Nous pouvons alors utilisé le HTML pour créer divers types de document qui sera lisible à peut prêt partout et qui à l'avantage d'être très léger.

TPageProducer

Ce composant permet de créer des pages web à partir d'un modèle. Il existe aussi possible d'utiliser le TDataSetPageProducer (bd). Il est alors possible de créer des lettres génériques. Les mots génériques créés par nous sous la forme " <#nom_du_tab> seront par la suite changé par une valeur désirée.

Modèle

<HTML>
  <HEAD>
    <TITLE> </TITLE> 
  </HEAD>
  
<BODY>

<p> <#date>  </p>
<p> Traitement Automatisé des Fiches de salaire.</p>


<p> <#nom_employe> </p>

<p>Nos archives indiquent que n'avez pas pris de journée de congé au cours des <#annee> dernière(s) 
année(s).

Vous n'êtes pas sans savoir que notre entreprise accorde 2 semaines de congés payés aux employés 
par an, ou bien leur offre la possibilité de prendre l'équivalent en salaire.

En outre, en accord avec les conventions signées avec les syndicats vous accorde une 
semaine supplémentaire de congés payés pour chaque période de cinq années de travail dans l'entreprise.
</p>

<p>Bien à vous,</p>

<p>La comptabilité</p>
</body>
</html>
 
Nous pouvons voir que la lettre ci-dessus est générique. Elle pourrait par exemple être envoyé au employé d'une entreprise. Elle présente quelques tags personnalisés.
  • <#date>
  • <#nom_employe>
  • <#annee>
Il serait possible par exemple de prendre des valeurs dans une base de donnée et de remplacer ces tag. Les possibilités sont alors immenses: envois de courriel, lettre...

Fonctionnement

Il faut spécifier le nom de notre fichier HTML générique par la propriété HTMLFile du TPageProducer. Il faut ensuite indiquer les tags devant être modifiés et spécifier leurs valeurs.

var      
  S:string;
begin
  S := PageProducer1.Content; //Renvoi le contenu après les modifications des tags.
  if Length(S) > 0 then
    with TFileStream.Create('tmp.htm', fmCreate) do
    try
      Write(S[1],Length(S));
    finally
      Free;
end;
 

Le remplacement des tags par les valeurs souhaitées se déroule dans l'évènement HTMLTag.
Note que dans notre code nous avons écris <#date> mais qu'il faut seulement écrire date dans cet
évènement.

procedure TForm1.PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
  const TagString: String; TagParams: TStrings; var ReplaceText: String);
begin
 if TagString = 'date' then
    ReplaceText := '12 juillet'
 else if TagString = 'nom_employe' then
    ReplaceText := 'Mr. Gendron'
 else if TagString = 'annee' then
    ReplaceText := '10';
end;
 

Nous avons utilisé des valeurs statiques dans cet exemple, mais il aurait été possible
d'utiliser des valeurs d'une base de données.

mardi 3 décembre 2002

Algorithme de tri


ALGORITHME DE TRI

Il existe de nombreux algorithmes de tri, je tenterais seulement de vous montrer les plus populaires et les plus utilisés.

Il n'y a pas vraiment de tri qui soit meilleur que les autres, la vitesse d'exécution d'un algorithme dépend des donnés à trier. Certains algorithmes sont plus efficaces dans certaines circonstances c'est ce que nous tenterons de vous montrer

Complexité

Dans le but de mesurer la complexité d'un algorithme de tri,deux quantités sont à observer :
  • le nombre d'échanges effectués,
  • le nombre de comparaisons effectués entre éléments du tableau.

Grand O

Le grand O  est utilisé pour indiquer la croissance d'une fonction. Le symbole utilisé est O.

Grand oméga

Le grand oméga est utilisé pour avoir la limite inférieur d'une fonction, en d'autre mot le minimum. Le symbole utilisé est Ω

Les tries

Buble sort

Ce type de tri est le plus simple, mais souvent le moins efficace. Il peut s'avérer utile pour des petits tris étant donné sa simplicité, il y a peu de chance de faire des erreurs.
L'idée du buble sort est de comparer un élément à son voisin et de les permuter si l'élément est plus grand que celui-ci.

procedure BubbleSort(var tabNote: array of Integer);
var
  i,j: integer;
  temp: integer;
begin
  for i := high(tabNote) downto low(tabNote) do 
    for j := low(tabNote) to high(tabNote)-1 do 
      if tabNote[j] >tabNote[j + 1] then 
      begin
        temp := tabNote[j];
        tabNote[j] := tabNote[j + 1];
        tabNote[j + 1] := temp;
      end;
end;
 
Comme vous pouvez le voir un tel algorithme est lent, imaginez trier 1000 000 de donnés avec ça. Vous pouvez remarquer que lorsqu'on change de position l'élément, il arrive souvent que le tableau soit trié avant que l'algorithme soit fini. On peut aisément améliorer cela en ajoutant une petite vérification.

procedure BubbleSort(var tabNote: array of Integer); 
var 
  i,j: integer;
  temp: integer; 
  Test: Boolean; 
begin 
  for i := low(tabNote) to high(tabNote) do begin  
    Test := false;
    for j := low(tabNote) to high(tabNote) - 1 do begin 
      if tabNote[j] > tabNote[Succ(j)] then begin 
        temp := tabNote[j]; 
        tabNote[j] := tabNote[Succ(j)];
        tabNote[Succ(j)] := temp;
        Test := true; 
      end; 
    end; 
    if not Test then break; 
  end; 
end;

Complexité

La complexité est O(n^2) pour des données mélangées, mais l'approche est O(n) si la liste est presque trié au début.

Insertionsort

Cette méthode est semblable à celle que nous utilisons lorsqu'on trie des cartes. Nous prenons chaque nouvelle carte et nous l'insérons à la bonne position dans le paquet déjà trié. Ce tri est particulièrement rapide lorsqu'il y a peu de désordre.

procedure Insertionsort(var tabNote: array of Integer); 
var 
  i, j: Integer; 
   temp: Byte; 
begin 
  tabNote[0] := 0;          //garde l'algo hors de l'alignement 
  for i := 2 to high(tabNote) do begin 
                           //débute à 2 puisque le premier élément 
                           //n'est ni plus petit 
                           //ni plus grand que lui-même
    temp := tabNote[i] ;
    j := i; 
    while tabNote[Pred(j)] > temp do 
    begin
      tabNote[j] := tabNote[Pred(j)]; 
      dec(j);
    end; 
     tabNote[j] := temp;  //insère l'élément à la position trouvé  
  end; 
end;

Complexité

Le meilleur cas est n et le pire cas est O(n2)

Shellsort

Ce tri est similaire à l'insertionsort. Il est un peu plus performant. L'insertionsort n'est pas très rapide puisque les éléments sont bougés d'un espace à la fois. Nous pouvons le faire bouger de plusieurs espaces, jusqu'à ce que nous trouvions le bon emplacement. Pour arriver à une telle solution, nous pouvons réduire la grosseur de k, chaque fois que nous constatons que (j-k) ième élément est plus grand que l'élément actuel. Nous pouvons diviser k par 3 chaque fois.

procedure ShellSort(var A : ArrayType; N : integer);
var
  Done : boolean;
  Jump,I,J : integer;
begin
  Jump := N;
  while (Jump > 1) do
  begin
    Jump := Jump div 2;
    repeat
      Done := true;
      for J := 1 to (N - Jump) do
      begin
        I := J + Jump;
        if (A[J] > A[I]) then
        begin
          Swap(A[J], A[I]);
          Done := false
        end;
      end;
    until Done;
  end
end;

Quicksort

Quicksort est l'algorithme de tri le plus populaire. Sur une entré aléatoire, Quicksort est le plus rapide des algorithmes que je connais. Quicksort est implanté de façon récursif, il peut ainsi être plus complexe à comprendre.
1. On doit spécifier un élément x pour établir l'alignement.
2. Chaque élément plus petit que x sera mis à droite et ceux plus grand à gauche.
3. Quicksort s'appelle et passe les deux parties. Lorsqu'il est appelé avec un tableau de grosseur 1, un élément a été trié.
4. Lorsque quicksort revient de la récursion, les deux parties ont été triées et peuvent être mises ensemble.

procedure Quicksort(var tabNote: TArray,longueur, r: Integer); 
var 
  i, j: Integer; 
  temp, old: Byte; 
begin 
  old := tabNote[(longueur + r) div 2]; 
  i := longeur;
  j := r;  
  repeat   
    while tabNote[i] < old do inc(i);   
    while old < tabNote[j] do dec(j);   
    if i <= j then 
    begin   
      temp := tabNote[i];
      tabNote[i] := tabNote[j];   
      tabNote[j] := temp;    
      inc(i);     
      dec(j);   
    end; 
    until i > j;
    if longeur < j then Quicksort( longueur, j); 
    if i < r then Quicksort( i, r); 
end;

Complexité

Le pire cas est O(n2).
La moyenne des résultats : O(n log n)..

Selection Sort

Ce tri parcourt le tableau à trier, cherche l'élément à remplacer et le permute. Ce tri peut s'avérer intéressant, s'il y a peu d'affectation (fichier).

procedure SelectionSort(var tabNote: array of Integer);
var
  I, J, temp: Integer;
begin
  for I := Low(tabNote) to High(tabNote) - 1 do
    for J := High(tabNote) downto I + 1 do
      if tabNote[I] > tabNote[J] then
      begin
        temp := tabNote[I];
        tabNote[I] := tabNote[J];
        tabNote[J] := temp;
      end;
end;

Complexité

La moyenne des résultats :O( n^2).
Un programme utilisant de nombreux algorithmes de tri est disponible ici.

lundi 2 décembre 2002

Procédure stockée


PROCÉDURE STOCKÉE

Une procédure stockée ressemble à une fonction en delphi. Cette procédure est entreposée sur le serveur de base de données, le client peut l'appeler. Une procédure peut avoir 0 ou plusieurs paramètres et retourné 0 ou plusieurs valeurs. Une procédure stockée est compilée sur le serveur lorsqu'elle est créée. Une requête est compilée à chaque fois qu'elle est envoyée au serveur. Il y a quelques avantages à utiliser les procédures stockées:
  • Plus rapide, car elle est déjà compilée sur le serveur
  • Diminue le trafic réseau car seuls les paramètres et le nom de la requête transitent par le réseau
  • Partage des ressources, plusieurs programmes peuvent utilisé la procédure
  • facilitée de maintenance, la mise à jour de la procédure profite à tous les programmes

Syntaxe d'une procédure stockée


CREATE PROCEDURE name
[( param datatype [, param datatype ...])]
[RETURNS ( param datatype [, param datatype ...])]
AS
<procedure_body>;
<procedure_body> = [< déclaration_variables >]
< block>
< déclaration_variables> =
DECLARE VARIABLE var datatype;
[DECLARE VARIABLE var datatype; ...]
<block> =
BEGIN
< compound_statement>
[< compound_statement> ...]
END
< compound_statement> = {<block> | statement;}

Suppression d'une procédure stockée

La syntaxe de suppression de la procédure stockée est fort simple.
drop procedure nom_procedure;

Déclaration de variable

La déclaration d'une variable doit suivre la convention: <DECLARE VARIABLE nomVariable Type de donnée>. Les variables globales n'existent pas.

/*Déclaration de variable nécessaire à la procédure*/
DECLARE VARIABLE tmpChar CHAR(5);
DECLARE VARIABLE tmpInt integer;
DECLARE VARIABLE tmpNum NUMERIC(15,2);

Déclaration de variable

Condition

La syntaxe du if else... ressemble étrangement à celle présents sous delphi.
IF <Expression de la condition> THEN
  <code>
ELSE
  <code>
Dans l'expression de la condition, il est possible d'utiliser certain opérateur SQL
  • BETWEEN ... and ...
  • LIKE ...
  • IN (..., ..., ...
  • EXISTS (sous-requête)
  • ANY (sous-requête)
  • ALL (sous-requête)
  • IS NULL
  • IS NOT NULL

Boucle

Cet opérateur permet comme nous le savons d'exécuter du code une certaine quantité de fois
WHILE (<Expression de la condition>) DO
        <code>

Nous allons créer une table pour notre exemple.
 
CREATE TABLE personne
(
  nopersonne INTEGER NOT NULL,
  age    INTEGER NOT NULL,
  pays         CHAR(8)  NOT NULL,
CONSTRAINT PK_nopersonne PRIMARY KEY (nopersonne)
);


Imaginons maintenant que cette table renferme des milliers d'enregistrements et que nous désirons obtenir l'âge moyen des personnes vivant dans un pays donné. Il serait possible d'écrire la requête ci-dessous et de l'assigner à un ibquery, ibsql ou à un ibdataset.
 
select avg(age)from  personne where pays = :PPAYS


Maintenant regardons la solution avec une procédure stockée

create procedure GET_AGE (PPAYS CHAR(8))
returns (AVG_AGE DECIMAL(8,2))AS
DECLARE VARIABLE i integer;
begin
  WHILE (i <= 5) DO
  begin
    select avg(age)
    from personne
  where pays = :PPAYS
  into :AVG_AGE;
  IF (AVG_AGE = 0) THEN
       AVG_AGE = 1;
  i = i +1;
  end
end
 

Dans cette procédure stockée, le select ne retourne qu'une valeur, si plusieurs valeurs auraient été retournées, il
aurait fallu utilisé: FOR SELECT...DO

Notez que c'est la valeur de avg_age qui va être retournée. En utilisant le composant: IBStoredProc, vous n'avez qu'à renseignez la propriété database et transaction. Ensuite, vous allez voir toutes les procédures stockées dans la propriété StoredProcName, vous n'avez qu'à sélectionner celle que vous désirez. Dans notre exemple ça sera: GET_AGE. Il est possible de voir les paramètres d'entrée et de sortie de la procédure en cliquant dans la propriété Params du composant IBStoredProc. Lorsque nous voulons appeler la procédure stockée dans notre code delphi et obtenir la valeur de retour, il suffit de faire pour notre exemple:

var
  avgAge:float;
begin
  IBStoredProc1.ExecProc;  //IBStoredProc1 étant le nom du composant dans delphi
  avgAge := IBStoredProc.ParamByName('AVG_AGE').AsFloat; 
end;

Il est possible d'exécuter toute sorte de requêtes avec les procédures stockées. La procédure ci-dessous supprime
les personnes ayant l'âge passé en paramètre.

create procedure AGEINF18 (persage int) as
begin
  delete from personne
  where age = :persage;
end

On a vu rapidement l'utilisation et la création de procédure stockée. Une connaissance de programmation et 
de SQL facilite leur utilisation  et permet d'alléger le client.