Ang kwento ng isang maliit na proyekto na may labindalawang taon ang haba (tungkol sa BIRMA.NET sa unang pagkakataon at tapat na unang-kamay)

Ang kapanganakan ng proyektong ito ay maaaring ituring na isang maliit na ideya na dumating sa akin sa isang lugar sa pagtatapos ng 2007, na kung saan ay nakalaan upang mahanap ang pangwakas na anyo nito pagkalipas lamang ng 12 taon (sa puntong ito sa oras - siyempre, kahit na ang kasalukuyang pagpapatupad, ayon sa sa may-akda, ay lubos na kasiya-siya).

Nagsimula ang lahat nang, sa proseso ng pagtupad sa aking mga opisyal na tungkulin noon sa silid-aklatan, iginuhit ko ang pansin sa katotohanan na ang proseso ng pagpasok ng data mula sa na-scan na teksto ng mga talahanayan ng mga nilalaman ng mga publikasyon ng libro (at musika) sa umiiral na database, tila, ay maaaring makabuluhang pinasimple at awtomatiko, sinasamantala ang pag-aari ng kaayusan at pag-uulit ng lahat ng data na kinakailangan para sa pag-input, tulad ng pangalan ng may-akda ng artikulo (kung pinag-uusapan natin ang tungkol sa isang koleksyon ng mga artikulo), ang pamagat ng ang artikulo (o ang subtitle na makikita sa talaan ng mga nilalaman) at ang numero ng pahina ng kasalukuyang item sa talaan ng mga nilalaman. Sa una, halos kumbinsido ako na ang isang sistema na angkop para sa pagsasagawa ng gawaing ito ay madaling mahanap sa Internet. Nang ang ilang sorpresa ay sanhi ng katotohanan na hindi ako makahanap ng ganoong proyekto, nagpasya akong subukang ipatupad ito sa aking sarili.

Pagkatapos ng medyo maikling panahon, nagsimulang gumana ang unang prototype, na agad kong sinimulan na gamitin sa aking pang-araw-araw na gawain, sabay-sabay na pag-debug nito sa lahat ng mga halimbawa na dumating sa aking kamay. Sa kabutihang palad, sa aking karaniwang lugar ng trabaho, kung saan hindi ako isang programmer, nakaligtas pa rin ako sa nakikitang "downtime" sa aking trabaho, kung saan masinsinan kong i-debug ang aking utak - isang halos hindi maisip na bagay sa kasalukuyang mga katotohanan, na nagpapahiwatig araw-araw na ulat sa gawaing ginawa sa araw. Ang proseso ng pag-polish ng programa ay tumagal ng kabuuang hindi bababa sa isang taon, ngunit kahit na pagkatapos nito ay halos hindi matatawag na ganap na matagumpay ang resulta - napakaraming iba't ibang mga konsepto ang unang inilatag na hindi lubos na malinaw para sa pagpapatupad: mga opsyonal na elemento na maaaring laktawan; pasulong na pagtingin sa mga elemento (para sa layunin ng pagpapalit ng mga nakaraang elemento sa mga resulta ng paghahanap); kahit ang sarili nating pagtatangka na ipatupad ang isang bagay tulad ng mga regular na expression (na may natatanging syntax). Dapat kong sabihin na bago ito ay medyo tinalikuran ko ang programming (sa loob ng mga 8 taon, kung hindi higit pa), kaya ang bagong pagkakataon na ilapat ang aking mga kasanayan sa isang kawili-wili at kinakailangang gawain ay ganap na nakuha ang aking pansin. Hindi kataka-taka na ang nagresultang source code - sa kawalan ng anumang malinaw na diskarte sa disenyo nito sa aking bahagi - ay medyo mabilis na naging isang hindi maisip na mishmash ng magkakaibang mga piraso sa wikang C na may ilang mga elemento ng C++ at mga aspeto ng visual programming (sa una ito ay nagpasya na gumamit ng isang sistema ng disenyo bilang Borland C++ Builder - "halos Delphi, ngunit sa C"). Gayunpaman, ang lahat ng ito sa huli ay nagbunga sa pag-automate ng mga pang-araw-araw na aktibidad ng aming aklatan.

