Cours VB.NETDate de mise à jour : 05/12/2010
XV-J. Structure de programme : programmation à trois couches
XV-J-1. Introduction
XV-J-2. Architecture n-tiers
XV-J-3. Architecture 3 tiers
XV-J-4. Exemple 1 : Ma bibliothèque (en écrivant du code)
XV-J-4-a. Couche métier
XV-J-4-b. Couche d'accès aux données
XV-J-4-c. Couche de présentation : interface graphique
XV-J-5. Exemple 2 : Bibliothèque (avec Binding et génération automatique de l'IU)
XV-J-5-a. Couche métier
XV-J-5-b. Création de la source de données
XV-J-5-c. Génération automatique de l'interface utilisateur
XV-J-5-d. Création du Binding
XV-K. Utilisation de Patron (motif de conception, Design Pattern)
XV-K-1. Singleton
XV-K-2. Itérateur
XV-L. Linq dans les Classes
XV-J. Structure de programme : programmation à trois couches
XV-J-1. Introduction
Les programmes les plus fréquemment développés sont ceux utilisant une interface utilisateur permettant de travailler sur un ensemble de données, par exemple les clients d'une entreprise. Il faut pouvoir ajouter, supprimer, modifier les clients, en afficher la liste. Une base de données permet de stocker les données.
Il y a quelques années, dans l'interface utilisateur, du code lisait, modifiait la base de données. Très vite, sur un projet important cette approche, non architecturée, montrait ses limites.
Aussi très rapidement, en programmation procédurale, le besoin de travailler sur des couches est apparu:
Pour afficher la liste des client de l'entreprise:
- La couche présentation: une windowsForm affichait la liste ; elle faisait appel à:
- La couche métier: une routine ChargeListe située dans un module standard sélectionnait les clients, elle faisait appel à:
- La couche données qui lisait la base de données.
Cela a été formalisé en programmation objet.
A noté que si les divers couches sont sur les ordinateurs différents, on parle d'architecture distribuée.
XV-J-2. Architecture n-tiers
De l'anglais tier signifiant étage ou niveau.
Architecture logicielle impliquant plusieurs composants, chaque composant étant le client d'un et le serveur d'un autre.
Le cas le plus simple de ce type d'architecture est le modèle Client/Serveur qui est en 2-tiers.
Tier 'Client' - Contient l'interface utilisateur, adresse des requêtes au serveur.
Tier 'Serveur' - Contient la base de données. Reçoit les requêtes, renvoie des données.
Dans les modèles 3-tiers et plus, il existe des composants intermédiaires qu'on appelle également middleware.
Un exemple typique d'un système 3-tier est le suivant :
- Tier de présentation - c'est principalement l'interface utilisateur. contient les différents types de clients, léger (Web, ASP, JSP) ou lourd (Swing, WinForm)
- Tier des règles de gestion: couche métier: Business Logic.
- Tier de base de données - les programmes du deuxième tier font appel à ce dernier pour consulter ou mettre à jour les données relatives à l'entreprise.
Sur le même schéma, on peut ajouter des intermédiaires supplémentaires et obtenir une architecture 4, 5, …, n-tier.
Un exemple d'architecture à 5 couches logicielles :
- Présentation: Contient tous les composants graphiques du module composant l'interface homme-machine (fenêtres, contrôles utilisateur…) avec le code propre à l'affichage de leur représentation et de leur contenu.
Cette couche ne peut référencer que les couches "Référence" et "Application". Mettre le moins de code possible dans cette couche.
- Application: Contient tous les contrôleurs de cas d'utilisation du module. Cette couche assure le liant entre les composants graphiques et les composants métier.
Cette couche ne peut référencer que les couches "Métier", "Persistance" et "Référence"
- Métier: Contient tous les composants métier dont le module a la responsabilité. Ces composants métier ont en charge la gestion du cycle de vie des objets métier gérés par le module. Cette couche ne peut référencer que les couches "Référence" et "Persistance"
- Référence: Cette couche contient les objets de données pures qui transitent entre toutes les autres couches. Ces objets sont aussi parfois nommés DataValues ou DataObjects.
- Persistence: Contient les composants assurant le mapping entre les objets définis dans la couche Métier et les composants de stockage définis dans la base de Données.
Cette couche ne peut référencer que les couches "Référence" et la base de données. Concrètement, il s'agit de la seule couche ayant un lien avec la base de données.
XV-J-3. Architecture 3 tiers
- L'architecture 3-tier (de l'anglais tier signifiant étage ou niveau) vise à séparer très nettement trois couches logicielles au sein d'une même application ou système, à modéliser et présenter cette application comme un empilement de trois couches, étages, niveaux ou strates dont le rôle est clairement défini :
- la présentation des données : correspondant à l'affichage, la restitution sur le poste de travail, le dialogue avec l'utilisateur,
- le traitement métier des données : correspondant à la mise en œuvre de l'ensemble des règles de gestion et de la logique applicative, c'est à ce niveau que se trouvent toutes les règles de gestion, et toute l'intelligence de la démarche.
- et enfin l' accès aux données persistantes (persistancy en anglais) : correspondant aux données qui sont destinées à être conservées sur la durée.
Relation entre les couches: Les services d'une couche sont mis à disposition de la couche supérieure.
XV-J-4. Exemple 1 : Ma bibliothèque (en écrivant du code)
Créons une application permettant de saisir , d'enregistrer, de voir des fiches 'Livre':
Il faut créer des objets 'Livre' puis un objet 'Livres' contenant une collection de tous les livres (Couche métier). Cette collection doit pouvoir être enregistrée puis lue sur disque (Couche d'accès au données). Enfin on doit pouvoir afficher le détail d'un livre (Interface utilisateur).
Couche métier :
- Classe " ClasseLivre " : entité métier, classe permettant d'instancier un livre avec comme propriété : Titre, auteur..
- Classe " ClasseLivres " (avec un 's'): classe comprenant une collection d'objet " Livre ". Elle possède des méthodes permettant d'ajouter un livre, de récupérer un livre dans la collection, de passer au précédent, au suivant...
Couche d'accès aux données :
- LoadData pour lire la collection de livres à partir d'un fichier (xml dans notre exemple)
- SaveData pour enregistrer la collection de livres dans un fichier (xml dans notre exemple)
Interfaces graphiques :
- 1 Formulaire principal permettant de saisir un nouveau livre et de faire défiler les livres.
XV-J-4-a. Couche métier
Créons la ClasseLivre", elle doit contenir:
2 property public : 'Titre' et 'Auteur'
2 variables private : m_titre et m_Auteur
Cela permettra d'instancier un objet livre et d'utiliser ses propriétés:
Exemple:
Dim livre As New ClasseLivre : livre.Nom= "Cours VB"
Voici la classe:
Public Class ClasseLivre
Private m_Titre As String
Private m_Auteur As String
Public Property Titre () As String
Get
Return m_Titre
End Get
Set (ByVal value As String )
m_Titre = value
End Set
End Property
Public Property Auteur () As String
Get
Return m_Auteur
End Get
Set (ByVal value As String )
m_Auteur = value
End Set
End Property
End Class
|
Créons la ClasseLivres" (avec un 's'), elle doit contenir:
1 collection nommé ListLivre d'objet générics: Collection.Generic.List (Of Classelivre)
C'est une collection typée, elle ne peut contenir que des 'Livre'
On instancie aussi un objet ad d'accès aux données.
La méthode public LivrePointé retourne le livre en cours, les méthodes FirstLivre, LastLivre, NextLivre, PreviousLivre permettent de se déplacer dans les livres. On peut ajouter un livre avec AddLivre.
Une variable nommée m_numéro sert dans la classe de "pointeur" du livre courant.
Pour enregistrer ou charger la collection de livre sur disque , il y a les 2 méthodes SaveData et LoadData. Elle appelle des méthodes de la couche de données.
Quand cette classe est instanciée elle charge les données (la procédure New appelle LoadData).
Imports System. Collections . Generic
Public Class ClasseLivres
Private ListLivre As New List (Of ClasseLivre)
Private m_numero As Integer
Private ad As New AccesAuxDonnees
Public Sub New ()
Me. LoadData ()
End Sub
Public Sub LoadData ()
ad. LoadData (ListLivre)
m_numero = 0
End Sub
Public Sub SaveData ()
ad. SaveData (ListLivre)
End Sub
Public Function LivrePointé () As ClasseLivre
If ListLivre. Count < > 0 Then
If m_numero < ListLivre. Count Then
Return ListLivre. Item (m_numero)
Else
Return Nothing
End If
Else
Return Nothing
End If
End Function
Public Sub AddLivre (ByVal l As ClasseLivre)
ListLivre. Add (l)
End Sub
Public Sub RemoveLivre ()
ListLivre. RemoveAt (m_numero)
End Sub
Public Sub UpdateLivre (ByVal l As ClasseLivre)
ListLivre. Item (m_numero) = l
End Sub
Public Sub NextLivre ()
If m_numero < ListLivre. Count Then
m_numero + = 1
End If
End Sub
Public Sub PreviousLivre ()
If m_numero > 0 Then
m_numero - = 1
End If
End Sub
Public Sub FirstLivre ()
m_numero = 0
End Sub
Public Sub LastLivre ()
m_numero = ListLivre. Count - 1
End Sub
End Class
|
Il aurait été plus élégant d'intancier l'objet d'accès au données dès le début de la classe comme cela:
Public Class ClasseLivres
Private ListLivre As New List (Of ClasseLivre)
Private m_numero As Integer
Dim ad As New AccesAuxDonnees
|
XV-J-4-b. Couche d'accès aux données
Ici nous enregistrons les données dans un fichier XML nommé "Meslivres.Xml" (il sera dans le répertoire bin/Debug lors de la conception, et dans le répertoire de l'exécutable si on installe le logiciel). On utilise la sérialisation et les Stream. (Voir chapitre sur la sérialization pour plus de détails)
Les Sub ont un paramètre: la collection de ClasseLivre.Ce paramètre est passé avec ByRef .
Imports System. Xml . Serialization
Imports System. IO
Public Class AccesAuxDonnees
Public Sub SaveData (ByVal list As Collections. Generic . List (Of ClasseLivre))
Dim serialXML As Xml. Serialization . XmlSerializer = Nothing
Dim streamIO As StreamWriter = Nothing
Try
serialXML = New Xml. Serialization . XmlSerializer (GetType (Collections. Generic . List (Of ClasseLivre)))
streamIO = New StreamWriter (" Meslivres.Xml " )
serialXML. Serialize (streamIO, list)
Catch ex As Exception
Throw ex
Finally
If streamIO IsNot Nothing Then
streamIO. Close ()
End If
End Try
End Sub
Public Sub LoadData (ByRef list As Collections. Generic . List (Of ClasseLivre))
Dim streamIO As StreamReader = Nothing
Dim serialXML As Xml. Serialization . XmlSerializer = Nothing
Try
If System. IO . File . Exists (" Meslivres.Xml " ) = True Then
serialXML = New Xml. Serialization . XmlSerializer (GetType (Collections. Generic . List (Of ClasseLivre)))
streamIO = New StreamReader (" Meslivres.Xml " )
list = CType (serialXML. Deserialize (streamIO), Collections. Generic . List (Of ClasseLivre))
End If
Catch ex As Exception
Throw ex
Finally
If streamIO IsNot Nothing Then
streamIO. Close ()
End If
End Try
End Sub
End Class
|
XV-J-4-c. Couche de présentation : interface graphique
On instancie un objet Livres, cet objet contient la collection de livre.
Il suffit ensuite d'utiliser Livres.LivrePointé qui est le livre en cours, Livres.NextLivre() pour passer au livre suivant, Livres.PreviousLivre pour passer au précédent.
Quand on clique sur 'Enregister livre' on effectue Livres.AddLivre.
Quand on clique sur 'Enregister tous les livres' on effectue Livres.SaveData ( qui fait appel à la couche de données).
Deux petites Sub LireLivre et AfficheLivre permettent de remplir ou de lire les TextBox à partir d'un objet livre.
Public Class InterfaceGraphique
Dim Livres As New ClasseLivres
Dim iFlagNewLivre As Integer
Sub LireLivre (ByVal l As ClasseLivre)
l. Titre = TextBoxTitre. Text
l. Auteur = TextBoxAuteur. Text
End Sub
Sub AfficheLivre (ByVal l As ClasseLivre)
If l IsNot Nothing Then
TextBoxTitre. Text = l. Titre
TextBoxAuteur. Text = l. Auteur
End If
End Sub
Private Sub ButtonNext_Click (ByVal sender As System. Object , ByVal e As System. EventArgs ) _
Handles ButtonNext. Click
Livres. NextLivre ()
AfficheLivre (Livres. LivrePointé )
iFlagNewLivre = False
End Sub
Private Sub ButtonPrevious_Click (ByVal sender As Object, ByVal e As System. EventArgs ) _
Handles ButtonPrevious. Click
Livres. PreviousLivre ()
AfficheLivre (Livres. LivrePointé )
iFlagNewLivre = False
End Sub
Private Sub ButtonNew_Click (ByVal sender As System. Object , ByVal e As System. EventArgs ) _
Handles ButtonNew. Click
TextBoxTitre. Text = " "
TextBoxAuteur. Text = " "
iFlagNewLivre = True
End Sub
Private Sub ButtonEnregister_Click (ByVal sender As System. Object , ByVal e As System. EventArgs ) _
Handles ButtonEnregister. Click
Dim NouveauLivre As New ClasseLivre
If iFlagNewLivre = True Then
LireLivre (NouveauLivre)
Livres. AddLivre (NouveauLivre)
Livres. LastLivre ()
Else
LireLivre (NouveauLivre)
Livres. UpdateLivre (NouveauLivre)
End If
iFlagNewLivre = False
End Sub
Private Sub ButtonEnregistertous_Click (ByVal sender As System. Object , ByVal e As System. EventArgs )
_Handles ButtonEnregistertous. Click
Livres. SaveData ()
End Sub
End Class
|
XV-J-5. Exemple 2 : Bibliothèque (avec Binding et génération automatique de l'IU)
C'est le même programme, mais on va laisser le soin à VB de générer automatiquement l'interface utilisateur et les liens (Binding) entre cette interface et les données.
La couche d'accès aux données est la même.
On a une Form vide.
XV-J-5-a. Couche métier
ClasseLivre est identique, par contre ClassesLivres est plus simple: elle contient uniquement la collection généric ListLivre contenant les livres
(Et SaveData et Load Data)
Imports System. Collections . Generic
Public Class ClasseLivre
Private m_Titre As String
Private m_Auteur As String
Public Property Titre () As String
Get
Return m_Titre
End Get
Set (ByVal value As String )
m_Titre = value
End Set
End Property
Public Property Auteur () As String
Get
Return m_Auteur
End Get
Set (ByVal value As String )
m_Auteur = value
End Set
End Property
Public Function GetTitre () As String
Return m_Titre
End Function
End Class
Public Class ClasseLivres
Public ListLivre As New Collections. Generic . List (Of ClasseLivre)
Private ad As New AccesAuxDonnees
Public Sub LoadData ()
ad. LoadData (ListLivre)
End Sub
Public Sub SaveData ()
ad. SaveData (ListLivre)
End Sub
End Class
|
Ici ListLivre est Public.
XV-J-5-b. Création de la source de données
Il faut ensuite créer une source de données:
Comme on affiche des livres, la source c'est la ClasseLivre.
Menu 'Données'=> 'Ajouter une nouvelle source de données'
Ici la source de données n'est pas une base de données mais un Objet:
On clique sur 'Objet' puis bouton 'Suivant'.
On déroule livre, qui est le nom de la solution, puis on clique sur 'ClasseLivre' et sur le bouton suivant.
Puis Ok; la source de données est créée.
XV-J-5-c. Génération automatique de l'interface utilisateur
Visual Studio dispose d'une fenêtre 'Sources de données' depuis laquelle vous pouvez faire glisser des éléments jusqu'à un formulaire pour créer automatiquement des contrôles liés aux données qui affichent des données.
Afficher les sources de données:
Menu 'Données' puis 'Afficher les sources de données'
Il apparaît à droite la fenêtre 'Sources de données'
Dérouler 'livre' et cliquer sur 'ClasseLivre'
Pour générer, non pas une grid mais des zones de saisie, dérouler la liste de ClasseLivre et cliquer sur 'Détails'.
Enfin faire un drag ans drop à partir de ClasseLivre et déposer le sur la form de gauche (qui est vide au départ)
Miracle: il apparaît automatiquement:
- des zones textbox pour chaque properties de la classe avec un label devant.
- une barre de navigation (tout est généré automatiquement: les bitmap des boutons dans les ressources Setting...)
- Un composant BindingSource.(Il fait le lien entre l'interface et la source de données)
- Un composant BindingNavigator.(Il gère la barre de navigation)
On voit bien en dessous les 2 composants qui ont été ajoutés.
XV-J-5-d. Création du Binding
Maintenant ,il faut indiquer la source de données, le Datasource du BindingSource: c'est la collection MesLivres.ListLivre (C'est pour cela que la collection ListLivre est Public)
Public Class Form1
Dim MesLivres As New ClasseLivres
Private Sub Form1_Load (ByVal sender As System. Object , ByVal e As System. EventArgs ) Handles MyBase. Load
ClasseLivreBindingSource. DataSource = MesLivres. ListLivre
End Sub
Private Sub SauveLivres_Click (ByVal sender As System. Object , ByVal e As System. EventArgs ) _
Handles Button1. Click
MesLivres. SaveData ()
End Sub
Private Sub LoadLivre_Click (ByVal sender As System. Object , ByVal e As System. EventArgs ) _
Handles Button2. Click
MesLivres. LoadData ()
ClasseLivreBindingSource. DataSource = MesLivres. ListLivre
End Sub
End Class
|
P.... !!ça marche!!
Ici ,les différentes parties du logiciel sont dans la même solution. Rien n'empêche de:
- Mettre les classes dans un même fichier .vb
- Mettre les classes dans différents fichiers .vb
- Créer les Classes dans une solution, la générer, inclure dans les références du projet principal les dll.
- Enfin si divers parties sont sur différentes machines, on parle d'architecture distribuée.
XV-K. Utilisation de Patron (motif de conception, Design Pattern)
Un motif de conception (design pattern) est un concept destiné à résoudre les problèmes récurrents en POO. En français on utilise aussi les termes modèle de conception, patron de conception ou de Patron.
Pour ne pas avoir à réinventer la roue, les patrons décrivent des solutions standards pour répondre à des problèmes de conception ou d'architecture .C'est une formalisation de bonnes pratiques, ce qui signifie qu'on privilégie les solutions éprouvées.
Il ne s'agit pas de fragments de code, mais d'une méthode de conception.
Les auteurs des principaux design patterns (il y en a 23), plus connus sous le nom de Gang Of Four, sont Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides. Les DP qu'ils ont conçus sont considérés comme la base de tous les autres .
XV-K-1. Singleton
Parfois , on a besoin d'une classe avec laquelle on veut créer une instance et une seule.
Il faut créer une classe:
- Ou il ne soit pas possible de créer plusieurs instances:
New , le constructeur, doit-être toujours private : cela empêche d'écrire 'Dim myobjet As New MyClasse' et empêche donc d'instancier.
On utilise donc:
- Ou une méthode de classe permet de créer une instance et une seule. Une méthodes de classe nommée habituellement 'GetInstance' peut être appelée (sans avoir à instancier) directement sur le nom de la classe. Shared Function getInstance() As sing
Cette fonction qui s'appelle toujours getInstance va servir à instancier une fois la variable Instance.
Shared instance As sing
Cette variable est la base du Singleton. Elle s'appelle Instance (par convention) elle est du même type que la class et contient l'instance unique.
Public Class sing
Shared instance As sing
Private Sub New ()
MyBase. New ()
End Sub
Shared Function getInstance () As sing
If IsNothing (instance) Then
instance = New sing
End If
Return instance
End Function
. . .
. . .
End Class
|
Comment utiliser cette Classe?
Dim t As sing = sing. getInstance
|
Remarque:
- Si on fait ensuite Dim t1 As sing = sing.getInstance c'est la même instance qui est retournée. On ne peut en créer qu'une..
- Si on écrit Dim t As New sing :cela plante.
On peut ajouter une protection contre les multi thread trop rapide avec
SyncLock GetType(sing)
Shared Function getInstance () As sing
If IsNothing (instance) Then
SyncLock GetType (sing)
If IsNothing (instance) Then
instance = New sing
end if
End SyncLock
End If
Return instance
End Function
|
XV-K-2. Itérateur
Un itérateur est un objet qui permet de parcourir tous les éléments contenus dans un conteneur.
Dans la programmation procédurale on utilise souvent une boucle (for next) avec un index , pour accéder séquentiellement à tous les éléments d'un tableau. Cette méthode se nomme Indexation.
En programmation objet, le but d'un itérateur est de permettre à son utilisateur de parcourir le conteneur, c'est-à-dire d'accéder séquentiellement à tous ses éléments, de consulter l'élément courant. L'itérateur permet isoler l'utilisateur de la structure interne du conteneur, parfois complexe.
Les itérateurs ont certains avantages:
- Une simple boucle n'est pas adapté à toutes les structures de données, en particulier celles qui n'ont de méthode d'accès à un élément quelconque ou celles à accès à un élément quelconque très lent.
- Les vrai itérateurs peuvent être écrit pour toutes sortes de structures de données: liste arbre , liste chaînée.., s'il y a changement dans l'organisation de la structure de données, celui qui utilise l'itérateur n'a pas à s'en soucier.
- Un vrai itérateur peut implanter des conditions additionnelles sur l'accès aux éléments, par exemple pour "sauter ou ne pas sauter".
- Un vrai itérateur peut dans certains cas permettre que le conteneur soit modifié, sans être invalidé pour autant. Par exemple, après qu'un itérateur s'est positionné derrière le premier élément, il est possible d'insérer d'autres éléments au début du conteneur avec des résultats prévisibles. Avec un index on aurait plus de problèmes, parce que la valeur de l'index devrait elle aussi être modifiée en conséquence.
En VB, il existe des itérateurs 'clé en main' pour les collections par exemple, mais ils n'ont pas tous les avantages décrit ci-dessus.
La Classe System.Array et celles qui implémentent l'interface IEnumerable possèdent 2 méthodes pour itérer:
- Une boucle For Each pour parcourir tous les éléments de l'Array.
- L'utilisation d'un énumérateur.
Voyons comment faire:
On peut aussi utiliser dans ce cas Getenumerator pour créer un énumérateur: Il permet de lire du premier élément au dernier:
Dans l'énumérateur l'élément courant est Current.
Pour passer au suivant , on utilise MoveNext.
Reset réinitialise.
Initialement le pointeur est avant le premier élément, aussi avant d'utiliser Current il faut faire MoveNext.
Attention, on ne peut que lire les données dans l'ordre; si on modifie la collection, il faut redémarrer la lecture.
Dim myArr (4) As String
myArr (0) = " toto "
myArr (1) = " lulu "
myArr (2) = " bibi "
myArr (3) = " tata "
Dim i As Integer = 0
Dim myEnumerator As System. Collections . IEnumerator = myArr. GetEnumerator ()
While myEnumerator. MoveNext () And Not (myEnumerator. Current Is Nothing )
Console. WriteLine (" [{0}] {1} " , i, myEnumerator. Current )
i + = 1
End While
|
XV-L. Linq dans les Classes
Lire le chapitre Linq dans la partie langage VB.
Exemple de Microsoft.
Créer 4 étudiants ayant un nom, prénom et des notes.(on les met dans une ArrayList) Rechercher les étudiants dont la première note est >95.
Public Class Student
Public FirstName As String
Public LastName As String
Public Scores As Integer ()
End Class
Sub Main ()
Dim student1 As New Student With {. FirstName = " Svetlana " , . LastName = " Omelchenko " , _
. Scores = New Integer () {98, 92, 81, 60}}
Dim student2 As New Student With {. FirstName = " Claire " , . LastName = " O'Donnell " , _
. Scores = New Integer () {75, 84, 91, 39}}
Dim student3 As New Student With {. FirstName = " Cesar " , . LastName = " Garcia " , _
. Scores = New Integer () {97, 89, 85, 82}}
Dim student4 As New Student With {. FirstName = " Sven " , . LastName = " Mortensen " , _
. Scores = New Integer () {88, 94, 65, 91}}
Dim arrList As New ArrayList ()
arrList. Add (student1)
arrList. Add (student2)
arrList. Add (student3)
arrList. Add (student4)
Dim query = From student As Student In arrList _
Where student. Scores (0) > 95 _
Select student
For Each student As Student In query
Console. WriteLine (student. LastName & " : " & student. Scores (0))
Next
Console. WriteLine (" Press any key to exit. " )
Console. ReadKey ()
End Sub
|
Module ' Output: ' Omelchenko: 98 ' Garcia: 97
Les sources présentés sur cette page sont libres de droits,
et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright © .
Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu :
textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts.
Cette page est déposée à la SACD.
|