Rubriques

Introduction Haut de la page

Ce document présente des modèles d'objet et de données relationnels et fournit une description abrégée d'une structure de persistance.

Bases de données relationnelles et orientation objet Haut de la page

Les bases de données relationnelles et l'orientation objet ne sont pas entièrement compatibles. Elles représentent deux vues différentes du monde : dans un SGBDR, tout ce que vous voyez, ce sont des données ; dans un système orienté objet, seul le comportement est visible. Ce n'est pas qu'une perspective soit meilleure que l'autre : le modèle orienté objet tend à bien fonctionner pour des systèmes ayant un comportement complexe et spécifique à l'état dans lesquels les données sont secondaires, ou dans des systèmes dans lesquels les données sont accédées par navigation uniquement selon une hiérarchie naturelle (par exemple, des nomenclatures). Le modèle SGBDR est parfaitement adapté aux applications générant des rapports et aux systèmes dans lesquels les relations sont dynamiques ou ad-hoc.

Le problème qui se pose est que de nombreuses informations sont stockées dans des bases de données relationnelles et si des applications orientées objet souhaitent accéder à ces données, elles doivent pouvoir lire et écrire dans un SGBDR. En outre, les systèmes orientés objet nécessitent souvent de partager des données avec des systèmes non orientés objet. Il est naturel, de ce fait, d'utiliser un SGBDR comme mécanisme de partage.

Alors que les conceptions relationnelles et orientées objet partagent des caractéristiques communes (un attribut d'objet est par conception similaire à des colonnes d'entités), les différences fondamentales font un défi de l'intégration parfaite. La principale différence réside dans le fait que les modèles de données exposent les données (via des valeurs de colonne) tandis que les modèles d'objet les masquent (les encapsulant derrière ses interfaces publiques).

Modèle de données relationnel Haut de la page

Le modèle relationnel est composé d'entités et de relations. Une entité peut être une table physique ou une projection logiques de plusieurs tables, appelées également vue. La figure ci-dessous illustre les tables LINEITEM, ORDER et PRODUCT, ainsi que leurs différentes relations. Un modèle relationnel présente les éléments suivants :

Diagramme détaillé dans le contenu.

Modèle relationnel

Une entité comporte des colonnes. Chaque colonne est identifiée par un nom et un type. Dans la figure ci-dessus, l'entité LINEITEM est composée des colonnes LineItem_Id (la clé primaire), Description, Price, Quantity, Product_Id et Order_Id (les deux dernières sont les clés externes qui relient l'entité LINEITEM aux entités ORDER et PRODUCT).

Une entité comporte des enregistrements ou des lignes. Chaque ligne représente un ensemble unique d'informations qui représente de manière unique les données persistantes d'un objet.  

Chaque entité présente une ou plusieurs clés primaires. Elles identifient de manière unique chaque enregistrement (par exemple, l'Id est la clé primaire de la table LINEITEM).

La prise en charge des relations est spécifique au fournisseur. L'exemple illustre le modèle logique et les relations entre les tables PRODUCT et LINEITEM. Dans le modèle physique, les relations sont typiquement implémentées à l'aide de références de clé externe/clé primaire. Si une entité fait référence à une autre, elle contient des colonnes qui sont des clés externes. Les colonnes de clé externe contiennent des données qui peuvent associer des enregistrements spécifiques de l'entité à l'entité associée.

Les relations présentent une multiplicité (également connue en tant que cardinalité). Les cardinalités courantes sont 1 à 1, 1 à n, n à 1 et n à n. Dans l'exemple, LINEITEM présente une relation 1 à 1 avec PRODUCT et PRODUCT une relation 0 à n avec LINEITEM.

Modèle Objet Haut de la page

Un modèle Objet contient, entre autres choses, des classes (voir [UML01] pour une complète définition d'un modèle d'objet). Les classes définissent la structure et le comportement d'un ensemble d'objets, parfois appelés instances d'objet. La structure est représentée sous forme d'attributs (valeurs de données) et d'associations (relations entre classes). La figure suivante illustre un diagramme de classe simple, ne présentant que les attributs (données) des classes.

Diagramme détaillé dans le contenu.

Modèle Objet (diagramme de classes)

Une commande porte un numéro (le numéro de commande) et une association à 1 ou plusieurs (1..*) lignes article. Chaque ligne article présente une quantité (la quantité commandée).

Le modèle d'objet prend en charge l'héritage. Une classe peut hériter des données et du comportement d'une autre classe (par exemple, des produits SoftwareProduct et HardwareProduct héritent d'attributs et de méthodes de la classe Product).

