Egia lehenik, edo zergatik diseinatu behar den sistema bat datu-basearen diseinuan oinarrituta

Aupa Habr!

Gaia ikertzen jarraitzen dugu Java ΠΈ Udaberriko, datu-base mailan barne. Gaur gonbidatzen zaitugu irakurtzera zergatik, aplikazio handiak diseinatzerakoan, datu-basearen egiturak izan behar duen garrantzia erabakigarria, eta ez Java kodea, nola egiten den eta zein salbuespen dauden arau honetan.

Artikulu berandu samarrean azalduko dut zergatik uste dudan ia kasu guztietan aplikazio bateko datu-eredua "datu-basetik" diseinatu behar dela "Java-ren gaitasunetatik" (edo edozein bezero-hizkuntzatik). lanean). Bigarren planteamendua eginez, zure proiektua hazten hasten denean minaren eta sufrimenduaren bide luze bati prestatzen ari zara.

artikuluan oinarrituta idatzi zen galdera bat, Stack Overflow-en emandakoa.

Reddit-i buruzko eztabaida interesgarriak ataletan /r/java ΠΈ /r/programazioa.

Kodea sortzea

Zein harritu ninduen jOOQ-a ezagutu ondoren, jOOQ-k iturburu-kodeen sorkuntzan oinarritzen duelako serioski funtzionatzeko iturburu-kodea sortzean. Inork ez zaitu eragozten jOOQ zuk komeni zaizun moduan erabiltzea, ezta kodea sortzera behartzen ere. Baina jOOQ-rekin lan egiteko modu lehenetsia (eskuliburuan deskribatzen den bezala) datu-basearen eskema (oinarrizko) batekin hasten zara, alderantzizko ingeniaritza egin jOOQ kode-sorgailua erabiliz, zure taulak ordezkatzen dituzten klase multzo bat lortzeko, eta ondoren idatzi mota. -Taula hauetarako kontsulta seguruak:

	for (Record2<String, String> record : DSL.using(configuration)
//   ^^^^^^^^^^^^^^^^^^^^^^^ Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ ΠΎ Ρ‚ΠΈΠΏΠ°Ρ… Π²Ρ‹Π²Π΅Π΄Π΅Π½Π° Π½Π° 
//   основании сгСнСрированного ΠΊΠΎΠ΄Π°, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ссылаСтся ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ΅
// Π½ΠΈΠΆΠ΅ условиС SELECT 
 
       .select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
//           vvvvv ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ сгСнСрированныС ΠΈΠΌΠ΅Π½Π°
       .from(ACTOR)
       .orderBy(1, 2)) {
    // ...
}

Kodea eskuz sortzen da muntaiatik kanpo, edo eskuz muntaia bakoitzean. Esate baterako, birsorkuntza hori berehala gerta daiteke Flyway datu-baseen migrazioa, eskuz edo automatikoki ere egin daitekeena.

Iturburu kodea sortzea

Artikulu honetan zehatz-mehatz eztabaidatuko ez ditudan kodeak sortzeko planteamendu hauekin lotutako filosofia, abantailak eta desabantailak daude -eskuzkoak eta automatikoak-. Baina, oro har, sortzen den kodearen helburu nagusia da Javan erreproduzitzeko aukera ematen diguna, gure sistemaren barruan edo kanpoan hartzen dugun β€œegia” hori. Zentzu batean, horixe egiten dute konpilatzaileek bytecode, makina-kode edo beste iturburu-koderen bat sortzen dutenean - gure "egia"-ren irudikapena beste hizkuntza batean lortzen dugu, arrazoi zehatzak kontuan hartu gabe.

Horrelako kode-sorgailu asko daude. Adibidez, XJC-k Java kodea sor dezake XSD edo WSDL fitxategietan oinarrituta. Printzipioa beti berdina da:

  • Badago egiaren bat (barnekoa edo kanpokoa) - adibidez, zehaztapen bat, datu-eredu bat, etab.
  • Egia honen tokiko irudikapena behar dugu gure programazio-lengoaian.