Kasabay nito, nagpasya ako, kung sakali, na kumuha ng mga kurso para sanayin ang mga propesyonal na software developer. Hindi ko alam kung posible bang matutunan ang "maging programmer" mula sa simula doon, ngunit isinasaalang-alang ang mga kasanayan na mayroon ako sa oras na iyon, medyo nakabisado ko ang mga teknolohiya na mas nauugnay sa oras na iyon, tulad ng bilang C#, Visual Studio para sa pagpapaunlad sa ilalim ng .NET, pati na rin ang ilang teknolohiyang nauugnay sa Java, HTML at SQL. Ang buong pagsasanay ay tumagal ng kabuuang dalawang taon, at nagsilbing panimulang punto para sa isa pang proyekto ko, na sa huli ay umabot ng ilang taon - ngunit ito ay isang paksa para sa isang hiwalay na publikasyon. Dito ay nararapat lamang na tandaan na sinubukan kong iakma ang mga pag-unlad na mayroon na ako sa inilarawang proyekto upang lumikha ng isang ganap na window application sa C# at WinForms na nagpapatupad ng kinakailangang pag-andar, at gamitin ito bilang batayan para sa paparating na diploma project.
Sa paglipas ng panahon, ang ideyang ito ay nagsimulang tila sa akin ay karapat-dapat na ipahayag sa mga taunang kumperensya na may partisipasyon ng mga kinatawan ng iba't ibang mga aklatan gaya ng "LIBKOM" at "CRIMEA". Ang ideya, oo, ngunit hindi ang aking pagpapatupad nito sa oras na iyon. Pagkatapos ay umaasa din ako na may magsusulat muli nito gamit ang mga mas karampatang diskarte. Sa isang paraan o iba pa, sa pamamagitan ng 2013 nagpasya akong magsulat ng isang ulat sa aking paunang gawain at ipadala ito sa Conference Organizing Committee na may isang aplikasyon para sa isang grant upang lumahok sa kumperensya. Medyo nagulat ako, naaprubahan ang aking aplikasyon, at nagsimula akong gumawa ng ilang mga pagpapabuti sa proyekto upang maihanda ito para sa pagtatanghal sa kumperensya.

Sa oras na iyon, ang proyekto ay nakatanggap na ng isang bagong pangalan na BIRMA, nakakuha ng iba't ibang karagdagang (hindi gaanong ganap na ipinatupad, ngunit sa halip ay ipinapalagay) na mga kakayahan - lahat ng detalye ay makikita sa aking ulat.

Sa totoo lang, mahirap tawaging kumpleto ang BIRMA 2013; Sa totoo lang, ito ay isang napaka-hacky na craft na ginawa sa pagmamadali. Sa mga tuntunin ng code, halos walang mga espesyal na pagbabago, maliban sa isang medyo walang magawa na pagtatangka na lumikha ng ilang uri ng pinag-isang syntax para sa parser, sa hitsura na nakapagpapaalaala sa IRBIS 64 formatting language (at sa katunayan, din ang sistema ng ISIS - na may mga panaklong bilang mga paikot na istruktura; bakit Noong panahong iyon, naisip kong medyo cool). Ang parser ay walang pag-asa na natisod sa mga bilog na ito ng mga panaklong na may naaangkop na uri (dahil ang mga panaklong ay gumanap din ng isa pang tungkulin, ibig sabihin, minarkahan nila ang mga opsyonal na istruktura sa panahon ng pag-parse na maaaring laktawan). Muli kong isinangguni ang lahat ng gustong makilala ang noon ay mahirap isipin, hindi makatarungang syntax ng BIRMA nang mas detalyado sa aking ulat noong panahong iyon.

