Otitọ ni akọkọ, tabi idi ti eto naa nilo lati ṣe apẹrẹ ti o da lori eto data data

Hey Habr!

A tesiwaju lati ṣawari koko-ọrọ naa Java и Springpẹlu ni ipele data data. Loni a nfunni lati ka nipa idi ti, nigbati o ba n ṣe apẹrẹ awọn ohun elo nla, o jẹ ipilẹ data, kii ṣe koodu Java, ti o yẹ ki o jẹ pataki pataki, bawo ni a ṣe ṣe eyi, ati kini awọn imukuro si ofin yii.

Ninu nkan yii kuku ti o ti sọ, Emi yoo ṣe alaye idi ti Mo ro pe ni gbogbo awọn ọran, awoṣe data ninu ohun elo yẹ ki o ṣe apẹrẹ “lati ibi ipamọ data” ju “lati awọn agbara Java” (tabi eyikeyi ede alabara ti o jẹ. ṣiṣẹ pẹlu). Nipa yiyan ọna keji, o tẹ ọna pipẹ ti irora ati ijiya ni kete ti iṣẹ akanṣe rẹ bẹrẹ lati dagba.

A kọ nkan naa da lori ibeere kan, fun lori Stack aponsedanu.

Awọn ijiroro ti o nifẹ lori reddit ni awọn apakan /r/java и /r/ siseto.

koodu iran

Bawo ni o ṣe ya mi lẹnu pe iru Layer kekere ti awọn olumulo ti, ti o ti mọ jOOQ, binu si otitọ pe jOOQ dale lori ipilẹṣẹ koodu orisun lati ṣiṣẹ. Ko si ẹnikan ti o da ọ duro lati lo jOOQ bi o ṣe rii pe o yẹ, ko si si ẹnikan ti o fi ipa mu ọ lati lo iran koodu. Ṣugbọn nipasẹ aiyipada (gẹgẹbi a ti ṣalaye ninu iwe afọwọkọ), jOOQ ṣiṣẹ bii eyi: o bẹrẹ pẹlu eto ipilẹ data (ojogun), yi ẹlẹrọ pada pẹlu olupilẹṣẹ koodu jOOQ lati gba awọn kilasi ti o ṣe aṣoju awọn tabili rẹ, lẹhinna kọ iru- awọn ibeere ailewu lodi si awọn tabili wọnyi:

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

Awọn koodu ti wa ni ti ipilẹṣẹ boya pẹlu ọwọ ita ti awọn Kọ, tabi pẹlu ọwọ lori gbogbo Kọ. Fun apẹẹrẹ, iru isọdọtun le tẹle lẹsẹkẹsẹ lẹhin Iṣilọ data data Flyway, eyiti o tun le ṣee ṣe pẹlu ọwọ tabi laifọwọyi.

Orisun koodu iran

Awọn ọgbọn oriṣiriṣi wa, awọn anfani ati awọn aila-nfani ti o ni nkan ṣe pẹlu awọn isunmọ wọnyi si iran koodu - afọwọṣe ati adaṣe - eyiti Emi kii yoo jiroro ni alaye ni nkan yii. Ṣugbọn, ni gbogbogbo, gbogbo aaye ti koodu ti ipilẹṣẹ ni pe o fun ọ laaye lati tun ṣe ni Java "otitọ" ti a gba fun lasan, boya laarin eto wa tabi ita rẹ. Ni ọna kan, awọn olupilẹṣẹ ti o ṣe ipilẹṣẹ bytecode, koodu ẹrọ, tabi iru koodu miiran lati koodu orisun ṣe ohun kanna - a gba aṣoju “otitọ” wa ni ede miiran, laibikita awọn idi kan pato.

Nibẹ ni o wa ọpọlọpọ iru koodu Generators. Fun apere, XJC le ṣe ipilẹṣẹ koodu Java ti o da lori awọn faili XSD tabi WSDL. Ilana nigbagbogbo jẹ kanna:

  • Otitọ kan wa (ti abẹnu tabi ita) - fun apẹẹrẹ, sipesifikesonu, awoṣe data, ati bẹbẹ lọ.
  • A nilo aṣoju agbegbe ti otitọ yii ni ede siseto wa.