Structures de persistance Haut de la page

La majorité des applications métier utilisent une technologie relationnelle comme magasin de données physiques. Le défi auquel font face les développeurs d'applications orientées objet est de séparer suffisamment et d'encapsuler la base de données relationnelle de telle sorte que les modifications du modèle de base ne "brisent" pas le modèle objet, et vice versa. De nombreuses solutions existent qui permettent aux applications d'accéder directement aux données relationnelles. Le défi consiste alors à parvenir à une intégration transparente entre le modèle objet et le modèle de données.

Les interfaces de programmation d'application (API) de base de données existent dans des versions standard (telle que ODBC de Microsoft) ou sont propriétaires (liaisons natives à des bases de données spécifiques). Les API fournissent des services d'application en langage LMD qui permettent aux applications d'accéder aux données relationnelles brutes. Dans des applications orientées objet, les données doivent subir une translation relationnelle objet pour pouvoir être utilisées par l'application. Ceci nécessite qu'une quantité considérable du code d'application effectue une translation des résultats de l'API de la base de données brute en objets d'application. Le but de la structure relationnelle objet est d'encapsuler de manière générique le magasin de données physiques et de fournir des services de translation d'objets appropriés.

Diagramme détaillé dans le contenu.

Objectif d'une structure de persistance

Les développeurs d'applications passent plus de 30% de leur temps à mettre en oeuvre l'accès aux bases de données relationnelles dans des applications orientées objet. Si l'interface relationnelle objet n'est pas correctement mise en oeuvre, l'investissement est perdu. L'implémentation d'une structure relationnelle objet capture cet investissement. La structure relationnelle objet peut être réutilisée dans les applications ultérieures, réduisant le coût d'implémentation relationnel objet à moins de 10% des coûts d'implémentation globaux. Le coût le plus important à prendre en considération lors de l'implémentation d'un système est la maintenance. Plus de 60% des coûts totaux d'un système au cours de son cycle de vie complet peuvent être attribués à la maintenance. Un système relationnel faiblement mis en oeuvre est une charge de maintenance à la fois technique et financière.

