URL: https://linuxfr.org/users/montaigne/journaux/cr%C3%A9ation-du-projet-oqltolang Title: Création du projet "OQLToLang" Authors: Ontologia Date: 2007年10月04日T12:41:20+02:00 Tags: Score: 0 La plupart des logiciels (surtout en gestion) nous amènent à manipuler des arborescences de données dans tous les sens. Nous, pauvres programmeurs, devont le faire à la main, avec des boucles. Le comble est qu'il existe des langages très bien conçus pour manipuler des donnés au sein d'arborescences de donnés. OQL en est un exemple. OQL est une extention de SQL pour les SGBDO. On pourrait utiliser d'autres dialectes, l'essentiel étant d'avoir un langage simple et intuitif, OQL me parait un bon candidat. J'ai personnellement beaucoup de facilités avec des langages type SQL, et beaucoup de difficultés avec la manipulation d'arbre de donnés avec des boucles. J'adore jouer avec le premier et déteste me farcir le second exercice. De plus je trouve totalement stupide que l'on continue en 2007 à encore faire à la main quelque chose qui pourrait être automatisé. On nous parlent sans cesse de diminuer les coûts, mais on perd des heures (et beaucoup d'argent) sur des problèmes de ce genre. Cela éviterait de plus de nombreux bugs, qui coutent eux aussi très cher. Microsoft l'a bien compris, en proposant un langage SQL interne dans C# (LINQ) Bref, c'est pour cela que je vous propose le projet "OQLtoLang", dont l'objectif est de générer le code de toute sorte de requête OQL pour différent langage. On pourra ainsi générer du java, Perl, Python, C++, etc... Un système de plugin permettra d'adapter le code de sortie aux spécificités de chaque langage. En effet, selon le genre de chose que l'on code, on a pas obligatoirement un framework genre Hibernate ou autre sous la main. De plus, il est souvent fastidieux de coder un interpréteur dans le langage que l'on utilise et utiliser ce genre de manière "tordu", au yeux de certains chefs de projet pas très ouvert, peu provoquer des problèmes. Un interpréteur, qui plus est, intrinsèquement lent, implique aussi de veiller à ce qu'une couche de la librairie soit disponible, il impose de disposer de réflexivité dans le langage, etc... Le but de ce projet est de générer un code **lisible, compréhensible et reprenable par n'importe qui** et correspondant à la requête. En effet, dans une équipe, le niveau du code doit souvent être nivelé par le bas pour être compréhensible par tout le monde. Une personne extérieur relisant le code doit croire qu'il s'agit d'une bête boucle écrit par un humain. Cela permettra à n'importe qui d'utiliser cet utilitaire avec n'importe quel langage, sans risquer aucun problème vis à vis de son équipe, de son supérieur, etc... Tout en gagnant énormément de temps. J'ai commencé à écrire du code en Ocaml, non pas que c'est le langage que je maîtrise le plus, mais qu'il me parait le plus adapté, avec son type somme, pour le problème. Faire ça sans type somme, ça serait l'horreur. En voici une description didactique. Je défini l'ensemble des type possible. C'est un système criticable parce qu'on pourrait avoir toutes sortes d'objet à récupérer, et du moment que l'on dispose d'une fonction d'égalité par référence et par structure sur 2 objets, cela suffirait amplement. On va faire sans pour le moment. £spaces£ £/spaces£type types_possibles = Entier| Chaine| Date| Tablo_entier | Tablo_ch | Collection | Objet | Chaine_const | Entier_const | Date_const | Tablo_entier_const | Tablo_ch_const;; Il faut ensuite pouvoir définir le chemin d'un objet (par exemple toto[4].proptab.elementAt(5).mumu ...), qui est ni plus ni moins qu'un chemin dans une arborescence £spaces£ £/spaces£type chemin_obj = Feuille of string*types_possibles | Obj_seul of string | Obj of string*chemin_obj | Collect_seul of string|Collect of string* chemin_obj;; On peut d'ors et déjà définir le _select_, liste d'items de l'objets à récupérer : £spaces£ £/spaces£type axiom_select = string*types_possibles;; £spaces£ £/spaces£type select = axiom_select list;; Le from n'est pas compliqué à définir, c'est une liste de différents chemins. £spaces£ £/spaces£type from = chemin_obj list;; La représentation de la clause where est beaucoup plus complexe : Dans une clause _where_, on trouve des comparaison (égalité, différence, supérieur, inférieur), bref des fonction binaire de type E,E -> bool , des tests ensemblistes d'appartenance ou non appartenance. £spaces£ £/spaces£type axiom_where = Comparaison of comp_vars | Ensemblein of ens_in | Ensemblenotin of ens_not_in ;; £spaces£ £/spaces£type where = axiom_where list;; Une comparaison s'effectue entre deux objets. Il faudra ajouter plus tard la possibilité d'y mettre une sous requête à la place. je ne l'ai pas mis pour simplifier. £spaces£ £/spaces£type operat = Egal | Diff | Sup | Sup_egal | Inf | Inf_egal;; £spaces£ £/spaces£type comp_vars = { op : operat ; vc1: chemin_obj; vc2 : chemin_obj};; Les test d'appartenance sont la comparaison entre deux élements : une requête, et un élement. £spaces£ £/spaces£type ens_in = { ve1 : chemin_obj; r : requete};; £spaces£ £/spaces£type ens_not_in = { vf1 : chemin_obj; r : requete};; une requête est donc la synthèse de tout cela : £spaces£ £/spaces£type requete = { sel : select ; from : from ; where : where };; Il nous faut maintenant modéliser le code : type code = Foreach of chemin_obj*code | Test of chemin_obj*chemin_obj*code | Ajout of chemin_obj;; permet de modéliser res : liste d'objet CNN // type donné par select pour chaque Figure.ListeDeCNN £spaces£ £/spaces£i : entier £spaces£ £/spaces£pour chaque Figure.ListeDeCNN[i].Property £spaces£ £/spaces£j : entier £spaces£ £/spaces£si Figure.ListeDeCNN[i].Property[j].NomValeur == "SEE_CNN" alors £spaces£ £/spaces£res.ajoute(Figure.ListeDeCNN[i]) // type de select £spaces£ £/spaces£fin si £spaces£ £/spaces£fin pour fin pour avec £spaces£ £/spaces£Foreach( £spaces£ £/spaces£Obj("Figure",Collect_seul("ListeDeCSN")), £spaces£ £/spaces£Foreach( £spaces£ £/spaces£Obj("Figure",Collect("ListeDeCNN",Obj("Property",Feuille("NomValeur",Chaine_const)))), £spaces£ £/spaces£Test(Collect("ListeDeCNN",Obj("Property",Feuille("NomValeur",Chaine_const))), £spaces£ £/spaces£Feuille("SEE_CNN",Chaine_const), £spaces£ £/spaces£Ajout(Obj("Figure",Collect_seul("ListeDeCNN")))));; Ce code correspond à la requête : £spaces£ £/spaces£select CNN.Object £spaces£ £/spaces£from £spaces£ £/spaces£Figure.ListeDeCNN.Property £spaces£ £/spaces£where £spaces£ £/spaces£Figure.ListeDeCNN.Property.NomValeur = "SEE_CNN" transformé selon la structure de donné en : £spaces£ £/spaces£ let req = { sel = ("CNN.Object",Objet) ; £spaces£ £/spaces£from = [Obj("Figure",Collect("ListeDeCNN",Obj_seul("Property")))]; £spaces£ £/spaces£where = [Comparaison({ £spaces£ £/spaces£op = Egal ; £spaces£ £/spaces£vc1 = Obj("Figure",Collect("ListeDeCNN",Obj("Property",Feuille("NomValeur",Chaine_const)))) ; £spaces£ £/spaces£vc2 =Feuille("SEE_CNN",Chaine_const)})] };; Je ne me suis pas lancé dans le code de la fonction qui va transformer la requête en code, en partie parce que je ne maîtrise pas assez bien ocaml et surtout par manque de temps. je cherche des personnes intéressées par la création de ce projet. Ocaml n'est pas imposé, bien qu'il me semble le plus adapté et le plus clair pour ce genre de chose avec son type somme et son filtrage de type. Si certains sont intéressés, nous pouvons créer un projet sur GNA ou un autre hébergement de ce style. Partant ?

AltStyle によって変換されたページ (->オリジナル) /