Pẹlupẹlu, o fẹrẹ jẹ imọran nigbagbogbo lati ṣe agbekalẹ iru aṣoju bẹ - lati yago fun apọju.

Iru Olupese ati Annotation Processing

Akiyesi: Omiiran, igbalode diẹ sii ati ọna pato si iran koodu fun jOOQ pẹlu lilo awọn olupese iru, bi wọn ti ṣe imuse ni F #. Ni idi eyi, koodu ti wa ni ipilẹṣẹ nipasẹ alakojo, kosi ni ipele akopo. Ni opo, iru koodu ko si ni irisi awọn koodu orisun. Ni Java, iru wa, botilẹjẹpe kii ṣe bi didara, awọn irinṣẹ - iwọnyi jẹ awọn ilana asọye, fun apẹẹrẹ, Lombok.

Ni ori kan, awọn nkan kanna n ṣẹlẹ nibi bi ninu ọran akọkọ, ayafi:

  • O ko rii koodu ti ipilẹṣẹ (boya ipo yii ko dabi ohun irira si ẹnikan?)
  • O gbọdọ rii daju pe awọn oriṣi le pese, iyẹn ni, “otitọ” gbọdọ wa nigbagbogbo. Eyi rọrun ninu ọran Lombok, eyiti o ṣe alaye “otitọ”. O nira diẹ sii pẹlu awọn awoṣe data data ti o dale lori asopọ ifiwe ti o wa nigbagbogbo.

Kini iṣoro pẹlu ipilẹṣẹ koodu?

Ni afikun si ibeere ẹtan ti bii o ṣe dara lati bẹrẹ ipilẹṣẹ koodu - pẹlu ọwọ tabi laifọwọyi, Mo ni lati darukọ pe awọn eniyan wa ti o gbagbọ pe iran koodu ko nilo rara. Idalare fun aaye yii, eyiti Mo wa kọja nigbagbogbo, ni pe lẹhinna o nira lati ṣeto opo gigun ti epo. Bẹẹni, o nira gaan. Awọn idiyele amayederun afikun wa. Ti o ba kan bẹrẹ pẹlu ọja kan pato (jẹ jOOQ, tabi JAXB, tabi Hibernate, ati bẹbẹ lọ), o gba akoko lati ṣeto ijoko iṣẹ kan ti iwọ yoo fẹ lati lo kikọ API funrararẹ lati gba iye ninu rẹ. .

Ti awọn idiyele ti o nii ṣe pẹlu agbọye ẹrọ ti monomono naa ga ju, lẹhinna, nitootọ, API ṣe iṣẹ ti ko dara lori lilo ti olupilẹṣẹ koodu (ati ni ọjọ iwaju o han pe isọdi ninu rẹ tun nira). Lilo yẹ ki o jẹ pataki pataki fun eyikeyi iru API. Ṣugbọn iyẹn jẹ ariyanjiyan kan kan lodi si iran koodu. Bibẹẹkọ, kọ patapata pẹlu ọwọ aṣoju agbegbe ti inu tabi otitọ ita.

Ọpọlọpọ yoo sọ pe wọn ko ni akoko lati ṣe gbogbo eyi. Wọn wa ni akoko ipari fun Ọja Super wọn. Ni ojo kan nigbamii a yoo comb awọn conveyors ijọ, a yoo ni akoko. Emi o da wọn lohùn:

Otitọ ni akọkọ, tabi idi ti eto naa nilo lati ṣe apẹrẹ ti o da lori eto data data
Atilẹba, Alan O'Rourke, jepe Stack

Ṣugbọn ni Hibernate / JPA o rọrun pupọ lati kọ koodu “ni Java”.

Looto. Fun Hibernate ati awọn olumulo rẹ, eyi jẹ ẹbun ati eegun kan. Ni Hibernate, o le nirọrun kọ awọn nkan meji kan, bii eyi:

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