Gainera, ia beti komeni da halako irudikapen bat sortzea erredundantzia ekiditeko.

Mota-hornitzaileak eta oharren tratamendua

Oharra: jOOQ-rako kodea sortzeko beste ikuspegi modernoagoa eta zehatzagoa da mota hornitzaileak erabiltzea. F#-n inplementatzen diren bezala. Kasu honetan, kodea konpilatzaileak sortzen du, benetan konpilazio fasean. Printzipioz, kode hori ez dago iturburu moduan. Java-k antzeko tresnak ditu, baina ez hain dotoreak - oharpen-prozesadoreak, adibidez, Lombok.

Zentzu batean, hemen lehen kasuan bezala gertatzen dira, honako hauek izan ezik:

  • Ez duzu sortzen den kodea ikusten (agian egoera hau ez da hain gaitzesgarria iruditzen norbaiti?)
  • Motak eman daitezkeela ziurtatu behar duzu, hau da, "egia" beti eskuragarri egon behar da. Hau erraza da Lomboken kasuan, β€œegia” ohartaraziz. Apur bat konplikatuagoa da etengabe eskuragarri dagoen zuzeneko konexio baten mende dauden datu-baseen ereduekin.

Zein da kodea sortzearen arazoa?

Kode-sorkuntza nola exekutatu onenaren -eskuz edo automatikoki- exekutatzeko galdera delikatuaz gain, aipatu behar dugu badagoela kodea sortzea batere beharrezkoa ez dela uste duten pertsonak. Gehien topatu dudan ikuspuntu honen justifikazioa da orduan zaila dela eraikuntza kanalizazioa ezartzea. Bai, benetan zaila da. Azpiegitura kostu gehigarriak sortzen dira. Produktu jakin batekin hasten ari bazara (dela jOOQ, edo JAXB, edo Hibernate, etab.), ekoizpen-ingurune bat konfiguratzeak APIa bera ikasten pasatzeko denbora behar du, hartatik balioa atera dezazun. .

Sorgailuaren egitura ulertzearekin lotutako kostuak handiegiak badira, orduan, hain zuzen ere, APIak lan eskasa egin zuen kode-sorgailuaren erabilgarritasunari dagokionez (eta geroago ikusten da erabiltzaileen pertsonalizazioa ere zaila dela). Erabilgarritasunak lehentasun handiena izan behar du horrelako edozein APIrentzat. Baina hau kodea sortzearen aurkako argudio bat besterik ez da. Bestela, guztiz eskuzkoa da barneko edo kanpoko egiaren tokiko irudikapena idaztea.

Askok esango dute ez dutela denborarik hau guztia egiteko. Super Produkturako epeak agortzen ari dira. Noizbait muntaketa-garraiatzaileak txukunduko ditugu, denbora izango dugu. erantzungo diet:

Egia lehenik, edo zergatik diseinatu behar den sistema bat datu-basearen diseinuan oinarrituta
Original, Alan O'Rourke, Audience Stack

Baina Hibernate/JPAn oso erraza da Java kodea idaztea.

Benetan. Hibernate eta bere erabiltzaileentzat, hau bedeinkapena eta madarikazio bat da. Hibernate-n entitate pare bat besterik gabe idatzi ditzakezu, honela:

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

Eta ia dena prest dago. Orain Hibernate-ri dagokio zure SQL "dialekto"-ko DDLan entitate hau zehatz-mehatz nola definituko den "xehetasun" konplexuak sortzea:

	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);

... eta hasi aplikazioa exekutatzen. Oso aukera polita azkar hasteko eta gauza desberdinak probatzeko.

Hala ere, mesedez, baimendu. Gezurretan ari nintzen.

  • Hibernatek benetan ezarriko al du gako nagusi izendatu honen definizioa?
  • Hibernatek aurkibide bat sortuko al du TITLE-n? – Ziur badakit beharko dugula.
  • Hibernatek zehazki egingo al du gako hau identitate-zehaztapenean identifikatzea?

