{"id":79465,"date":"2020-04-27T07:42:20","date_gmt":"2020-04-27T05:42:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh"},"modified":"2020-04-27T07:42:20","modified_gmt":"2020-04-27T05:42:20","slug":"istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","title":{"rendered":"La v\u00e9rit\u00e9 d'abord, ou pourquoi le syst\u00e8me doit \u00eatre con\u00e7u en fonction de la base de donn\u00e9es","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Salut, Habr !<\/p>\n<p>Nous continuons \u00e0 explorer le sujet <noindex><a rel=\"nofollow\" href=\"https:\/\/www.piter.com\/collection\/all\/product\/sovremennyy-yazyk-java-lyambda-vyrazheniya-potoki-i-funktsionalnoe-programmirovanie\">Java<\/a><\/noindex> et <noindex><a rel=\"nofollow\" href=\"https:\/\/storage.piter.com\/upload\/contents\/978544611587\/978544611587_X.pdf\">Printemps<\/a><\/noindex>, y compris au niveau des bases de donn\u00e9es. Aujourd'hui, nous vous proposons de lire pourquoi, lors de la conception de grandes applications, la structure de la base de donn\u00e9es, et non le code Java, devrait avoir une importance primordiale, comment cela se fait, et quelles sont les exceptions \u00e0 cette r\u00e8gle.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex> <br \/>\nDans cet article quelque peu tardif, j'expliquerai pourquoi je crois que dans presque tous les cas, le mod\u00e8le de donn\u00e9es dans une application doit \u00eatre con\u00e7u \u00ab en fonction de la base de donn\u00e9es \u00bb, et non \u00ab en fonction des capacit\u00e9s de Java \u00bb (ou d'un autre langage client avec lequel vous travaillez). En choisissant la deuxi\u00e8me approche, vous vous engagez sur un long chemin de douleur et de souffrance d\u00e8s que votre projet commence \u00e0 cro\u00eetre.<\/p>\n<p>Cet article est inspir\u00e9 par <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/50706556\/kotlin-with-jooq-and-write-table-models-manually-without-code-generation\">une question<\/a><\/noindex>, pos\u00e9e sur Stack Overflow.<\/p>\n<p>Des discussions int\u00e9ressantes sur reddit dans les sections <noindex><a rel=\"nofollow\" href=\"https:\/\/www.reddit.com\/r\/java\/comments\/8p0uj3\/truth_first_or_why_you_should_mostly_implement\/\">\/r\/java<\/a><\/noindex> et <noindex><a rel=\"nofollow\" href=\"https:\/\/www.reddit.com\/r\/programming\/comments\/8p0qle\/truth_first_or_why_you_should_mostly_implement\/\">\/r\/programming<\/a><\/noindex>.<\/p>\n<h4>G\u00e9n\u00e9ration de code<\/h4>\n<p>\nJe suis tellement surpris qu'il existe une si petite couche d'utilisateurs qui, apr\u00e8s avoir rencontr\u00e9 jOOQ, s'offusquent du fait qu'avec jOOQ, on s'appuie s\u00e9rieusement sur la g\u00e9n\u00e9ration de code. Personne ne vous emp\u00eache d'utiliser jOOQ comme vous le souhaitez et ne vous force \u00e0 utiliser la g\u00e9n\u00e9ration de code. Mais par d\u00e9faut (comme d\u00e9crit dans le manuel), travailler avec jOOQ se d\u00e9roule ainsi : vous partez d'un sch\u00e9ma de base de donn\u00e9es (h\u00e9rit\u00e9), vous effectuez une r\u00e9tro-conception \u00e0 l'aide du g\u00e9n\u00e9rateur de code jOOQ pour obtenir un ensemble de classes repr\u00e9sentant vos tables, puis vous \u00e9crivez des requ\u00eates type-safes \u00e0 ces tables :<\/p>\n<pre><code class=\"java\">\tfor (Record2 record : DSL.using(configuration)\n\/\/   ^^^^^^^^^^^^^^^^^^^^^^^ Informations sur les types d\u00e9duites de \n\/\/   code g\u00e9n\u00e9r\u00e9 auquel se r\u00e9f\u00e8re la condition SELECT ci-dessous\n\n       .select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)\n\/\/           vvvvv ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ noms g\u00e9n\u00e9r\u00e9s\n       .from(ACTOR)\n       .orderBy(1, 2)) {\n    \/\/ ...\n}<\/code><\/pre>\n<p>\nLe code est g\u00e9n\u00e9r\u00e9 soit manuellement en dehors de la construction, soit manuellement \u00e0 chaque construction. Par exemple, une telle r\u00e9g\u00e9n\u00e9ration peut se produire juste apr\u00e8s <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2014\/06\/25\/flyway-and-jooq-for-unbeatable-sql-development-productivity\/\">la migration de la base de donn\u00e9es Flyway, qui peut \u00e9galement \u00eatre effectu\u00e9e manuellement ou automatiquement<\/a><\/noindex>.<\/p>\n<h4>G\u00e9n\u00e9ration de code source<\/h4>\n<p>\nAvec ces approches de g\u00e9n\u00e9ration de code - manuelles et automatiques - sont associ\u00e9es diff\u00e9rentes philosophies, avantages et inconv\u00e9nients, que je ne vais pas d\u00e9tailler dans cet article. Mais, en g\u00e9n\u00e9ral, toute l'essence du code g\u00e9n\u00e9r\u00e9 r\u00e9side dans le fait qu'il permet de reproduire en Java cette \"v\u00e9rit\u00e9\" que nous consid\u00e9rons comme acquise, soit dans le cadre de notre syst\u00e8me, soit en dehors de celui-ci. D'une certaine mani\u00e8re, c'est ce que font les compilateurs, g\u00e9n\u00e9rant du bytecode, du code machine ou tout autre type de code \u00e0 partir des sources - nous obtenons une repr\u00e9sentation de notre \"v\u00e9rit\u00e9\" dans un autre langage, ind\u00e9pendamment des raisons sp\u00e9cifiques. <\/p>\n<p>Il existe de nombreux g\u00e9n\u00e9rateurs de code. Par exemple, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/tools\/unix\/xjc.html\">XJC peut g\u00e9n\u00e9rer du code Java \u00e0 partir de fichiers XSD ou WSDL.<\/a><\/noindex>Le principe est toujours le m\u00eame :<\/p>\n<ul>\n<li>Il existe une certaine v\u00e9rit\u00e9 (interne ou externe) - par exemple, une sp\u00e9cification, un mod\u00e8le de donn\u00e9es, etc.<\/li>\n<li>Nous avons besoin d'une repr\u00e9sentation locale de cette v\u00e9rit\u00e9 dans notre langage de programmation.<\/li>\n<\/ul>\n<p>\nIl est presque toujours judicieux de g\u00e9n\u00e9rer une telle repr\u00e9sentation - pour \u00e9viter la redondance.<\/p>\n<h4>Providers de types et traitement des annotations<\/h4>\n<p>\n\u00c0 noter : une autre approche, plus moderne et sp\u00e9cifique, de g\u00e9n\u00e9ration de code pour jOOQ implique l'utilisation de providers de types, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/fsharp\/tutorials\/type-providers\/\">tels qu'ils sont r\u00e9alis\u00e9s en F#.<\/a><\/noindex>Dans ce cas, le code est g\u00e9n\u00e9r\u00e9 par le compilateur, pr\u00e9cis\u00e9ment au stade de la compilation. Sous forme de sources, ce code n'existe fondamentalement pas. En Java, il existe des outils similaires, bien que moins \u00e9l\u00e9gants - ce sont les processeurs d'annotations, par exemple, <noindex><a rel=\"nofollow\" href=\"https:\/\/projectlombok.org\">Lombok.<\/a><\/noindex>.<\/p>\n<p>Dans un certain sens, les m\u00eames choses se produisent ici que dans le premier cas, \u00e0 l'exception de :<\/p>\n<ul>\n<li>Vous ne voyez pas le code g\u00e9n\u00e9r\u00e9 (peut-\u00eatre que cette situation ne semble pas si repoussante \u00e0 quelqu'un ?)<\/li>\n<li>Vous devez garantir que les types peuvent \u00eatre fournis, c'est-\u00e0-dire que la \"v\u00e9rit\u00e9\" doit toujours \u00eatre accessible. Cela est facile dans le cas de Lombok, qui annotent la \"v\u00e9rit\u00e9\". Cela devient un peu plus compliqu\u00e9 avec des mod\u00e8les de bases de donn\u00e9es, dont le fonctionnement d\u00e9pend d'une connexion active constamment disponible.<\/li>\n<\/ul>\n<p><\/p>\n<h4>Quel est le probl\u00e8me avec la g\u00e9n\u00e9ration de code ?<\/h4>\n<p>\nEn plus de la question d\u00e9licate de savoir comment il est pr\u00e9f\u00e9rable de lancer la g\u00e9n\u00e9ration de code \u2013 manuellement ou automatiquement, il convient \u00e9galement de mentionner qu'il y a des personnes qui pensent que la g\u00e9n\u00e9ration de code n'est tout simplement pas n\u00e9cessaire. Le raisonnement derri\u00e8re ce point de vue, que j'ai rencontr\u00e9 le plus souvent, est que cela rend difficile la configuration du pipeline de construction. Oui, c'est effectivement compliqu\u00e9. Cela entra\u00eene des co\u00fbts d'infrastructure suppl\u00e9mentaires. Si vous d\u00e9butez avec un produit particulier (qu'il s'agisse de jOOQ, JAXB, Hibernate, etc.), le temps consacr\u00e9 \u00e0 la configuration de l'environnement de travail est du temps que vous pr\u00e9f\u00e9reriez passer \u00e0 \u00e9tudier l'API elle-m\u00eame afin d'en tirer de la valeur par la suite.<\/p>\n<p>Si les co\u00fbts li\u00e9s \u00e0 la compr\u00e9hension du fonctionnement du g\u00e9n\u00e9rateur sont trop \u00e9lev\u00e9s, alors effectivement, cela signifie que l'API n'a pas suffisamment travaill\u00e9 sur l'ergonomie du g\u00e9n\u00e9rateur de code (et il s'av\u00e8re par la suite que la personnalisation utilisateur y est \u00e9galement complexe). La facilit\u00e9 d'utilisation doit \u00eatre la priorit\u00e9 absolue pour toute API de ce type. Mais c'est juste un argument contre la g\u00e9n\u00e9ration de code. Par ailleurs, il est totalement possible d'\u00e9crire manuellement la repr\u00e9sentation locale de la v\u00e9rit\u00e9 interne ou externe.<\/p>\n<p>Beaucoup diront qu'ils n'ont pas le temps de s'occuper de tout cela. Ils ont des d\u00e9lais serr\u00e9s pour leur Super Produit. On s'occupera des pipelines de construction plus tard, il y aura le temps. Je leur r\u00e9ponds :<\/p>\n<p><img decoding=\"async\" alt=\"La v\u00e9rit\u00e9 d&#039;abord, ou pourquoi le syst\u00e8me doit \u00eatre con\u00e7u en fonction de la base de donn\u00e9es\" src=\"\/wp-content\/uploads\/2020\/04\/cd9aca1e0365fa5af28cfc72c201cb8c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/www.flickr.com\/photos\/toddle_email_newsletters\/15596940251\/in\/photostream\/\">Original<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"http:\/\/audiencestack.com\/static\/blog.html\">Alan O'Rourke, Audience Stack<\/a><\/noindex> <\/p>\n<p><b>Mais avec Hibernate \/ JPA, il est si facile d'\u00e9crire du code \u00ab sous Java \u00bb. <\/b><\/p>\n<p>Effectivement. Pour Hibernate et ses utilisateurs, c'est \u00e0 la fois une b\u00e9n\u00e9diction et une mal\u00e9diction. Avec Hibernate, on peut simplement \u00e9crire quelques entit\u00e9s comme ceci :<\/p>\n<pre><code class=\"java\">\t@Entity\nclass Book {\n  @Id\n  int id;\n  String title;\n}<\/code><\/pre>\n<p>\nEt presque tout est pr\u00eat. Maintenant, la t\u00e2che d'Hibernate est de g\u00e9n\u00e9rer les d\u00e9tails complexes de la mani\u00e8re dont cette entit\u00e9 sera d\u00e9finie dans le DDL de votre dialecte SQL :<\/p>\n<pre><code class=\"sql\">\tCREATE TABLE book (\n  id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,\n  title VARCHAR(50),\n\n  CONSTRAINT pk_book PRIMARY KEY (id)\n);\n\nCREATE INDEX i_book_title ON book (title);<\/code><\/pre>\n<p>\n\u2026 et nous commen\u00e7ons \u00e0 faire fonctionner l'application. C'est vraiment une fonctionnalit\u00e9 incroyable pour commencer rapidement \u00e0 travailler et \u00e0 essayer diff\u00e9rentes choses.<\/p>\n<p>Cependant, permettez-moi. J'ai exag\u00e9r\u00e9.<\/p>\n<ul>\n<li>Est-ce qu'Hibernate appliquera vraiment la d\u00e9finition de cette cl\u00e9 primaire nomm\u00e9e ?<\/li>\n<li>Est-ce qu'Hibernate va cr\u00e9er un index dans TITLE ? \u2013 je sais pertinemment qu'il nous sera n\u00e9cessaire. <\/li>\n<li>Est-ce qu'Hibernate fera vraiment de cette cl\u00e9 une cl\u00e9 identifiant dans la sp\u00e9cification d'identit\u00e9 ?<\/li>\n<\/ul>\n<p>\nProbablement pas. Si vous d\u00e9veloppez votre projet \u00e0 partir de z\u00e9ro, il est toujours pratique de simplement abandonner l'ancienne base de donn\u00e9es et de g\u00e9n\u00e9rer une nouvelle d\u00e8s que vous ajoutez les annotations n\u00e9cessaires. Ainsi, l'entit\u00e9 Book finira par avoir la forme suivante : <\/p>\n<pre><code class=\"java\">\t@Entity\n@Table(name = \"book\", indexes = {\n  @Index(name = \"i_book_title\", columnList = \"title\")\n})\nclass Book {\n  @Id\n  @GeneratedValue(strategy = IDENTITY)\n  int id;\n  String title;\n}\n<\/code><\/pre>\n<p>\nG\u00e9nial. G\u00e9n\u00e9rer \u00e0 nouveau. Encore une fois, dans ce cas, cela sera tr\u00e8s facile au d\u00e9part.<\/p>\n<h4>Mais par la suite, cela aura un co\u00fbt.<\/h4>\n<p>\nT\u00f4t ou tard, il faudra passer en production. C'est \u00e0 ce moment-l\u00e0 que ce mod\u00e8le cessera de fonctionner. Parce que : <\/p>\n<p>En production, vous ne pourrez plus abandonner l'ancienne base de donn\u00e9es et tout recommencer \u00e0 z\u00e9ro si n\u00e9cessaire. Votre base de donn\u00e9es sera consid\u00e9r\u00e9e comme h\u00e9rit\u00e9e.<\/p>\n<p>\u00c0 partir de maintenant et pour toujours, vous devrez \u00e9crire <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2014\/06\/25\/flyway-and-jooq-for-unbeatable-sql-development-productivity\/\">des scripts de migration DDL, par exemple, en utilisant Flyway.<\/a><\/noindex>. Que se passera-t-il alors avec vos entit\u00e9s ? Vous pourrez soit les adapter manuellement (et ainsi doubler votre volume de travail), soit demander \u00e0 Hibernate de les g\u00e9n\u00e9rer \u00e0 nouveau pour vous (quelles sont les chances que ce soit conforme \u00e0 vos attentes ?). Dans tous les cas, vous perdez.<\/p>\n<p>Ainsi, d\u00e8s que vous serez en production, vous aurez besoin de patches \u00e0 chaud. Et il faut d\u00e9ployer ceux-ci en production tr\u00e8s rapidement. \u00c9tant donn\u00e9 que vous ne vous \u00eates pas pr\u00e9par\u00e9 et n'avez pas organis\u00e9 un flux de migration fluide pour la production, vous appliquerez tous des patchs qui ne seront pas bien faits. Ensuite, vous n'aurez pas le temps de tout faire correctement. Et vous bl\u00e2merez Hibernate, parce que quelqu'un d'autre est toujours responsable, sauf vous\u2026<\/p>\n<p>Au lieu de cela, tout aurait pu \u00eatre fait compl\u00e8tement diff\u00e9remment d\u00e8s le d\u00e9but. Par exemple, mettre des roues rondes sur le v\u00e9lo.<\/p>\n<h4>D'abord la base de donn\u00e9es.<\/h4>\n<p>\nLa v\u00e9ritable \"v\u00e9rit\u00e9\" dans le sch\u00e9ma de votre base de donn\u00e9es et la \"souverainet\u00e9\" sur celui-ci se trouvent dans la base de donn\u00e9es elle-m\u00eame. Le sch\u00e9ma n'est d\u00e9fini que dans la base de donn\u00e9es elle-m\u00eame et nulle part ailleurs, et chaque client a une copie de ce sch\u00e9ma, il est donc tout \u00e0 fait logique d'imposer le respect du sch\u00e9ma et de son int\u00e9grit\u00e9, en le faisant directement dans la base de donn\u00e9es - l\u00e0 o\u00f9 les informations sont stock\u00e9es. <br \/>\nC'est une vieille sagesse m\u00eame us\u00e9e. Les cl\u00e9s primaires et uniques - c'est bien. Les cl\u00e9s \u00e9trang\u00e8res - c'est bien. La v\u00e9rification des contraintes - c'est bien. <noindex><a rel=\"nofollow\" href=\"https:\/\/community.oracle.com\/ideas\/13028\">Assertions<\/a><\/noindex> \u2013 c'est bien. <\/p>\n<p>Cependant, ce n'est pas tout. Par exemple, en utilisant Oracle, vous voudrez probablement sp\u00e9cifier :<\/p>\n<ul>\n<li>Dans quel espace de table se trouve votre table <\/li>\n<li>Quelle est sa valeur PCTFREE <\/li>\n<li>Quelle est la taille du cache dans votre s\u00e9quence (derri\u00e8re l'identifiant)<\/li>\n<\/ul>\n<p>\nIl se peut que tout cela ne soit pas important dans les petites syst\u00e8mes, mais il n'est pas n\u00e9cessaire d'attendre de passer au domaine du \u00ab big data \u00bb \u2014 il est possible de commencer \u00e0 tirer parti des optimisations de stockage des donn\u00e9es fournies par le fournisseur beaucoup plus t\u00f4t, comme celles mentionn\u00e9es ci-dessus. Aucune des ORM que j'ai pu voir (y compris jOOQ) ne donne acc\u00e8s \u00e0 l'ensemble des options DDL que vous souhaiterez peut-\u00eatre utiliser dans votre base de donn\u00e9es. Les ORM offrent des outils qui aident \u00e0 r\u00e9diger du DDL.<\/p>\n<p>Mais au final, un sch\u00e9ma bien con\u00e7u est \u00e9crit manuellement en DDL. Tout DDL g\u00e9n\u00e9r\u00e9 n'est qu'une approximation de celui-ci.<\/p>\n<h4>Qu'en est-il du mod\u00e8le client ?<\/h4>\n<p>\nComme mentionn\u00e9 pr\u00e9c\u00e9demment, du c\u00f4t\u00e9 client, vous aurez besoin d'une copie du sch\u00e9ma de votre base de donn\u00e9es, une vue client. Il est superflu de mentionner que cette vue client doit \u00eatre synchronis\u00e9e avec le mod\u00e8le r\u00e9el. Comment y parvenir au mieux ? Avec un g\u00e9n\u00e9rateur de code.<\/p>\n<p>Toutes les bases de donn\u00e9es fournissent leurs m\u00e9tadonn\u00e9es via SQL. Voici comment obtenir toutes les tables de votre base de donn\u00e9es sur diff\u00e9rents dialectes SQL :<\/p>\n<pre><code class=\"sql\">\t-- H2, HSQLDB, MySQL, PostgreSQL, SQL Server\nSELECT table_schema, table_name\nFROM information_schema.tables\n\n-- DB2\nSELECT tabschema, tabname\nFROM syscat.tables\n\n-- Oracle\nSELECT owner, table_name\nFROM all_tables\n\n-- SQLite\nSELECT name\nFROM sqlite_master\n\n-- Teradata\nSELECT databasename, tablename\nFROM dbc.tables\n<\/code><\/pre>\n<p>\nCes requ\u00eates (ou similaires, selon qu'il faille aussi consid\u00e9rer les vues, les vues mat\u00e9rialis\u00e9es, ou les fonctions \u00e0 valeur tabulaire) sont \u00e9galement ex\u00e9cut\u00e9es via l'appel <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/sql\/DatabaseMetaData.html#getTables(java.lang.String,java.lang.String,java.lang.String,java.lang.String%5B%5D)\"><code>DatabaseMetaData.getTables()<\/code><\/a><\/noindex> de JDBC, ou via le module m\u00e9ta jOOQ.<\/p>\n<p>\u00c0 partir des r\u00e9sultats de telles requ\u00eates, il est relativement facile de g\u00e9n\u00e9rer n'importe quelle vue client du mod\u00e8le de votre base de donn\u00e9es, peu importe la technologie que vous utilisez c\u00f4t\u00e9 client.<\/p>\n<ul>\n<li>Si vous utilisez JDBC ou Spring, vous pouvez cr\u00e9er un ensemble de constantes de cha\u00eene <\/li>\n<li>Si vous utilisez JPA, vous pouvez g\u00e9n\u00e9rer vous-m\u00eame les entit\u00e9s <\/li>\n<li>Si vous utilisez jOOQ, vous pouvez g\u00e9n\u00e9rer la m\u00e9ta-mod\u00e8le de jOOQ<\/li>\n<\/ul>\n<p>\nSelon le volume de fonctionnalit\u00e9s propos\u00e9 par votre API client (par exemple, jOOQ ou JPA), le m\u00e9ta-mod\u00e8le g\u00e9n\u00e9r\u00e9 peut \u00eatre v\u00e9ritablement riche et complet. Prenons, par exemple, la possibilit\u00e9 de jointures implicites, <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2018\/02\/20\/type-safe-implicit-join-through-path-navigation-in-jooq-3-11\/\">introduite dans jOOQ 3.11<\/a><\/noindex>, qui repose sur les m\u00e9tadonn\u00e9es g\u00e9n\u00e9r\u00e9es concernant les relations de cl\u00e9s \u00e9trang\u00e8res entre vos tables.<\/p>\n<p>D\u00e9sormais, toute augmentation de la base de donn\u00e9es entra\u00eenera automatiquement la mise \u00e0 jour du code client. Imaginez par exemple :<\/p>\n<pre><code class=\"sql\">ALTER TABLE book RENAME COLUMN title TO book_title;<\/code><\/pre>\n<p>\nVoudriez-vous vraiment faire ce travail deux fois ? Absolument pas. Il suffit de fixer le DDL, de le faire passer par votre pipeline de construction et d'obtenir l'entit\u00e9 mise \u00e0 jour :<\/p>\n<pre><code class=\"java\">@Entity\n@Table(name = \"book\", indexes = {\n \n  \/\/ Avez-vous d\u00e9j\u00e0 pens\u00e9 \u00e0 cela ?\n  @Index(name = \"i_book_title\", columnList = \"book_title\")\n})\nclass Book {\n  @Id\n  @GeneratedValue(strategy = IDENTITY)\n  int id;\n \n  @Column(\"book_title\")\n  String bookTitle;\n}<\/code><\/pre>\n<p>\nOu bien la classe jOOQ mise \u00e0 jour. La plupart des modifications DDL se refl\u00e8tent \u00e9galement sur la s\u00e9mantique et pas seulement sur la syntaxe. Il est donc pratique de consulter le code compil\u00e9 pour voir quel code sera (ou pourrait \u00eatre) impact\u00e9 par l'augmentation de votre base de donn\u00e9es.<\/p>\n<h4>La seule v\u00e9rit\u00e9<\/h4>\n<p>\nQu'importe la technologie que vous utilisez, il existe toujours un mod\u00e8le qui constitue la seule source de v\u00e9rit\u00e9 pour un certain sous-syst\u00e8me \u2013 ou, au minimum, nous devons viser cela et \u00e9viter cette confusion d'entreprise o\u00f9 \"la v\u00e9rit\u00e9\" est \u00e0 la fois partout et nulle part. Tout pourrait \u00eatre beaucoup plus simple. Si vous ne faites qu'\u00e9changer des fichiers XML avec un autre syst\u00e8me, utilisez simplement des XSD. Regardez le m\u00e9ta-mod\u00e8le INFORMATION_SCHEMA de jOOQ en forme XML :<br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/www.jooq.org\/xsd\/jooq-meta-3.10.0.xsd\">https:\/\/www.jooq.org\/xsd\/jooq-meta-3.10.0.xsd<\/a><\/noindex><\/p>\n<ul>\n<li>L'XSD est bien comprise<\/li>\n<li>L'XSD marque tr\u00e8s bien le contenu XML et permet de valider dans tous les langages clients <\/li>\n<li>L'XSD est bien versionn\u00e9e et poss\u00e8de une r\u00e9trocompatibilit\u00e9 avanc\u00e9e <\/li>\n<li>L'XSD peut \u00eatre transform\u00e9e en code Java \u00e0 l'aide de XJC<\/li>\n<\/ul>\n<p>\nLe dernier point est important. Lors de la communication avec un syst\u00e8me externe \u00e0 l'aide de messages XML, nous voulons \u00eatre s\u00fbrs de la validit\u00e9 de nos messages. Cela peut \u00eatre facilement r\u00e9alis\u00e9 gr\u00e2ce \u00e0 JAXB, XJC et XSD. Ce serait compl\u00e8tement insens\u00e9 de penser qu'avec une approche de conception \u00ab Java d'abord \u00bb, o\u00f9 nous faisons nos messages sous forme d'objets Java, nous pourrions les mapper de mani\u00e8re claire sur XML et les envoyer pour consommation dans un autre syst\u00e8me. XML g\u00e9n\u00e9r\u00e9 de cette mani\u00e8re serait de tr\u00e8s mauvaise qualit\u00e9, non document\u00e9, et difficile \u00e0 faire \u00e9voluer. Si un accord sur le niveau de service (SLA) existait pour cette interface, nous l'aurions imm\u00e9diatement compromis.<\/p>\n<p>Honn\u00eatement, c'est exactement ce qui se passe constamment avec les API au format JSON, mais c'est une autre histoire, la prochaine fois je me f\u00e2cherai\u2026 <\/p>\n<h4>Bases de donn\u00e9es : c'est la m\u00eame chose<\/h4>\n<p>\nEn travaillant avec des bases de donn\u00e9es, vous comprenez qu'elles sont toutes fondamentalement similaires. Une base poss\u00e8de ses donn\u00e9es et doit g\u00e9rer le sch\u00e9ma. Toute modification apport\u00e9e au sch\u00e9ma doit \u00eatre mise en \u0153uvre directement sur le DDL, afin de mettre \u00e0 jour la source unique de v\u00e9rit\u00e9.<\/p>\n<p>Lorsque la mise \u00e0 jour de la source a eu lieu, tous les clients doivent \u00e9galement mettre \u00e0 jour leurs copies du mod\u00e8le. Certains clients peuvent \u00eatre \u00e9crits en Java en utilisant jOOQ et Hibernate ou JDBC (ou tous en m\u00eame temps). D'autres clients peuvent \u00eatre \u00e9crits en Perl (je leur souhaite bonne chance), et d'autres encore en C#. Peu importe. Le mod\u00e8le principal se trouve dans la base de donn\u00e9es. Les mod\u00e8les g\u00e9n\u00e9r\u00e9s \u00e0 l'aide de l'ORM sont g\u00e9n\u00e9ralement de mauvaise qualit\u00e9, mal document\u00e9s, et difficiles \u00e0 faire \u00e9voluer.<\/p>\n<p>Alors ne faites pas d'erreurs. Ne faites pas d'erreurs d\u00e8s le d\u00e9part. Travaillez en vous basant sur la base de donn\u00e9es. Construisez un pipeline de d\u00e9ploiement qui peut \u00eatre automatis\u00e9. Incluez des g\u00e9n\u00e9rateurs de code pour faciliter la copie de votre mod\u00e8le de base de donn\u00e9es et le d\u00e9ploiement sur les clients. Et arr\u00eatez de vous soucier des g\u00e9n\u00e9rateurs de code. Ils sont bons. Avec eux, vous serez plus productif. Il suffit de consacrer un peu de temps au d\u00e9but pour les configurer \u2013 et par la suite, vous b\u00e9n\u00e9ficierez de plusieurs ann\u00e9es d\u2019augmentation de productivit\u00e9, qui formeront l\u2019histoire de votre projet.<\/p>\n<p>Ne me remerciez pas encore, plus tard.<\/p>\n<h4>Explication<\/h4>\n<p>\nPour plus de clart\u00e9 : Cet article ne pr\u00e9conise en aucun cas que l'ensemble du syst\u00e8me (c'est-\u00e0-dire le domaine, la logique m\u00e9tier, etc.) doit \u00eatre adapt\u00e9 au mod\u00e8le de votre base de donn\u00e9es. Dans cet article, je mentionne que le code client interagissant avec la base de donn\u00e9es doit fonctionner en se basant sur le mod\u00e8le de donn\u00e9es, de sorte que lui-m\u00eame ne reproduise pas le mod\u00e8le de base de donn\u00e9es au statut de \u00ab premier classe \u00bb. Cette logique est g\u00e9n\u00e9ralement situ\u00e9e au niveau d'acc\u00e8s aux donn\u00e9es de votre client.<\/p>\n<p>Dans les architectures \u00e0 deux niveaux, qui existent encore par endroits, ce type de mod\u00e8le syst\u00e8me peut \u00eatre le seul possible. Cependant, dans la plupart des syst\u00e8mes, le niveau d'acc\u00e8s aux donn\u00e9es me semble \u00eatre une \u00ab sous-syst\u00e8me \u00bb, encapsulant le mod\u00e8le de la base de donn\u00e9es.<\/p>\n<h4>Exceptions<\/h4>\n<p>\nIl existe des exceptions \u00e0 toute r\u00e8gle, et j'ai d\u00e9j\u00e0 mentionn\u00e9 que l'approche de priorit\u00e9 de la base de donn\u00e9es et de g\u00e9n\u00e9ration de code source peut parfois \u00eatre inappropri\u00e9e. Voici quelques-unes de ces exceptions (d'autres peuvent \u00e9ventuellement exister) :<\/p>\n<ul>\n<li>Lorsque le sch\u00e9ma est inconnu et doit \u00eatre ouvert. Par exemple, vous \u00eates un fournisseur d'outils qui aide les utilisateurs \u00e0 naviguer dans n'importe quel sch\u00e9ma. Ouf. Ici, il n'y a pas de g\u00e9n\u00e9ration de code. Mais, tout de m\u00eame - la base de donn\u00e9es avant tout.<\/li>\n<li>Lorsque le sch\u00e9ma doit \u00eatre g\u00e9n\u00e9r\u00e9 \u00e0 la vol\u00e9e pour r\u00e9soudre un certain probl\u00e8me. Cet exemple semble \u00eatre une version l\u00e9g\u00e8rement enjou\u00e9e du pattern <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">entity attribute value<\/a><\/noindex>, c'est-\u00e0-dire que vous n'avez vraiment pas de sch\u00e9ma clairement d\u00e9fini. Dans ce cas, il est souvent m\u00eame impossible d'\u00eatre certain qu'un SGBD vous conviendra.<\/li>\n<\/ul>\n<p>\nLes exceptions sont par nature exceptionnelles. Dans la plupart des cas li\u00e9s \u00e0 l'utilisation d'un SGBD, le sch\u00e9ma est connu \u00e0 l'avance, il est \u00e0 l'int\u00e9rieur du SGBD et constitue la seule source de \u00ab v\u00e9rit\u00e9 \u00bb, et tous les clients doivent avoir des copies d\u00e9riv\u00e9es de celui-ci. Id\u00e9alement, un g\u00e9n\u00e9rateur de code devrait \u00eatre impliqu\u00e9.<br \/>\n<br \/>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/piter\/blog\/498816\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443 Java \u0438 Spring, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435, \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043f\u043e\u0447\u0435\u043c\u0443 \u043f\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u043d\u0435 \u043a\u043e\u0434 Java, \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f, \u0438 \u043a\u0430\u043a\u0438\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430. \u0412 \u044d\u0442\u043e\u0439 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u043e\u0437\u0434\u0430\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043e\u0431\u044a\u044f\u0441\u043d\u044e, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":79466,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-79465","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0418\u0441\u0442\u0438\u043d\u0430 \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u0438\u043b\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-04-27T05:42:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-04-27T05:42:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47La v\u00e9rit\u00e9 avant tout, ou pourquoi il faut concevoir le syst\u00e8me en fonction de la structure de la base de donn\u00e9es | ProHoster","description":"Bonjour, Habr ! Nous continuons \u00e0 explorer le sujet","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0418\u0441\u0442\u0438\u043d\u0430 \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u0438\u043b\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-04-27T05:42:20+00:00","article:modified_time":"2020-04-27T05:42:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"79465","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:37:24","updated":"2022-09-29 16:13:15","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/79465","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=79465"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/79465\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/79466"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=79465"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=79465"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=79465"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}