Sa pangkalahatan, bukod sa pakikibaka sa sarili kong parser, wala na akong masasabi pa tungkol sa code ng bersyong ito - maliban sa reverse conversion ng mga umiiral nang source sa C++ habang pinapanatili ang ilang tipikal na feature ng .NET code (to be honest, it's mahirap maunawaan , kung ano ang eksaktong nag-udyok sa akin na ibalik ang lahat - marahil ang ilang hangal na takot para sa pagpapanatiling lihim ng aking mga source code, na para bang ito ay isang bagay na katumbas ng lihim na recipe ng Coca-Cola).

Marahil ang hangal na desisyon na ito ay namamalagi din sa dahilan ng mga kahirapan sa pagpapares ng nagresultang DLL library sa umiiral na interface ng isang home-made workstation para sa pagpasok ng data sa isang electronic catalog (oo, hindi ko binanggit ang isa pang mahalagang katotohanan: mula ngayon, lahat ang code ng "engine" ng BIRMA ay tulad ng inaasahan, ito ay nakahiwalay sa bahagi ng interface at nakabalot sa naaangkop na DLL). Bakit kailangang magsulat ng isang hiwalay na workstation para sa mga layuning ito, na gayon pa man, sa hitsura at paraan ng pakikipag-ugnayan nito sa gumagamit, walang kahihiyang kinopya ang parehong workstation na "Catalogizer" ng IRBIS 64 system - ito ay isang hiwalay na tanong. Sa madaling salita: nagbigay ito ng kinakailangang katatagan sa aking mga pag-unlad noon para sa aking proyekto sa pagtatapos (kung hindi, ang hindi natutunaw na parser engine lamang ay hindi sapat). Bilang karagdagan, nakatagpo ako pagkatapos ng ilang mga paghihirap sa pagpapatupad ng interface ng workstation ng Cataloger gamit ang sarili kong mga module, na ipinatupad sa parehong C++ at C#, at direktang ma-access ang aking makina.

Sa pangkalahatan, kakaiba, ito ay medyo clumsy na prototype ng hinaharap na BIRMA.NET na nakatadhana na maging aking "workhorse" sa susunod na apat na taon. Hindi masasabi na sa panahong ito ay hindi ko man lang sinubukang maghanap ng mga paraan para sa isang bago, mas kumpletong pagpapatupad ng isang matagal nang ideya. Sa iba pang mga inobasyon, dapat ay mayroon nang mga nested cyclic sequence na maaaring may kasamang mga opsyonal na elemento - ito ay kung paano ko bibigyang-buhay ang ideya ng mga unibersal na template para sa bibliographic na paglalarawan ng mga publikasyon at iba't ibang mga kawili-wiling bagay. Gayunpaman, sa aking mga praktikal na gawain sa oras na iyon, ang lahat ng ito ay hindi gaanong hinihiling, at ang pagpapatupad na mayroon ako noong panahong iyon ay sapat na para sa pagpasok ng mga talaan ng nilalaman. Bilang karagdagan, ang direksyon ng pag-unlad ng aming silid-aklatan ay nagsimulang lumihis nang higit pa tungo sa digitalization ng mga archive ng museo, pag-uulat at iba pang mga aktibidad na hindi gaanong interes sa akin, na sa huli ay pinilit akong umalis dito, na nagbibigay-daan sa mga nais maging mas masaya sa lahat ng ito.

Kabalintunaan, ito ay pagkatapos ng mga dramatikong kaganapan na ang proyekto ng BIRMA, na sa oras na iyon ay mayroon nang lahat ng mga katangian ng isang tipikal na pangmatagalang proyekto ng konstruksiyon, ay tila nagsimulang kumuha ng kanyang pinakahihintay na bagong buhay! Nagkaroon ako ng mas maraming libreng oras para sa walang ginagawa na pag-iisip, muli akong nagsimulang magsuklay sa World Wide Web sa paghahanap ng katulad na bagay (sa kabutihang palad, ngayon ay maaari ko nang hulaan na hanapin ang lahat ng ito hindi lamang kahit saan, ngunit sa GitHub), at sa isang lugar sa At the simula ng taong ito, sa wakas ay nakatagpo ako ng katumbas na produkto mula sa kilalang kumpanya ng Salesforce sa ilalim ng hindi gaanong mahalagang pangalan Gorp. Sa sarili nito, magagawa nito ang halos lahat ng kailangan ko mula sa naturang parser engine - ibig sabihin, matalinong ihiwalay ang mga indibidwal na fragment mula sa di-makatwirang, ngunit malinaw na nakabalangkas na teksto, habang mayroong isang medyo user-friendly na interface para sa end user, kabilang ang mga naiintindihan na essences, bilang isang pattern, template at pangyayari, at kasabay nito ang paggamit ng pamilyar na syntax ng mga regular na expression, na nagiging hindi maihahambing na mas nababasa dahil sa paghahati sa mga itinalagang semantic group para sa pag-parse.

Sa pangkalahatan, nagpasya ako na ito ang isa Gorp (Nagtataka ako kung ano ang ibig sabihin ng pangalang ito? Marahil ay isang uri ng "pangkalahatang oriented na regular na parser"?) - kung ano mismo ang hinahanap ko sa loob ng mahabang panahon. Totoo, ang agarang pagpapatupad nito para sa sarili kong mga pangangailangan ay nagkaroon ng ganoong problema na ang makinang ito ay nangangailangan ng masyadong mahigpit na pagsunod sa pagkakasunud-sunod ng istruktura ng pinagmulang teksto. Para sa ilang mga ulat tulad ng mga log file (ibig sabihin, sila ay inilagay ng mga developer bilang malinaw na mga halimbawa ng paggamit ng proyekto), ito ay medyo angkop, ngunit para sa parehong mga teksto ng na-scan na mga talahanayan ng mga nilalaman, ito ay malamang na hindi. Pagkatapos ng lahat, ang parehong pahina na may talaan ng mga nilalaman ay maaaring magsimula sa mga salitang "Talaan ng Mga Nilalaman", "Mga Nilalaman" at anumang iba pang mga paunang paglalarawan na hindi namin kailangang ilagay sa mga resulta ng nilalayong pagsusuri (at manu-manong putulin ang mga ito sa bawat oras ay hindi rin maginhawa). Bilang karagdagan, sa pagitan ng mga indibidwal na umuulit na elemento, tulad ng pangalan ng may-akda, pamagat at numero ng pahina, ang pahina ay maaaring maglaman ng isang tiyak na dami ng basura (halimbawa, mga guhit, at mga random na character lamang), na maganda rin na magagawang putulin. Gayunpaman, ang huling aspeto ay hindi pa gaanong makabuluhan, ngunit dahil sa una, ang umiiral na pagpapatupad ay hindi maaaring magsimulang maghanap ng mga kinakailangang istruktura sa teksto mula sa isang tiyak na lugar, ngunit sa halip ay pinoproseso lamang ito mula sa simula, hindi natagpuan ang tinukoy na mga pattern doon at... natapos ang aking trabaho. Malinaw, ang ilang pagsasaayos ay kailangan upang hindi bababa sa payagan ang ilang espasyo sa pagitan ng mga paulit-ulit na istruktura, at iyon ang nagpabalik sa akin sa trabaho.

Ang isa pang problema ay ang proyekto mismo ay ipinatupad sa Java, at kung ako ay nagplano sa hinaharap na ipatupad ang ilang paraan ng interfacing ng teknolohiyang ito sa mga pamilyar na aplikasyon para sa pagpasok ng data sa mga umiiral nang database (tulad ng Irbis's "Cataloguer"), at least At least gawin ito sa C# at .NET. Hindi ang Java mismo ay isang masamang wika - minsan ko pa itong ginamit upang ipatupad ang isang kawili-wiling window application na nagpatupad ng functionality ng isang domestic programmable calculator (bilang bahagi ng isang proyekto ng kurso). At sa mga tuntunin ng syntax ito ay halos kapareho sa parehong C-sharp. Well, ito ay isang plus lamang: mas madali para sa akin na tapusin ang isang umiiral na proyekto. Gayunpaman, hindi ko nais na muling bumulusok sa medyo hindi pangkaraniwang mundo ng mga window (o sa halip, desktop) na mga teknolohiya ng Java - pagkatapos ng lahat, ang wika mismo ay hindi "iniayon" para sa gayong paggamit, at hindi ako naghahangad ng pag-uulit ng ang nakaraang karanasan. Marahil ito ay tiyak dahil ang C# kasabay ng WinForms ay mas malapit sa Delphi, kung saan marami sa atin ang minsang nagsimula. Sa kabutihang palad, ang kinakailangang solusyon ay natagpuan nang mabilis - sa anyo ng proyekto IKVM.NET, na nagpapadali sa pagsasalin ng mga umiiral nang Java program sa pinamamahalaang .NET code. Totoo, ang proyekto mismo ay inabandona na ng mga may-akda noong panahong iyon, ngunit ang pinakabagong pagpapatupad nito ay nagpapahintulot sa akin na lubos na matagumpay na maisagawa ang mga kinakailangang aksyon para sa mga pinagmulang teksto Gorp.

Kaya ginawa ko ang lahat ng kinakailangang pagbabago at binuo ang lahat sa isang DLL ng naaangkop na uri, na madaling "kunin" ng anumang mga proyekto para sa .NET Framework na nilikha sa Visual Studio. Pansamantala, gumawa ako ng isa pang layer para sa maginhawang presentasyon ng mga resulta na ibinalik Gorp, sa anyo ng mga kaukulang istruktura ng data na magiging maginhawa upang iproseso sa isang view ng talahanayan (ginagamit bilang batayan ang parehong mga hilera at column; parehong mga key ng diksyunaryo at mga numerical index). Buweno, ang mga kinakailangang kagamitan mismo para sa pagproseso at pagpapakita ng mga resulta ay naisulat nang mabilis.

Gayundin, ang proseso ng pag-aangkop ng mga template para sa bagong makina upang turuan itong mag-parse ng mga umiiral nang sample ng mga na-scan na teksto ng mga talaan ng nilalaman ay hindi nagdulot ng anumang mga espesyal na komplikasyon. Sa katunayan, hindi ko na kinailangan pang sumangguni sa aking mga nakaraang template: Nilikha ko lang ang lahat ng kinakailangang mga template mula sa simula. Bukod dito, kung ang mga template na idinisenyo upang gumana sa nakaraang bersyon ng system ay nagtatakda ng isang medyo makitid na balangkas para sa mga teksto na maaaring mai-parse nang tama sa kanilang tulong, ginawang posible ng bagong makina na bumuo ng medyo unibersal na mga template na angkop para sa ilang uri ng markup sa minsan. Sinubukan ko pang magsulat ng ilang uri ng komprehensibong template para sa anumang di-makatwirang talaan ng mga nilalaman ng teksto, bagaman, siyempre, kahit na sa lahat ng mga bagong posibilidad na nagbubukas para sa akin, kabilang ang, sa partikular, ang limitadong kakayahang ipatupad ang parehong nested na paulit-ulit na pagkakasunud-sunod ( tulad ng, halimbawa, mga apelyido at inisyal ng ilang magkakasunod na may-akda), ito ay naging isang utopia.

Marahil sa hinaharap posible na ipatupad ang isang tiyak na konsepto ng mga meta-template, na magagawang suriin ang pinagmulan ng teksto para sa pagsunod sa ilang magagamit na mga template nang sabay-sabay, at pagkatapos, alinsunod sa mga resulta na nakuha, piliin ang pinaka-angkop, gamit ang ilang uri ng matalinong algorithm. Ngunit ngayon ay mas nag-aalala ako sa isa pang tanong. Parang parser Gorp, sa kabila ng lahat ng versatility nito at ang mga pagbabagong ginawa ko, likas pa rin itong walang kakayahang gawin ang isang tila simpleng bagay na nagawa ng aking self-written parser mula sa pinakaunang bersyon. Namely: nagkaroon siya ng kakayahang hanapin at i-extract mula sa source text ang lahat ng fragment na tumutugma sa mask na tinukoy sa loob ng template na ginamit sa tamang lugar, habang hindi interesado sa kung ano ang nilalaman ng ibinigay na text sa mga puwang sa pagitan ng mga fragment na ito. Sa ngayon, bahagyang napabuti ko lamang ang bagong makina, na nagpapahintulot sa ito na maghanap para sa lahat ng posibleng mga bagong pag-uulit ng isang naibigay na pagkakasunud-sunod ng naturang mga maskara mula sa kasalukuyang posisyon, na iniiwan ang posibilidad para sa pagkakaroon sa teksto ng mga hanay ng mga di-makatwirang mga character na ganap na hindi nakilala sa pag-parse, nakapaloob sa pagitan ng mga nakitang umuulit na istruktura. Gayunpaman, hindi nito ginawang posible na itakda ang susunod na maskara anuman ang mga resulta ng paghahanap para sa nakaraang fragment gamit ang kaukulang maskara: ang higpit ng inilarawan na istraktura ng teksto ay hindi pa rin nag-iiwan ng puwang para sa mga di-makatwirang pagsasama ng mga hindi regular na character.

At kung para sa mga halimbawa ng mga talahanayan ng mga nilalaman na nakita ko ang problemang ito ay hindi pa mukhang napakaseryoso, kung gayon kapag sinusubukang mag-aplay ng isang bagong mekanismo ng pag-parse sa isang katulad na gawain ng pag-parse ng mga nilalaman ng isang website (i.e. ang parehong pag-parse), ang mga limitasyon ay dito sila ay lumitaw sa lahat ng kanilang mga halata. Pagkatapos ng lahat, napakadaling itakda ang mga kinakailangang mask para sa mga fragment ng web markup, kung saan matatagpuan ang data na hinahanap natin (na kailangang kunin), ngunit paano natin mapipilit ang parser na agad na lumipat sa susunod katulad na fragment, sa kabila ng lahat ng posibleng tag at HTML attribute na maaaring ilagay sa mga puwang sa pagitan ng mga ito?

Pagkatapos mag-isip nang kaunti, nagpasya akong magpakilala ng ilang pattern ng serbisyo (%all_before) и (%all_after), na nagsisilbi sa malinaw na layunin ng pagtiyak na ang lahat ng maaaring nilalaman sa pinagmulang teksto ay nilaktawan bago ang anumang pattern (mask) na sumusunod sa kanila. Bukod dito, kung (%all_before) binalewala lang ang lahat ng mga arbitrary na inklusyon na ito, kung gayon (%all_after), sa kabaligtaran, pinapayagan silang maidagdag sa nais na fragment pagkatapos lumipat mula sa nakaraang fragment. Ito ay medyo simple, ngunit upang maipatupad ang konsepto na ito kailangan kong magsuklay muli sa mga mapagkukunan ng gorp upang gawin ang mga kinakailangang pagbabago upang hindi masira ang naipatupad na lohika. Sa huli, nagawa namin ito (bagaman kahit na ang pinaka, pinaka-una, kahit na napaka-buggy, ang pagpapatupad ng aking parser ay naisulat, at mas mabilis pa - sa loob ng ilang linggo). Mula ngayon, ang sistema ay nagkaroon ng isang tunay na unibersal na anyo - hindi bababa sa 12 taon pagkatapos ng mga unang pagtatangka na gawin itong gumana.

Siyempre, hindi ito ang katapusan ng ating mga pangarap. Maaari mo ring ganap na muling isulat ang gorp template parser sa C#, gamit ang alinman sa mga available na library para sa pagpapatupad ng isang libreng grammar. Sa tingin ko ang code ay dapat na makabuluhang pinasimple, at ito ay magbibigay-daan sa amin upang mapupuksa ang legacy sa anyo ng mga umiiral na mga mapagkukunan ng Java. Ngunit sa umiiral na uri ng makina, posible rin na gumawa ng iba't ibang mga kagiliw-giliw na bagay, kabilang ang isang pagtatangka na ipatupad ang mga meta-template na nabanggit ko na, hindi banggitin ang pag-parse ng iba't ibang data mula sa iba't ibang mga website (gayunpaman, hindi ko pinababayaan na ang mga umiiral nang dalubhasang software tool ay mas angkop para dito – wala pa akong angkop na karanasan sa paggamit ng mga ito).

Siyanga pala, ngayong tag-init ay nakatanggap na ako ng imbitasyon sa pamamagitan ng email mula sa isang kumpanyang gumagamit ng mga teknolohiya ng Salesforce (ang nag-develop ng orihinal na Gorp), pumasa sa isang panayam para sa kasunod na trabaho sa Riga. Sa kasamaang palad, sa ngayon ay hindi pa ako handa para sa mga naturang muling pag-deploy.

Kung ang materyal na ito ay pumukaw ng ilang interes, pagkatapos ay sa ikalawang bahagi ay susubukan kong ilarawan nang mas detalyado ang teknolohiya para sa pag-compile at kasunod na pag-parse ng mga template gamit ang halimbawa ng pagpapatupad na ginamit sa Salesforce Gorp (ang sarili kong mga karagdagan, maliban sa ilang mga function na salita na inilarawan na, halos walang pagbabago sa template syntax mismo, kaya halos lahat ng dokumentasyon para sa orihinal na system Gorp Angkop din para sa aking bersyon).

Pinagmulan: www.habr.com

Magdagdag ng komento