Seguruenik ez. Zure proiektua hutsetik garatzen ari bazara, beti da komenigarria datu-base zaharra baztertzea eta berri bat sortzea beharrezko oharrak gehitu bezain laster. Horrela, Liburuaren entitateak, azken batean, honela hartuko du:

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

Cool. Birsortu. Berriz ere, kasu honetan hasieran oso erraza izango da.

Baina gero ordaindu beharko duzu

Lehenago edo beranduago produkzioan sartu beharko duzu. Orduantxe geldituko da eredu honek funtzionatzea. Zeren:

Ekoizpenean, jada ezin izango da, beharrezkoa bada, datu-base zaharra baztertu eta hutsetik hastea. Zure datu-basea ondare bihurtuko da.

Hemendik aurrera eta betiko idatzi beharko duzu DDL migrazio-scriptak, adibidez, Flyway erabiliz. Zer gertatuko da zure entitateekin kasu honetan? Eskuz molda ditzakezu (eta, beraz, zure lan-karga bikoiztu), edo Hibernate-ri esan diezaiokezu birsortzeko (zenbat litekeena da horrela sortutakoak zure itxaropenak betetzeko?) Edozein modutan, galdu egiten duzu.

Beraz, produkzioan sartzen zarenean adabaki beroak beharko dituzu. Eta oso azkar jarri behar dira ekoizpenean. Ekoizpenerako zure migrazioen kanalizazio leuna prestatu eta antolatu ez zenuenez, dena adabakitzen duzu. Eta orduan jada ez duzu denbora guztia behar bezala egiteko. Eta Hibernate kritikatzen duzu, beti beste norbaiten errua baita, zuk ez...

Horren ordez, gauzak guztiz ezberdin egin zitezkeen hasiera-hasieratik. Adibidez, jarri bizikleta bati gurpil biribilak.

Datu-basea lehenik

Zure datu-basearen eskemaren benetako "egia" eta horren gaineko "burujabetza" datu-basean dago. Eskema datu-basean bertan eta inon baino ez da definitzen, eta bezero bakoitzak eskema honen kopia bat du, beraz, zentzuzkoa da eskema eta bere osotasuna betetzea ezartzea, datu-basean ondo egiteko - informazioa dagoen tokian. gordeta.
Hau jakituria zaharra da, baita jakituria ere. Gako nagusiak eta bakarrak onak dira. Kanpoko giltzak onak dira. Murrizketak egiaztatzea ona da. Baieztapenak - Ondo.

Gainera, hori ez da guztia. Adibidez, Oracle erabiliz, ziurrenik zehaztu nahi zenuke:

  • Zein mahai-espaziotan dago zure mahaia?
  • Zein da bere PCTFREE balioa?
  • Zein da zure sekuentziako cache-tamaina (id-aren atzean)

Baliteke hori sistema txikietan garrantzitsua ez izatea, baina ez duzu datu handien eremura joan arte itxaron beharrik; askoz lehenago has zaitezke saltzaileek emandako biltegiratze-optimizazioei etekina ateratzen lehen aipatutakoak bezalakoak. Ikusi ditudan ORM-ek (jOOQ barne) ez du zure datu-basean erabili nahi dituzun DDL aukeren multzo osorako sarbidea ematen. ORMek DDL idazten laguntzen duten tresna batzuk eskaintzen dituzte.

Baina azkenean, ondo diseinatutako zirkuitu bat DDLn eskuz idatzita dago. Sortutako edozein DDL haren hurbilketa bat baino ez da.

Zer gertatzen da bezero ereduarekin?

Goian esan bezala, bezeroan zure datu-basearen eskemaren kopia bat beharko duzu, bezeroaren ikuspegia. Aipatu beharrik ez dago bezeroaren ikuspegi honek benetako ereduarekin sinkronizatuta egon behar duela. Zein da hori lortzeko modurik onena? Kode-sorgailu bat erabiliz.

