Verità l-ewwel, jew għaliex sistema jeħtieġ li tkun iddisinjata bbażata fuq id-disinn tad-database

Ħej Habr!

Inkomplu nirriċerkaw is-suġġett Java и rebbiegħa, inkluż fil-livell tad-database. Illum nistednuk taqra dwar għaliex, meta tfassal applikazzjonijiet kbar, hija l-istruttura tad-database, u mhux il-kodiċi Java, li għandha tkun ta 'importanza deċiżiva, kif dan isir, u x'eċċezzjonijiet hemm għal din ir-regola.

F'dan l-artikolu pjuttost tard, ser nispjega għaliex nemmen li fi kważi l-każijiet kollha, il-mudell tad-dejta f'applikazzjoni għandu jkun iddisinjat "minn id-database" aktar milli "mill-kapaċitajiet ta' Java" (jew kwalunkwe lingwa tal-klijent li tkun int taħdem ma'). Billi tieħu t-tieni approċċ, tkun qed tħejji lilek innifsek għal triq twila ta 'uġigħ u tbatija ladarba l-proġett tiegħek jibda jikber.

L-artiklu nkiteb ibbażat fuq mistoqsija waħda, mogħtija fuq Stack Overflow.

Diskussjonijiet interessanti fuq reddit f'sezzjonijiet /r/java и /r/programmazzjoni.

Ġenerazzjoni tal-kodiċi

Kemm kont sorpriż li hemm segment daqshekk żgħir ta 'utenti li, wara li jkunu saru midħla ta' jOOQ, huma rrabjati bil-fatt li jOOQ jiddependi serjament fuq il-ġenerazzjoni tal-kodiċi tas-sors biex jopera. Ħadd mhu qed iwaqqafk milli tuża jOOQ kif jidhirlek, jew iġġiegħlek tuża l-ġenerazzjoni tal-kodiċi. Iżda l-mod awtomatiku (kif deskritt fil-manwal) ta' kif taħdem ma' jOOQ huwa li tibda bi skema ta' database (legata), tagħmel inġinerija inversa billi tuża l-ġeneratur tal-kodiċi jOOQ biex b'hekk tikseb sett ta' klassijiet li jirrappreżentaw it-tabelli tiegħek, u mbagħad tikteb it-tip. -mistoqsijiet sikuri għal dawn it-tabelli:

	for (Record2<String, String> record : DSL.using(configuration)
//   ^^^^^^^^^^^^^^^^^^^^^^^ Информация о типах выведена на 
//   основании сгенерированного кода, на который ссылается приведенное
// ниже условие SELECT 
 
       .select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
//           vvvvv ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ сгенерированные имена
       .from(ACTOR)
       .orderBy(1, 2)) {
    // ...
}

Il-kodiċi huwa ġġenerat jew manwalment barra mill-assemblaġġ, jew manwalment f'kull assemblaġġ. Per eżempju, tali riġenerazzjoni tista 'ssegwi immedjatament wara Migrazzjoni tad-database tal-Flyway, li tista' ssir ukoll manwalment jew awtomatikament.

Ġenerazzjoni tal-kodiċi tas-sors

Hemm diversi filosofiji, vantaġġi u żvantaġġi assoċjati ma 'dawn l-approċċi għall-ġenerazzjoni tal-kodiċi - manwali u awtomatika - li mhux se niddiskuti fid-dettall f'dan l-artikolu. Iżda, b'mod ġenerali, il-punt kollu tal-kodiċi ġġenerat huwa li jippermettilna nirriproduċu f'Java dik il-"verità" li nieħdu bħala mogħtija, jew fis-sistema tagħna jew barra minnha. F'ċertu sens, dan huwa dak li jagħmlu l-kompilaturi meta jiġġeneraw bytecode, kodiċi tal-magni, jew xi forma oħra ta 'kodiċi sors - aħna nġibu rappreżentazzjoni tal-"verità" tagħna f'lingwa oħra, irrispettivament mir-raġunijiet speċifiċi.

Hemm ħafna ġeneraturi ta 'kodiċi bħal dawn. Pereżempju, XJC jista 'jiġġenera kodiċi Java ibbażat fuq fajls XSD jew WSDL. Il-prinċipju huwa dejjem l-istess:

  • Hemm xi verità (interna jew esterna) - pereżempju, speċifikazzjoni, mudell tad-dejta, eċċ.
  • Għandna bżonn rappreżentazzjoni lokali ta 'din il-verità fil-lingwa ta' programmar tagħna.

Barra minn hekk, huwa kważi dejjem rakkomandabbli li tiġi ġġenerata tali rappreżentazzjoni sabiex tiġi evitata s-sensja.

Fornituri tat-Tip u Ipproċessar ta' Annotazzjonijiet

Nota: approċċ ieħor, aktar modern u speċifiku għall-ġenerazzjoni tal-kodiċi għal jOOQ qed juża fornituri tat-tip, peress li huma implimentati f'F#. F'dan il-każ, il-kodiċi huwa ġġenerat mill-kompilatur, fil-fatt fl-istadju tal-kumpilazzjoni. Fil-prinċipju, tali kodiċi ma jeżistix fil-forma tas-sors. Java għandu għodda simili, għalkemm mhux daqshekk eleganti - proċessuri ta' annotazzjoni, pereżempju, Lombok.

F'ċertu sens, l-istess affarijiet jiġri hawn bħal fl-ewwel każ, bl-eċċezzjoni ta ':

  • Ma tarax il-kodiċi ġġenerat (forsi din is-sitwazzjoni tidher inqas repulsiva għal xi ħadd?)
  • Trid tiżgura li t-tipi jistgħu jiġu pprovduti, jiġifieri, "veru" għandu dejjem ikun disponibbli. Dan huwa faċli fil-każ ta 'Lombok, li jannota "verità". Huwa ftit aktar ikkumplikat b'mudelli ta 'database li jiddependu fuq konnessjoni diretta kontinwament disponibbli.

X'inhi l-problema bil-ġenerazzjoni tal-kodiċi?

Minbarra l-mistoqsija delikata dwar kif l-aħjar titmexxa l-ġenerazzjoni tal-kodiċi - manwalment jew awtomatikament, irridu nsemmu wkoll li hemm nies li jemmnu li l-ġenerazzjoni tal-kodiċi mhi meħtieġa xejn. Il-ġustifikazzjoni għal din il-perspettiva, li ltqajt magħha l-aktar spiss, hija li mbagħad huwa diffiċli li titwaqqaf pipeline tal-bini. Iva, huwa verament diffiċli. Jqumu spejjeż addizzjonali tal-infrastruttura. Jekk għadek qed tibda b'prodott partikolari (kemm jekk hu jOOQ, jew JAXB, jew Hibernate, eċċ.), it-twaqqif ta' ambjent ta' produzzjoni jieħu ż-żmien li tippreferi tqatta' titgħallem l-API innifsu sabiex tkun tista' tiġbed il-valur minnu. .

Jekk l-ispejjeż assoċjati mal-fehim tal-istruttura tal-ġeneratur huma għoljin wisq, allura, tabilħaqq, l-API għamlet xogħol fqir fuq l-użabilità tal-ġeneratur tal-kodiċi (u aktar tard jirriżulta li l-personalizzazzjoni tal-utent fiha hija wkoll diffiċli). L-użabilità għandha tkun l-ogħla prijorità għal kwalunkwe API bħal din. Iżda dan huwa biss argument wieħed kontra l-ġenerazzjoni tal-kodiċi. Inkella, huwa assolutament kompletament manwali li tikteb rappreżentazzjoni lokali tal-verità interna jew esterna.

Ħafna jgħidu li m'għandhomx ħin jagħmlu dan kollu. Qegħdin jispiċċaw l-iskadenzi għas-Super Prodott tagħhom. Xi darba nirranġaw il-conveyors tal-assemblaġġ, ikollna ħin. Jien se nwieġebhom:

Verità l-ewwel, jew għaliex sistema jeħtieġ li tkun iddisinjata bbażata fuq id-disinn tad-database
Original, Alan O'Rourke, Munzell tal-Udjenza

Iżda f'Hibernate/JPA huwa daqshekk faċli li tikteb kodiċi Java.

Tassew. Għal Hibernate u l-utenti tiegħu, din hija kemm barka kif ukoll saħta. F'Hibernate tista' sempliċement tikteb ftit entitajiet, bħal dan:

	@Entity
class Book {
  @Id
  int id;
  String title;
}

U kważi kollox lest. Issa huwa f'idejn Hibernate li jiġġenera d-"dettalji" kumplessi ta' kif eżattament din l-entità se tiġi definita fid-DDL tad-"djalett" SQL tiegħek:

	CREATE TABLE book (
  id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
  title VARCHAR(50),
 
  CONSTRAINT pk_book PRIMARY KEY (id)
);
 
CREATE INDEX i_book_title ON book (title);

... u tibda tħaddem l-applikazzjoni. Opportunità tassew sabiħa biex tibda malajr u tipprova affarijiet differenti.

Madankollu, jekk jogħġbok ippermettili. Kont nigdeb.

  • Hibernate fil-fatt se jinforza d-definizzjoni ta 'din iċ-ċavetta primarja msemmija?
  • Hibernate se joħloq indiċi fit-TITLE? – Naf żgur li se jkollna bżonnha.
  • Hibernate se jagħmel eżattament din iċ-ċavetta li tidentifika fl-Ispeċifikazzjoni tal-Identità?

Probabbilment le. Jekk qed tiżviluppa l-proġett tiegħek mill-bidu, dejjem ikun konvenjenti li sempliċement tarmi d-database l-antika u tiġġenera waħda ġdida hekk kif iżżid l-annotazzjonijiet meħtieġa. Għalhekk, l-entità Ktieb fl-aħħar mill-aħħar se tieħu l-forma:

	@Entity
@Table(name = "book", indexes = {
  @Index(name = "i_book_title", columnList = "title")
})
class Book {
  @Id
  @GeneratedValue(strategy = IDENTITY)
  int id;
  String title;
}

Kessaħ. Riġenera. Għal darb'oħra, f'dan il-każ se jkun faċli ħafna fil-bidu.

Imma int ikollok tħallas għaliha aktar tard

Illum jew għada jkollok tidħol fil-produzzjoni. Dak huwa meta dan il-mudell se jieqaf jaħdem. Minħabba li:

Fil-produzzjoni, mhux se jkun aktar possibbli, jekk meħtieġ, li tintrema d-database l-antika u tibda mill-bidu. Id-database tiegħek se ssir wirt.

Minn issa u għal dejjem ikollok tikteb Skripts ta' migrazzjoni DDL, pereżempju, bl-użu ta' Flyway. X'se jiġri mill-entitajiet tiegħek f'dan il-każ? Tista' jew tadattahom manwalment (u b'hekk tirdoppja l-ammont ta' xogħol tiegħek), jew tista' tgħid lil Hibernate biex tirriġenerahom għalik (kemm huma probabbli dawk iġġenerati b'dan il-mod biex jilħqu l-aspettattivi tiegħek?) Jew il-mod, titlef.

Allura ladarba tidħol fil-produzzjoni ser ikollok bżonn irqajja sħan. U jeħtieġ li jitpoġġew fil-produzzjoni malajr ħafna. Peress li inti ma ppreparajtx u ma organizzajtx pipeline bla xkiel tal-migrazzjonijiet tiegħek għall-produzzjoni, inti garża kollox. U allura m'għadx għandek ħin biex tagħmel kollox b'mod korrett. U tikkritika lil Hibernate, għax dejjem tort ta’ xi ħadd ieħor, mhux int...

Minflok, l-affarijiet setgħu saru kompletament differenti mill-bidu nett. Per eżempju, poġġi roti tondi fuq rota.

Database l-ewwel

Il-"verità" reali fl-iskema tad-database tiegħek u s-"sovranità" fuqha jinsabu fid-database. L-iskema hija definita biss fid-database nnifisha u mkien ieħor, u kull klijent għandu kopja ta 'din l-iskema, għalhekk jagħmel sens perfett li tinforza l-konformità mal-iskema u l-integrità tagħha, biex tagħmel dan id-dritt fid-database - fejn l-informazzjoni hija maħżuna.
Dan huwa qadim, anke għerf mibrumin. Iċ-ċwievet primarji u uniċi huma tajbin. Ċwievet barranin huma tajbin. Il-kontroll tar-restrizzjonijiet huwa tajjeb. Asserzjonijiet - Multa.

Barra minn hekk, dan mhux kollox. Pereżempju, billi tuża Oracle, inti probabilment trid tispeċifika:

  • F'liema tablespace tinsab il-mejda tiegħek?
  • X'inhu l-valur PCTFREE tiegħu?
  • X'inhu d-daqs tal-cache fis-sekwenza tiegħek (wara l-id)

Dan jista 'ma jkunx importanti f'sistemi żgħar, iżda m'għandekx għalfejn tistenna sakemm tmur fil-qasam tad-dejta kbira—tista' tibda tibbenefika minn ottimizzazzjonijiet tal-ħażna pprovduti mill-bejjiegħ bħal dawk imsemmija hawn fuq ħafna aktar kmieni. L-ebda wieħed mill-ORMs li rajt (inkluż jOOQ) ma jipprovdi aċċess għas-sett sħiħ ta' għażliet DDL li tista' tkun trid tuża fid-database tiegħek. L-ORMs joffru xi għodod li jgħinuk tikteb DDL.

Iżda fl-aħħar tal-ġurnata, ċirkwit iddisinjat tajjeb huwa miktub bl-idejn fid-DDL. Kwalunkwe DDL iġġenerat huwa biss approssimazzjoni tiegħu.

Xi ngħidu dwar il-mudell tal-klijent?

Kif imsemmi hawn fuq, fuq il-klijent ser ikollok bżonn kopja tal-iskema tad-database tiegħek, il-veduta tal-klijent. M'hemmx għalfejn insemmi, din il-fehma tal-klijent għandha tkun sinkronizzata mal-mudell attwali. X'inhu l-aħjar mod biex jinkiseb dan? Bl-użu ta 'ġeneratur tal-kodiċi.

Id-databases kollha jipprovdu l-meta-informazzjoni tagħhom permezz tal-SQL. Ara kif tikseb it-tabelli kollha mid-database tiegħek f'djaletti SQL differenti:

	-- H2, HSQLDB, MySQL, PostgreSQL, SQL Server
SELECT table_schema, table_name
FROM information_schema.tables
 
-- DB2
SELECT tabschema, tabname
FROM syscat.tables
 
-- Oracle
SELECT owner, table_name
FROM all_tables
 
-- SQLite
SELECT name
FROM sqlite_master
 
-- Teradata
SELECT databasename, tablename
FROM dbc.tables

Dawn il-mistoqsijiet (jew oħrajn simili, skont jekk għandekx tikkunsidra wkoll fehmiet, fehmiet materjalizzati, funzjonijiet valutati fuq tabella) huma wkoll eżegwiti billi ċċempel DatabaseMetaData.getTables() minn JDBC, jew bl-użu tal-meta-modulu jOOQ.

Mir-riżultati ta' mistoqsijiet bħal dawn, huwa relattivament faċli li tiġġenera kwalunkwe rappreżentazzjoni min-naħa tal-klijent tal-mudell tad-database tiegħek, irrispettivament minn liema teknoloġija tuża fuq il-klijent.

  • Jekk qed tuża JDBC jew Spring, tista 'toħloq sett ta' kostanti ta 'sekwenza
  • Jekk tuża JPA, tista' tiġġenera l-entitajiet infushom
  • Jekk tuża jOOQ, tista 'tiġġenera l-meta-mudell jOOQ

Skont kemm tkun offruta funzjonalità mill-API tal-klijent tiegħek (eż. jOOQ jew JPA), il-mudell meta ġġenerat jista' jkun verament għani u komplut. Ħu, pereżempju, il-possibbiltà ta' tingħaqdiet impliċiti, introdott f'jOOQ 3.11, li tiddependi fuq meta informazzjoni ġġenerata dwar ir-relazzjonijiet ewlenin barranin li jeżistu bejn it-tabelli tiegħek.

Issa kull żieda fid-database awtomatikament taġġorna l-kodiċi tal-klijent. Immaġina pereżempju:

ALTER TABLE book RENAME COLUMN title TO book_title;

Verament trid tagħmel dan ix-xogħol darbtejn? Fl-ebda każ. Sempliċement ikkommetti d-DDL, mexxiha permezz tal-pipeline tal-bini tiegħek, u ikseb l-entità aġġornata:

@Entity
@Table(name = "book", indexes = {
 
  // Вы об этом задумывались?
  @Index(name = "i_book_title", columnList = "book_title")
})
class Book {
  @Id
  @GeneratedValue(strategy = IDENTITY)
  int id;
 
  @Column("book_title")
  String bookTitle;
}

Jew il-klassi jOOQ aġġornata. Ħafna mill-bidliet DDL jaffettwaw ukoll is-semantika, mhux biss is-sintassi. Għalhekk, jista 'jkun utli li tħares fil-kodiċi kkompilat biex tara liema kodiċi se (jew jista') jiġi affettwat mill-inkrement tad-database tiegħek.

L-unika verità

Irrispettivament minn liema teknoloġija tuża, dejjem hemm mudell wieħed li huwa l-uniku sors ta 'verità għal xi sottosistema - jew, għall-inqas, għandna nistinkaw għal dan u nevitaw tali konfużjoni ta' intrapriża, fejn "verità" hija kullimkien u mkien f'daqqa. . Kollox jista 'jkun ħafna aktar sempliċi. Jekk qed tiskambja fajls XML ma 'xi sistema oħra, uża biss XSD. Ħares lejn il-meta-mudell INFORMATION_SCHEMA minn jOOQ f'forma XML:
https://www.jooq.org/xsd/jooq-meta-3.10.0.xsd

  • XSD huwa mifhum tajjeb
  • XSD tokenizes kontenut XML tajjeb ħafna u jippermetti validazzjoni fil-lingwi kollha tal-klijenti
  • XSD huwa verġjonat tajjeb u għandu kompatibilità b'lura avvanzata
  • XSD jista 'jiġi tradott f'kodiċi Java bl-użu ta' XJC

L-aħħar punt huwa importanti. Meta nikkomunikaw ma' sistema esterna li tuża messaġġi XML, irridu nkunu ċerti li l-messaġġi tagħna huma validi. Dan huwa faċli ħafna li jinkiseb billi tuża JAXB, XJC u XSD. Ikun ġenn kbir li wieħed jaħseb li, b'approċċ ta' disinn "Java first" fejn nagħmlu l-messaġġi tagħna bħala oġġetti Java, li b'xi mod jistgħu jiġu mmappjati b'mod koerenti ma' XML u jintbagħtu għal sistema oħra għall-konsum. XML iġġenerat b'dan il-mod ikun ta 'kwalità fqira ħafna, mhux dokumentat, u diffiċli biex jiġi żviluppat. Kieku kien hemm ftehim ta 'livell ta' servizz (SLA) għal tali interface, aħna immedjatament inkabbruh.

Onestament, dan huwa dak li jiġri l-ħin kollu ma 'JSON APIs, iżda dik hija storja oħra, jien ser quarrel darba li jmiss...

Databases: huma l-istess ħaġa

Meta taħdem ma 'databases, tirrealizza li huma kollha bażikament simili. Il-bażi hija proprjetarja tad-dejta tagħha u trid tmexxi l-iskema. Kwalunkwe modifika li ssir lill-iskema trid tiġi implimentata direttament fid-DDL sabiex is-sors uniku tal-verità jiġi aġġornat.

Meta jkun seħħ aġġornament tas-sors, il-klijenti kollha għandhom jaġġornaw ukoll il-kopji tagħhom tal-mudell. Xi klijenti jistgħu jinkitbu f'Java billi jużaw jOOQ u Hibernate jew JDBC (jew it-tnejn). Klijenti oħra jistgħu jinkitbu f'Perl (nawgurawhom biss xorti tajba), filwaqt li oħrajn jistgħu jinkitbu f'C#. Ma jimpurtax. Il-mudell ewlieni jinsab fid-database. Mudelli ġġenerati bl-użu ta 'ORMs huma ġeneralment ta' kwalità fqira, dokumentati ħażin, u diffiċli biex jiġu żviluppati.

Mela tiżbaljax. Tiżbaljax mill-bidu nett. Xogħol mid-database. Ibni pipeline ta 'skjerament li jista' jiġi awtomatizzat. Ippermetti lill-ġeneraturi tal-kodiċi biex tagħmilha faċli biex tikkopja l-mudell tad-database tiegħek u tispiċċah fuq il-klijenti. U tieqaf tinkwieta dwar il-ġeneraturi tal-kodiċi. Huma tajbin. Magħhom int se ssir aktar produttiv. Għandek bżonn biss li tqatta 'ftit ħin twaqqafhom mill-bidu nett - u mbagħad jistennewk snin ta' produttività akbar, li se jiffurmaw l-istorja tal-proġett tiegħek.

Tirringrazzjix s'issa, aktar tard.

kjarifika

Biex tkun ċara: Dan l-artikolu bl-ebda mod ma jippromwovi li għandek bżonn tgħawweġ is-sistema kollha (jiġifieri, dominju, loġika tan-negozju, eċċ., eċċ.) biex taqbel mal-mudell tad-database tiegħek. Dak li qed ngħid f'dan l-artikolu huwa li l-kodiċi tal-klijent li jinteraġixxi mad-database għandu jaġixxi fuq il-bażi tal-mudell tad-database, sabiex huwa stess ma jirriproduċix il-mudell tad-database fi status ta '"l-ewwel klassi". Din il-loġika normalment tinsab fis-saff ta 'aċċess għad-dejta fuq il-klijent tiegħek.

F'arkitetturi b'żewġ livelli, li għadhom ippreservati f'xi postijiet, mudell ta 'sistema bħal dan jista' jkun l-uniku wieħed possibbli. Madankollu, fil-biċċa l-kbira tas-sistemi s-saff ta 'aċċess għad-dejta jidhirli li huwa "subsistema" li tiġbor il-mudell tad-database.

Eċċezzjonijiet

Hemm eċċezzjonijiet għal kull regola, u diġà għedt li l-approċċ tal-ġenerazzjoni tad-database-ewwel u tal-kodiċi tas-sors kultant jista 'jkun mhux xieraq. Hawn huma ftit eċċezzjonijiet bħal dawn (probabbilment hemm oħrajn):

  • Meta l-iskema mhix magħrufa u jeħtieġ li tiġi skoperta. Per eżempju, inti fornitur ta 'għodda li tgħin lill-utenti jinnavigaw kwalunkwe dijagramma. Ugh. M'hemm l-ebda ġenerazzjoni ta 'kodiċi hawn. Iżda xorta waħda, id-database tiġi l-ewwel.
  • Meta ċirkwit irid jiġi ġġenerat fuq il-fly biex issolvi xi problema. Dan l-eżempju jidher qisu verżjoni kemmxejn fantasiża tal-mudell valur tal-attribut tal-entità, jiġifieri, m'għandekx verament skema definita b'mod ċar. F'dan il-każ, ħafna drabi tista' lanqas tkun ċert li RDBMS ikun jaqbel għalik.

L-eċċezzjonijiet huma min-natura tagħhom eċċezzjonali. Fil-biċċa l-kbira tal-każijiet li jinvolvu l-użu ta 'RDBMS, l-iskema hija magħrufa minn qabel, tirrisjedi fi ħdan l-RDBMS u hija l-uniku sors ta' "verità", u l-klijenti kollha jridu jakkwistaw kopji derivati ​​minnha. Idealment, għandek bżonn tuża ġeneratur tal-kodiċi.

Sors: www.habr.com

Żid kumment