Caractéristiques essentielles d'une structure relationnelle objet Haut de la page

  • Performances. Une attention particulière doit être portée à la décomposition des objets en données et à la composition des objets à partir de données. Dans les systèmes où le rendement des données est élevé et constitue un point sensible, c'est souvent le talon d'Achille d'une d'accès conçue de manière inappropriée.
  • Réduire les compromis de conception. Un pattern familier pour les technologistes objet ayant créés des systèmes qui utilisent des bases de données relationnelles, consiste à affiner le modèle Objet pour faciliter le stockage dans des systèmes relationnels et de modifier le modèle relationnel pour faciliter le stockage des objets. Alors que des réglages mineurs sont souvent nécessaires, une couche d'accès parfaitement conçue réduit la détérioration de la conception du modèle relationnel et objet.
  • Extensibilité. La couche d'accès est une structure qui permet aux développeurs d'applications d'étendre la structure si certaines fonctionnalités y sont souhaitées. En général, une couche d'accès prend en charge, sans extension, 65 à 85% des exigences de stockage des données d'une application. Si la couche d'accès n'est pas conçue comme une structure extensible, répondre aux derniers 35 à 15% des exigences de stockage des données d'une application peut s'avérer très difficile et onéreux.
  • Documentation. La couche d'accès est à la fois un composant fonctionnel et structurel. L'API d'un composant fonctionnel doit être clairement définie, parfaitement documentée, et facilement compréhensible. Comme précédemment indiqué, la couche d'accès est conçue pour être étendue. Une structure extensible doit être très détaillée. Les classes destinées à être surclassées doivent être identifiées. Les caractéristiques du protocole de chaque classe concernée doivent être spécifiées (par exemple, publique, privée, protégée, finale, etc.). En outre, une partie importante de la conception de la structure en couches d'accès peut être exposée et documentée pour faciliter l'extensibilité.
  • Prise en charge des mappages relationnels objet courants. Une couche d'accès doit fournir la prise en charge de certains mappages relationnels objet de base sans le besoin d'extension. Ces mappages relationnels objet sont présentés dans une section ultérieure de ce document.
  • Interfaces de persistance. Dans une application orientée objet, le modèle métier d'une application objet capture la connaissance sémantique du domaine du problème. Les développeurs doivent manipuler et interagir avec des objets sans devoir trop s'inquiéter à propos du stockage de données et des détails d'extraction. Un sous-ensemble bien défini d'interfaces persistantes (enregistrer, supprimer, trouver) doit être fourni aux développeurs d'applications.

Services relationnels objets courants Haut de la page

Des patterns courants émergent d'applications relationnelles objet. Les professionnels informatiques qui ont à plusieurs reprises croisés cette lacune commencent à comprendre et à reconnaître certaines structures et certains comportements montrant des applications relationnelles objet réussies. Ces structures et ces comportements ont été formalisés par les spécifications de haut niveau des services CORBA (qui s'appliquent tout aussi bien à des systèmes COM/DCOM).

Les spécifications des services CORBA qui sont applicables et utiles à prendre en considération pour le mappage relationnel objet sont les suivantes :

Les sections suivantes utilisent ces catégories pour structurer une discussion sur les services relationnels objet courants. Pour plus de détails, le lecteur est invité à se rapporter aux spécifications CORBA appropriées.

Persistance Haut de la page

La persistance est un terme utilisé pour décrire comment les objets utilisent un support de stockage secondaire pour gérer leur état à travers des sessions discrètes. La persistance permet à un utilisateur d'enregistrer des objets dans une session et d'y accéder lors d'une session ultérieure. Lorsqu'ils sont accédés ultérieurement, leur état (par exemple, attributs) sera le même que celui de la session précédente. Dans des systèmes multi-utilisateurs, il peut ne pas en être de même car d'autres utilisateurs peuvent accéder aux mêmes objets et les modifier. La persistance est associée à d'autres services abordés dans cette section. La considération des relations, de la simultanéité et autres est intentionnelle (et cohérente avec la décomposition des services par CORBA).