Datu-base guztiek beren meta informazioa ematen dute SQL bidez. Hona hemen zure datu-baseko taula guztiak SQL dialekto ezberdinetan nola lortu:

	-- 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

Kontsulta hauek (edo antzekoak, ikuspegiak, ikuspegi materializatuak, taula-baliodun funtzioak ere kontuan hartu behar dituzun ala ez) deituz ere exekutatzen dira. DatabaseMetaData.getTables() JDBCtik, edo jOOQ meta-modulua erabiliz.

Kontsulten emaitzetatik, nahiko erraza da zure datu-base-ereduaren edozein bezeroen ordezkaritza sortzea, bezeroan erabiltzen duzun teknologia edozein dela ere.

  • JDBC edo Spring erabiltzen ari bazara, kate-konstante multzo bat sor dezakezu
  • JPA erabiltzen baduzu, entitateak beraiek sor ditzakezu
  • jOOQ erabiltzen baduzu, jOOQ meta-eredua sor dezakezu

Zure bezeroaren APIak (adibidez, jOOQ edo JPA) eskaintzen duen funtzionalitatearen arabera, sortutako meta-eredua oso aberatsa eta osoa izan daiteke. Hartu, adibidez, elkartze inplizituen aukera, jOOQ 3.11n sartua, zure taulen artean dauden atzerriko gako-erlazioei buruzko sortutako meta-informazioan oinarritzen dena.

Orain datu-basearen gehikuntzak automatikoki eguneratuko du bezeroaren kodea. Imajinatu adibidez:

ALTER TABLE book RENAME COLUMN title TO book_title;

Benetan nahi al zenuke lan hau bi aldiz egin? Inola ere ez. Besterik gabe, konprometitu DDL, exekutatu zure eraikuntza kanalizazioan eta lortu eguneratutako entitatea:

@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;
}

Edo jOOQ klase eguneratua. DDL aldaketa gehienek semantikari ere eragiten diote, ez sintaxiari bakarrik. Hori dela eta, erabilgarria izan daiteke konpilatutako kodean begiratzea zure datu-basearen gehikuntzak zer kode izango duen (edo izan dezakeen) eragina ikusteko.

Egia bakarra

Erabiltzen duzun teknologia edozein dela ere, beti dago azpisistema batzuen egiaren iturri bakarra den eredu bat - edo, gutxienez, horretan ahalegindu beharko genuke eta enpresa-nahasmena saihestu beharko genuke, non "egia" edonon eta inon dagoen aldi berean. . Dena askoz errazagoa izan liteke. XML fitxategiak beste sistema batekin trukatzen ari bazara, erabili XSD. Begiratu jOOQ-ren INFORMATION_SCHEMA meta-eredua XML formatuan:
https://www.jooq.org/xsd/jooq-meta-3.10.0.xsd

  • XSD ondo ulertzen da
  • XSD-k XML edukia oso ondo onartzen du eta bezeroen hizkuntza guztietan balioztatzea ahalbidetzen du
  • XSD ondo bertsionatuta dago eta atzerako bateragarritasun aurreratua du
  • XSD Java kodeara itzul daiteke XJC erabiliz

Azken puntua garrantzitsua da. XML mezuak erabiliz kanpoko sistema batekin komunikatzean, gure mezuak baliozkoak direla ziurtatu nahi dugu. Hori oso erraza da lortzen JAXB, XJC eta XSD erabiliz. Erokeria hutsa litzateke pentsatzea, gure mezuak Java objektu gisa egiten ditugun "Java lehenik" diseinu-ikuspegiarekin, nolabait XML-ra koherenteki mapatu eta beste sistema batera bidal daitezkeela kontsumitzeko. Modu honetan sortutako XML kalitate txarrekoa izango litzateke, dokumenturik gabekoa eta garatzeko zaila izango litzateke. Interfaze horretarako zerbitzu-mailako akordioa (SLA) balego, berehala izorratuko genuke.