Ati pe o fẹrẹ jẹ pe ohun gbogbo ti ṣetan. Ni bayi ọpọlọpọ ti Hibernate ni lati ṣe agbekalẹ “awọn alaye” eka ti bii iru nkan gangan yoo ṣe tumọ ni DDL ti “dialect” rẹ ti SQL:

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

... ati bẹrẹ ṣiṣe ohun elo naa. Ẹya ti o dara pupọ lati dide ati ṣiṣe ni iyara ati gbiyanju awọn nkan oriṣiriṣi.

Sibẹsibẹ, jẹ ki mi. Mo parọ.

  • Njẹ Hibernate yoo fi ipa mu itumọ ti bọtini akọkọ ti a darukọ yii?
  • Njẹ Hibernate yoo ṣẹda atọka lori TITLE? Mo mọ daju pe a nilo rẹ.
  • Njẹ Hibernate yoo jẹ ki bọtini yii jẹ bọtini idanimọ ni pato Identity?

Boya beeko. Ti o ba n ṣe agbekalẹ iṣẹ akanṣe rẹ lati ibere, o rọrun nigbagbogbo lati sọ ọrọ data atijọ silẹ ki o ṣe ipilẹṣẹ tuntun kan ni kete ti o ba ṣafikun awọn asọye pataki. Nitorinaa, nkankan Iwe naa yoo gba fọọmu nikẹhin:

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

Itura. Tuntun-pada. Lẹẹkansi, ninu ọran yii, yoo rọrun pupọ ni ibẹrẹ.

Ṣugbọn iwọ yoo ni lati sanwo fun nigbamii.

Laipẹ tabi nigbamii iwọ yoo ni lati lọ si iṣelọpọ. Ti o ni nigbati awọn awoṣe da ṣiṣẹ. Nitoripe:

Ni iṣelọpọ, kii yoo ṣee ṣe mọ, ti o ba jẹ dandan, lati sọ data data atijọ silẹ ki o bẹrẹ ohun gbogbo lati ibere. Ipamọ data rẹ yoo yipada si ọkan ti o jẹ julọ.

Lati isisiyi lọ ati lailai iwọ yoo ni lati kọ Awọn iwe afọwọkọ ijira DDL, fun apẹẹrẹ lilo Flyway. Ati kini yoo ṣẹlẹ si awọn ile-iṣẹ rẹ ninu ọran yii? O le ṣe deede wọn pẹlu ọwọ (ati ilọpo iṣẹ ṣiṣe rẹ) tabi jẹ ki Hibernate tun wọn pada fun ọ (bawo ni o ṣe ṣee ṣe eyi ti ipilẹṣẹ ni ọna yii lati pade awọn ireti rẹ?) O padanu boya ọna.

Nitorinaa, ni kete ti o ba lọ si iṣelọpọ, iwọ yoo nilo awọn abulẹ gbona. Ati pe wọn nilo lati mu wa si iṣelọpọ ni iyara pupọ. Niwọn igba ti o ko ti mura ati ṣeto pipelining didan ti awọn iṣiwa rẹ fun iṣelọpọ, o n parẹ lainidii. Ati lẹhinna o ko ni akoko lati ṣe ohun gbogbo ti o tọ. Ati pe o kọlu Hibernate, nitori pe o jẹ ẹbi ẹnikẹni nigbagbogbo, ṣugbọn kii ṣe iwọ…

Dipo, lati ibẹrẹ akọkọ, ohun gbogbo le ti ṣe ni iyatọ patapata. Fun apẹẹrẹ, fi awọn kẹkẹ yika lori kẹkẹ.

Database akọkọ

“Otitọ” gidi ninu ero data data rẹ ati “aṣẹ ọba-alaṣẹ” lori rẹ wa laarin ibi ipamọ data naa. Eto naa jẹ asọye nikan ni ibi ipamọ data funrararẹ ati ko si ibi miiran, ati pe ọkọọkan awọn alabara ni ẹda kan ti ero yii, nitorinaa o jẹ oye pipe lati fi ipa mu ifaramọ si ero ati iduroṣinṣin rẹ, lati ṣe ni ẹtọ ni ibi ipamọ data - nibiti alaye ti wa ni ipamọ.
Eleyi jẹ atijọ ani hackneyed ọgbọn. Awọn bọtini akọkọ ati alailẹgbẹ dara. Awọn bọtini ajeji jẹ itanran. Ṣiṣayẹwo ihamọ jẹ dara. Awọn iṣeduro - O dara.