Exemples de services spécifiques fournis par la persistance :

  • Gestion des connexions de source de données : les applications relationnelles objet doivent initialiser une connexion avec la source de données physiques. Les systèmes de base de données relationnelle nécessite l'identification du serveur et de la base de données. La spécificité de la gestion des connexions tend à être spécifique au fournisseur de base de données et la structure doit être conçue conformément de manière flexible.
  • Extraction d'objet : lorsque des objets sont restaurés de la base de données, des données sont extraites de la base de données et traduites en objets. Ce processus implique l'extraction des données de structures spécifiques à la base de données extraites de la source de données, la conversion des données de types de base de données en types et/ou classes d'objet appropriés, la création de l'objet approprié et la définition des attributs spécifiques à l'objet.
  • Stockage d'objets : le processus de stockage d'objets reflète l'extraction d'objets. Les valeurs des attributs appropriés sont extraites de l'objet, une structure spécifique à la base de données est créée avec les valeurs d'attributs (il peut s'agir d'une chaîne SQL, d'une procédure stockée ou d'un appel de procédure éloignée spécial), et la structure est envoyée à la base de données.
  • Suppression d'objets : lorsque des objets sont supprimés d'un système, les données qui leur sont associées sont supprimées de la base de données relationnelle. La suppression d'objets nécessite que les informations appropriées soient extraites de l'objet, qu'une demande d'objet soit constituée (il peut s'agir d'une chaîne SQL, d'une procédure stockée ou d'un appel de procédure éloignée) et que celle-ci soit soumise à la base de données. Notez que dans certains langages, tels que Smalltalk et Java, la suppression explicite n'est pas prise en charge. En revanche, une stratégie appelée récupération de place l'est. Les structures de persistance prenant en charge ces langages doivent fournir une alternative pour retirer des données de la base de données, une fois que les applications n'y font plus référence. Un moyen courant consiste pour la base de données à gérer les nombres de références correspondant au nombre de fois qu'un objet est référencé par les autres objets. Lorsque le nombre de référence d'un objet tombe à zéro, aucun objet n'y fait plus référence et il est alors possible de le supprimer. Il peut être acceptable de supprimer des objets dont le nombre de références est à zéro, puisque même si un objet n'est plus référencé, il peut toujours être demandé. Une règle s'appliquant à toute la base de données lorsque la suppression d'objets est autorisée, demeure nécessaire.

Requête Haut de la page

Le stockage d'objets persistants est peu utile sans mécanisme de recherche et d'extraction des objets spécifiques. Les fonctions de requête permettent aux applications d'interroger et d'extraire des objets en fonction de critères variés. Les opérations de requête de base fournies par une structure de mappages relationnelle objet sont "find" et "find unique". L'opération "find unique" extrait un objet spécifique et l'opération "find" renvoie une collection d'objets basée sur un critère de recherche.

Les fonctions de requête de magasin de données varient de façon importante. Des magasins de données basés sur de simples fichiers peuvent implémenter des opérations de requête rigides, développées en interne, tandis que des systèmes relationnels fournissent un langage LMD flexible. Les structures de mappages relationnels objet étendent le modèle de requête relationnel pour en faire un modèle centré objet plutôt que centré données. Des mécanismes de passe-système sont également implémentés pour utiliser la flexibilité des requêtes relationnelles et les extensions spécifiques aux fournisseurs (par exemple, des procédures mémorisées).

Notez qu'il existe un conflit potentiel entre les mécanismes de requête basés sur une base de données et le paradigme objet : les mécanismes de requête de base de données sont guidés par des valeurs d'attributs (colonnes) d'une table. Dans les objets correspondants, le principe d'encapsulation nous empêche de voir les valeurs des attributs. Ils sont encapsulés par les opérations de la classe. L'encapsulation simplifie la modification des applications. Grâce à elle, nous pouvons modifier la structure interne d'une classe sans s'occuper des classes dépendantes, tant que les opérations de la classe visibles publiquement ne sont pas modifiées. Un mécanisme de requête basé sur la base de données dépend de la représentation interne d'une classe, brisant effectivement l'encapsulation. Le défi pour la structure consiste à empêcher les requêtes de rendre les applications fragiles face aux modifications.

Transactions Haut de la page

La prise en charge transactionnelle permet au développeur d'applications de définir une unité de travail atomisée. Dans la terminologie de base de données, cela signifie que le système doit pouvoir appliquer un ensemble de modifications sur la base de données ou s'assurer qu'aucune des modifications n'est appliquée. Les opérations au sein d'une transaction s'exécutent toutes avec succès ou la transaction échoue en totalité. Les structures relationnelles objet doivent au minimum fournir une fonction de transaction engagement/annulation de type base de données relationnelle. La conception des structures relationnelles objet dans un environnement multi-utilisateur peut présenter de nombreux défis et un intérêt particulier doit y être apporté.