Egia esan, hau da JSON APIekin uneoro gertatzen dena, baina hori beste istorio bat da, hurrengoan liskarra egingo dut...

Datu-baseak: gauza bera dira

Datu-baseekin lan egitean, funtsean denak antzekoak direla konturatzen zara. Oinarria bere datuen jabea da eta eskema kudeatu behar du. Eskeman egindako edozein aldaketa DDLan zuzenean inplementatu behar da, egiaren iturri bakarra eguneratu dadin.

Iturburuaren eguneraketa gertatzen denean, bezero guztiek ereduaren kopiak ere eguneratu behar dituzte. Bezero batzuk Javan idatz daitezke jOOQ eta Hibernate edo JDBC erabiliz (edo biak). Beste bezero batzuk Perl-en idatz daitezke (zorte ona opa diegu), beste batzuk C#-n idatz daitezke. Berdin du. Eredu nagusia datu-basean dago. ORMak erabiliz sortutako ereduak kalitate txarrekoak, gaizki dokumentatuak eta garatzeko zailak izan ohi dira.

Beraz, ez egin akatsik. Ez egin akatsik hasiera-hasieratik. Datu-basetik lan egin. Eraiki inplementazio kanalizazioa automatizatu daitekeen. Gaitu kode-sorgailuak zure datu-basearen eredua kopiatzea eta bezeroengana botatzea errazteko. Eta utzi kode sortzaileei buruz kezkatzea. Onak dira. Haiekin produktiboagoa izango zara. Denbora pixka bat eman behar duzu hasiera-hasieratik konfiguratzen, eta gero produktibitatea handitzeko urteak zain dituzu, eta horrek zure proiektuaren historia osatuko du.

Ez eman oraindik eskerrik asko, gero.

Argitzeko

Argi izateko: artikulu honek ez du inolaz ere defendatzen sistema osoa okertu behar duzula (hau da, domeinua, negozio-logika, etab., etab.) zure datu-basearen eredua egokitzeko. Artikulu honetan esaten dudana da datu-basearekin elkarreragiten duen bezero-kodeak datu-basearen ereduaren arabera jokatu behar duela, berak datu-base eredua "lehen mailako" egoeran erreproduzi ez dezan. Logika hau zure bezeroaren datuetarako sarbidearen geruzan kokatu ohi da.

Leku batzuetan oraindik kontserbatzen diren bi mailatako arkitekturetan, halako sistema-eredu bat izan daiteke posible bakarra. Hala ere, sistema gehienetan datu-sarbide-geruza datu-basearen eredua kapsulatzen duen "azpisistema" bat dela iruditzen zait.

salbuespenak

Arau guztietan salbuespenak daude, eta dagoeneko esan dut datu-basea lehenik eta iturburu-kodea sortzeko ikuspegia batzuetan desegokia izan daitekeela. Hona hemen halako salbuespen batzuk (baliteke beste batzuk ere):

  • Eskema ezezaguna denean eta aurkitu behar denean. Adibidez, erabiltzaileei edozein diagrama nabigatzen laguntzen dien tresna baten hornitzailea zara. Uf. Hemen ez dago koderik sortzen. Hala ere, datu-basea da lehena.
  • Zirkuitu bat hegan sortu behar denean arazoren bat konpontzeko. Adibide honek ereduaren bertsio apur bat fantasiazko bat dirudi entitate-atributuaren balioa, hau da, ez duzu benetan eskema argi eta garbi zehazturik. Kasu honetan, askotan ezin duzu ziur egon RDBMS bat zuretzat egokia izango denik.

Salbuespenak berez apartekoak dira. RDBMS baten erabilera dakarten kasu gehienetan, eskema aldez aurretik ezagutzen da, RDBMS barruan dago eta "egia" iturri bakarra da, eta bezero guztiek eskuratu behar dituzte hortik eratorritako kopiak. Egokiena, kode-sorgailu bat erabili behar duzu.

Iturria: www.habr.com

Gehitu iruzkin berria