Ati pe, kii ṣe gbogbo rẹ. Fun apẹẹrẹ, lilo Oracle, o le fẹ lati pato:

  • Kini aaye tabili tabili rẹ wa ninu
  • Kini iye PCTFREE rẹ
  • Kini iwọn kaṣe ni ọkọọkan rẹ (lẹhin id)

Gbogbo eyi le ma ṣe pataki ni awọn ọna ṣiṣe kekere, ṣugbọn kii ṣe pataki lati duro titi iyipada si ijọba ti “data nla” - o le bẹrẹ lati ni anfani lati awọn iṣapeye ibi ipamọ ti olupese ti pese, gẹgẹbi awọn ti a mẹnuba loke, pupọ tẹlẹ. Ko si ọkan ninu awọn ORM ti Mo ti rii (pẹlu jOOQ) ti o pese iraye si akojọpọ awọn aṣayan DDL ti o le fẹ lati lo ninu aaye data rẹ. Awọn ORM nfunni awọn irinṣẹ diẹ lati ṣe iranlọwọ fun ọ lati kọ DDL.

Ṣugbọn ni opin ọjọ naa, apẹrẹ ti a ṣe daradara ni a kọ ni ọwọ ni DDL. Eyikeyi ti ipilẹṣẹ DDL jẹ isunmọ rẹ nikan.

Kini nipa awoṣe alabara?

Gẹgẹbi a ti sọ loke, lori alabara iwọ yoo nilo ẹda kan ti ero data data rẹ, wiwo alabara. Tialesealaini lati sọ, wiwo alabara gbọdọ wa ni imuṣiṣẹpọ pẹlu awoṣe gidi. Kini ọna ti o dara julọ lati ṣaṣeyọri eyi? Pẹlu a koodu monomono.

Gbogbo awọn apoti isura infomesonu pese alaye-meta wọn nipasẹ SQL. Eyi ni bii o ṣe le gba gbogbo awọn tabili ni oriṣiriṣi awọn ede SQL lati ibi ipamọ data rẹ:

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

Awọn ibeere wọnyi (tabi awọn iru, ti o da lori boya o tun ni lati gbero awọn iwo, awọn iwo ohun elo, awọn iṣẹ ti o ni idiyele tabili) tun ṣe nipasẹ pipe DatabaseMetaData.getTables() lati JDBC, tabi lilo jOOQ meta-module.

Lati awọn abajade iru awọn ibeere bẹẹ, o rọrun pupọ lati ṣe agbekalẹ eyikeyi aṣoju-ẹgbẹ alabara ti awoṣe data data rẹ, laibikita iru imọ-ẹrọ ti o lo lori alabara.

  • Ti o ba nlo JDBC tabi Orisun omi o le ṣẹda ṣeto ti awọn iduro okun
  • Ti o ba nlo JPA, lẹhinna o le ṣe ipilẹṣẹ awọn nkan funrararẹ
  • Ti o ba nlo jOOQ o le ṣe ina apẹrẹ jOOQ meta

Da lori iye agbara API alabara rẹ nfunni (fun apẹẹrẹ jOOQ tabi JPA), awoṣe meta ti ipilẹṣẹ le jẹ ọlọrọ ati pipe. Mu, fun apẹẹrẹ, o ṣeeṣe lati darapọ mọ, ti a ṣe ni jOOQ 3.11, eyiti o da lori alaye-meta ti ipilẹṣẹ nipa awọn ibatan bọtini ajeji laarin awọn tabili rẹ.

Bayi eyikeyi data afikun yoo ṣe imudojuiwọn koodu alabara laifọwọyi. Fojuinu fun apẹẹrẹ:

ALTER TABLE book RENAME COLUMN title TO book_title;

Ṣe iwọ yoo fẹ gaan lati ṣe iṣẹ yii lẹẹmeji? Ni ọran kankan. A kan ṣe DDL naa, ṣiṣe nipasẹ opo gigun ti epo rẹ, ati gba nkan ti a ṣe imudojuiwọn:

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

Tabi kilaasi jOOQ ti a ṣe imudojuiwọn. Pupọ julọ awọn iyipada DDL tun kan awọn atunmọ, kii ṣe sintasi nikan. Nitorinaa, o le rọrun lati rii ninu koodu ti o ṣajọ kini koodu yoo (tabi o le ni ipa) nipasẹ jijẹ data data rẹ.

Awọn nikan otitọ

Laibikita iru imọ-ẹrọ ti o lo, awoṣe kan nigbagbogbo wa ti o jẹ orisun otitọ nikan fun diẹ ninu awọn eto ipilẹ-tabi o kere ju a yẹ ki o tiraka fun eyi ki o yago fun rudurudu ile-iṣẹ nibiti “otitọ” wa nibikibi ati besi ni ẹẹkan. Ohun gbogbo le rọrun pupọ. Ti o ba kan paarọ awọn faili XML pẹlu eto miiran, lo XSD nikan. Wo jOOQ's INFORMATION_SCHEMA meta-awoṣe ni fọọmu XML:
https://www.jooq.org/xsd/jooq-meta-3.10.0.xsd

  • XSD ni oye daradara
  • XSD ṣe samisi akoonu XML daradara pupọ ati gba afọwọsi ni gbogbo awọn ede alabara
  • XSD jẹ ẹya daradara ati ibaramu sẹhin pupọ
  • XSD le ṣe tumọ si koodu Java nipa lilo XJC

Awọn ti o kẹhin ojuami jẹ pataki. Nigbati o ba n ba eto ita sọrọ nipa lilo awọn ifiranṣẹ XML, a fẹ lati rii daju pe awọn ifiranṣẹ wa wulo. Eyi rọrun pupọ lati ṣaṣeyọri pẹlu JAXB, XJC ati XSD. Yoo jẹ isinwin lasan lati ronu pe, ni ọna apẹrẹ akọkọ-Java nibiti a ti ṣe awọn ifiranṣẹ wa bi awọn nkan Java, wọn le bakan ṣe ni oye si XML ati firanṣẹ fun agbara si eto miiran. XML ti a ṣe ni ọna yii yoo jẹ didara ko dara, ti ko ni iwe-aṣẹ, ati pe o nira lati dagbasoke. Ti adehun ba wa lori ipele ti didara iṣẹ (SLA) lori iru wiwo, a yoo dabaru lẹsẹkẹsẹ.

Lati so ooto, eyi ni deede ohun ti o ṣẹlẹ ni gbogbo igba pẹlu JSON API, ṣugbọn iyẹn ni itan miiran, Emi yoo jiyan nigba miiran…

Awọn aaye data: wọn jẹ kanna

Nṣiṣẹ pẹlu awọn apoti isura infomesonu, o loye pe gbogbo wọn jẹ ipilẹ kanna. Ibi-ipamọ data ni data rẹ ati pe o gbọdọ ṣakoso eto naa. Eyikeyi awọn iyipada ti a ṣe si eto naa gbọdọ jẹ imuse taara ni DDL ki orisun kan ti otitọ jẹ imudojuiwọn.

Nigbati imudojuiwọn orisun ba ti waye, gbogbo awọn alabara gbọdọ tun ṣe imudojuiwọn awọn ẹda ti awoṣe wọn. Diẹ ninu awọn alabara le kọ ni Java nipa lilo jOOQ ati Hibernate tabi JDBC (tabi mejeeji). Awọn onibara miiran le kọ ni Perl (jẹ ki a fẹ wọn ni orire), awọn miiran ni C #. Ko ṣe pataki. Awọn ifilelẹ ti awọn awoṣe jẹ ninu awọn database. Awọn awoṣe ti ipilẹṣẹ ORM nigbagbogbo jẹ didara ko dara, ti ni akọsilẹ ti ko dara, ati nira lati dagbasoke.