Outre les fonctions fournies par la structure de persistance, l'application doit comprendre comment traiter les erreurs. Lorsqu'une transaction échoue ou est annulée, le système doit être en mesure de restaurer son état à un état antérieur fiable, généralement grâce en lisant les informations de l'état antérieur dans la base de données. Ainsi, il existe une étroite interaction entre la structure de persistance et la structure de traitement des erreurs.

Simultanéité Haut de la page

Des systèmes orientés objet multi-utilisateurs doivent contrôler les accès simultanés aux objets. Lorsqu'un objet est accédé simultanément par plusieurs utilisateurs, le système doit fournir un mécanisme pour s'assurer que les modifications apportées à l'objet dans le magasin persistant se produisent de manière prévisible et contrôlée. Les structures relationnelles objet peuvent implémenter des contrôles de simultanéité pessimistes et/ou optimistes.

  • Le contrôle de simultanéité pessimiste nécessite que les développeurs d'applications spécifient leurs intentions lorsque l'objet est extrait du magasin de données (par exemple, lecture seule, verrou en écriture, ...). Si des objets sont verrouillés, d'autres utilisateurs peuvent être bloqués lors de l'accès à l'objet et attendre que le verrou soit libéré. La simultanéité pessimiste doit être utilisée et implémentée avec précaution du fait qu'il est possible de créer des situations d'interblocage.
  • Le contrôle de simultanéité optimiste présume qu'il est peu probable que le même objet soit accédé simultanément. Les conflits de simultanéité sont détectés lorsque les modifications sont enregistrées dans la base de données. Généralement, si l'objet a été modifié par un autre utilisateur depuis son extraction, une erreur est renvoyée à l'application, indiquant un incident lors de la modification. Il est de la responsabilité de l'application de détecter et de traiter l'erreur. La structure doit donc mettre en cache les valeurs simultanées des objets et les comparer par rapport à la base de données. La simultanéité optimiste est moins coûteuse s'il y a peu de conflits de simultanéité, mais plus onéreuse si le nombre de conflits est relativement important (du fait du besoin de recommencer le travail si des conflits se produisent).

Toutes les applications faisant usage de données partagées doivent utiliser la même stratégie de simultanéité. Il n'est pas possible de mélanger un contrôle de simultanéité optimiste et pessimiste dans les mêmes données partagées, sinon une altération risque de se produire. Le besoin de stratégie de simultanéité cohérente est mieux géré via une structure de persistance.

Relations Haut de la page

Les objets ont des relations avec d'autres objets. Un objet Commande comporte de nombreux objets de ligne article. Un objet Livre comporte de nombreux objets Chapitre. Un objet Employé appartient exactement à un objet Entreprise. Dans les systèmes relationnels, les relations entre entités sont implémentées à l'aide de références de clé externe/clé primaire. Dans les systèmes orientés objet, les relations sont généralement implémentées de manière explicite via des attributs. Si un objet Commande comporte des lignes articles, l'objet Commande contient un attribut nommé ligneArticle. Cet attribut comporte de nombreux objet Ligne article.

Les aspects relationnels d'une structure relationnelle objet sont interdépendants des services de persistance, de transaction et de requête. Lorsqu'un objet est stocké, extrait, qu'il subit une transaction ou une requête, ses objets associés doivent être pris en considération :

  • Lorsqu'un objet est extrait, ses objets associés doivent-ils être extraits également ? Tout simplement, oui. Mais si les objets associés ne sont pas nécessaire, l'opération est très onéreuse. Une bonne structure permet un mélange de stratégies.
  • Lorsqu'un objet est stocké, ses objets associés doivent-ils être également stockés s'ils ont été modifiés ? Là encore, la réponse dépend du contexte.

Bien que par conception, il soit plus avantageux de prendre en compte des services relationnels objet séparément, leurs implémentations de structure relationnelle objet sont co-dépendantes. Les services doivent être implémentés de façon cohérente non seulement sur les organisations individuelles, mais sur toutes les applications qui partagent les mêmes données. Une structure est le moyen le plus économique pour y parvenir.



RUP (Rational Unified Process)   2003.06.15