Nitorina maṣe ṣe awọn aṣiṣe. Maṣe ṣe awọn aṣiṣe lati ibẹrẹ. Ṣiṣẹ lati ibi ipamọ data. Kọ opo gigun ti imuṣiṣẹ ti o le ṣe adaṣe. Mu awọn olupilẹṣẹ koodu ṣiṣẹ ni irọrun daakọ awoṣe data data rẹ ki o da silẹ lori awọn alabara. Ati ki o da aibalẹ nipa awọn olupilẹṣẹ koodu. Wọn dara. Pẹlu wọn, iwọ yoo di diẹ si iṣelọpọ. Gbogbo ohun ti o nilo lati ṣe ni lilo akoko diẹ lati ṣeto wọn lati ibẹrẹ, ati pe iwọ yoo ni awọn ọdun ti ilọsiwaju iṣẹ lati kọ itan iṣẹ akanṣe rẹ.

Maṣe dupẹ lọwọ mi sibẹsibẹ, nigbamii.

Alaye lori

Lati ṣe kedere: Nkan yii ko ṣe ni eyikeyi ọna ti o ṣagbe pe gbogbo eto (ie, agbegbe, ọgbọn iṣowo, ati bẹbẹ lọ, ati bẹbẹ lọ) nilo lati ni rọ lati baamu awoṣe data data rẹ. Ohun ti Mo n sọrọ nipa ninu nkan yii ni pe koodu alabara ti o ṣe ajọṣepọ pẹlu data data yẹ ki o ṣiṣẹ lori ipilẹ awoṣe data ki o ko tun ṣe awoṣe data data ni ipo “kilasi akọkọ”. Iru ọgbọn bẹ nigbagbogbo wa ni ipele iwọle data lori alabara rẹ.

Ni awọn faaji ipele meji, eyiti o tun tọju ni awọn aaye kan, iru awoṣe eto le jẹ ọkan ti o ṣeeṣe. Bibẹẹkọ, ninu ọpọlọpọ awọn ọna ṣiṣe, ipele iraye si data dabi si mi lati jẹ “subsystem” ti o ṣe agbekalẹ awoṣe data data.

Awọn imukuro

Awọn imukuro wa si gbogbo ofin, ati pe Mo ti sọ tẹlẹ pe data akọkọ ati ọna iran koodu orisun le jẹ aibojumu nigbakan. Eyi ni tọkọtaya ti iru awọn imukuro (o ṣee ṣe awọn miiran):

  • Nigbati eto naa jẹ aimọ ati pe o nilo lati ṣii. Fun apẹẹrẹ, o pese ohun elo kan lati ṣe iranlọwọ fun awọn olumulo lilö kiri ni eyikeyi aworan atọka. Phew. Ko si iran koodu nibi. Sugbon si tun - awọn database akọkọ ti gbogbo.
  • Nigba ti a Circuit nilo lati wa ni ti ipilẹṣẹ lori awọn fly lati yanju diẹ ninu awọn isoro. Apeere yii dabi pe o jẹ ẹya frilly die-die ti apẹrẹ naa iye eroja nkankan, i.e., o ko gan ni kan daradara-telẹ ero. Ni ọran yii, igbagbogbo o ko le rii daju rara pe RDBMS yoo baamu fun ọ.

Awọn imukuro jẹ nipasẹ iseda alailẹgbẹ. Ni ọpọlọpọ awọn ọran ti o kan lilo RDBMS, ero naa ni a mọ tẹlẹ, o wa ninu RDBMS ati pe o jẹ orisun nikan ti “otitọ”, ati pe gbogbo awọn alabara ni lati gba awọn ẹda ti o gba lati ọdọ rẹ. Bi o ṣe yẹ, eyi yẹ ki o kan olupilẹṣẹ koodu kan.

orisun: www.habr.com

Fi ọrọìwòye kun