Tarina yhdestä pienestä kaksitoista vuotta kestävästä projektista (tietoa BIRMA.NETistä ensimmäistä kertaa ja suoraan sanottuna omakohtaisesti)

Tämän projektin syntyä voidaan pitää pienenä, jossain vuoden 2007 lopulla syntyneenä ideana, jonka oli määrä löytää lopullinen muotonsa vasta 12 vuotta myöhemmin (tällä hetkellä – toki vaikka nykyinen toteutus, kirjoittajalle, on erittäin tyydyttävä).

Kaikki alkoi siitä, että kirjastossa silloisten virkatehtäviäni suorittaessani kiinnitin huomiota siihen, että kirja- (ja musiikki-) julkaisujen sisällysluetteloiden skannatun tekstin tietojen syöttäminen olemassa olevaan tietokantaan, ilmeisesti voidaan merkittävästi yksinkertaistaa ja automatisoida hyödyntäen kaikkien syöttämiseen tarvittavien tietojen, kuten artikkelin kirjoittajan nimen (jos puhumme artikkelikokoelmasta), artikkelin otsikon, järjestystä ja toistettavuutta (tai sisällysluettelossa näkyvä alaotsikko) ja nykyisen sisällysluettelokohteen sivunumero. Aluksi olin käytännössä vakuuttunut siitä, että tämän tehtävän suorittamiseen sopiva järjestelmä löytyy helposti Internetistä. Kun yllätys aiheutti se, että en löytänyt tällaista projektia, päätin yrittää toteuttaa sen itse.

Melko lyhyen ajan kuluttua alkoi toimimaan ensimmäinen prototyyppi, jota aloin heti käyttämään päivittäisessä toiminnassani, samalla kun debugasin sitä kaikista käsiini tulleista esimerkeistä. Onneksi tavallisella työpaikallani, jossa en missään nimessä ollut ohjelmoija, pääsin sitten silti eroon työssäni näkyvistä "seisokeista", joiden aikana tein intensiivisesti aivolapseni virheenkorjausta - mikä on lähes mahdotonta ajatella nykytodellisuudessa. päivittäiset raportit päivän aikana tehdystä työstä. Ohjelman hiominen kesti yhteensä peräti noin vuoden, mutta sen jälkeenkin tulosta tuskin voitu kutsua täysin onnistuneeksi - alun perin laadittiin liikaa erilaisia ​​konsepteja, jotka eivät olleet täysin selkeitä toteutukseen: valinnaisia ​​elementtejä, jotka ohitetaan; elementtien katselu eteenpäin (aihempien elementtien korvaamiseksi hakutuloksissa); jopa oma yritys toteuttaa jotain säännöllisten lausekkeiden kaltaista (jolla on ainutlaatuinen syntaksi). Täytyy sanoa, että ennen tätä olin jossain määrin luopunut ohjelmoinnista (noin 8 vuodeksi, ellei enemmänkin), joten uusi mahdollisuus soveltaa taitojani mielenkiintoiseen ja tarpeelliseen tehtävään vangitsi huomioni täysin. Ei ole yllättävää, että tuloksena olevasta lähdekoodista - ilman selkeitä lähestymistapoja sen suunnitteluun - tuli melko nopeasti käsittämätön sekoitus erilaisia ​​​​osia C-kielessä joidenkin C++-elementtien ja visuaalisen ohjelmoinnin osien kanssa (alun perin se päätettiin käyttää sellaista suunnittelujärjestelmää kuin Borland C++ Builder - "melkein Delphi, mutta C"). Kaikki tämä kuitenkin kantoi hedelmää kirjastomme päivittäisen toiminnan automatisoinnissa.

Samalla päätin varmuuden vuoksi käydä kursseilla, joilla koulutetaan ammattimaisia ​​ohjelmistokehittäjiä. En tiedä, onko siellä todella mahdollista oppia "ohjelmoijaksi" tyhjästä, mutta kun otetaan huomioon jo tuolloin omaamani taidot, pystyin jonkin verran hallitsemaan siihen mennessä merkityksellisempiä teknologioita, kuten kuten C#, Visual Studio .NET-kehitykseen, sekä joitain Java-, HTML- ja SQL-tekniikoita. Koko koulutus kesti yhteensä kaksi vuotta ja toimi lähtökohtana toiselle projektilleni, joka lopulta ulottui useille vuosille - mutta tämä on erillisen julkaisun aihe. Tässä olisi vain paikallaan todeta, että yritin mukauttaa jo aiemmin tehtyjä kehityshankkeita kuvattuun projektiin luodakseni C#- ja WinForms-kielellä täysimittainen ikkunasovellus, joka toteuttaa tarvittavat toiminnot ja käyttää sitä pohjana tuleva diplomityö.
Ajan myötä tämä ajatus alkoi minusta tuntua arvoiselta tulla esiin sellaisissa vuosittaisissa konferensseissa, joihin osallistui eri kirjastojen, kuten "LIBKOM" ja "CRIMEA" edustajia. Idea kyllä, mutta ei minun tuolloin toteutukseni. Sitten toivoin myös, että joku kirjoittaisi sen uudelleen käyttämällä pätevämpiä lähestymistapoja. Tavalla tai toisella päätin vuoteen 2013 mennessä kirjoittaa raportin esityöstäni ja lähettää sen konferenssin järjestelytoimikunnalle apurahahakemuksen kera osallistua konferenssiin. Hieman yllätyksekseni hakemukseni hyväksyttiin, ja aloin tehdä joitain parannuksia projektiin valmistellakseni sen esittelyä varten konferenssissa.

Siihen mennessä projekti oli jo saanut uuden nimen BIRMA, hankkinut useita lisäominaisuuksia (ei niinkään täysin toteutettuja, vaan pikemminkin oletettuja) - kaikki yksityiskohdat löytyvät raportistani.

Rehellisesti sanottuna BIRMA 2013:a oli vaikea kutsua täydelliseksi; Rehellisesti sanottuna se oli erittäin hakkeroitu käsityö, joka tehtiin kiireessä. Koodin suhteen ei käytännössä ollut mitään erityisiä innovaatioita, lukuun ottamatta melko avutonta yritystä luoda jäsentimelle jonkinlainen yhtenäinen syntaksi, joka muistuttaa ulkonäöltään IRBIS 64 -muotoilukieltä (ja itse asiassa myös ISIS-järjestelmää - suluilla syklisinä rakenteina; miksi Tuolloin ajattelin, että se näytti aika siistiltä). Jäsentäjä törmäsi toivottomasti näihin sopivan tyyppisiin sulkurenkaisiin (koska suluilla oli myös toinen rooli, nimittäin ne merkitsivät jäsentämisen aikana valinnaisia ​​rakenteita, jotka voidaan ohittaa). Vetoan jälleen kaikkiin, jotka haluavat tutustua BIRMA:n silloiseen vaikeasti kuviteltaviin, perusteettomiin syntaksiin tarkemmin tuolloiseen raporttiin.

Yleisesti ottaen, paitsi kamppailun oman jäsentimeni kanssa, minulla ei ole muuta sanottavaa tämän version koodista - paitsi olemassa olevien lähteiden käänteinen muuntaminen C++:ksi säilyttäen samalla joitain tyypillisiä .NET-koodin ominaisuuksia (rehellisesti sanottuna se on vaikea ymmärtää , mikä tarkalleen sai minut siirtämään kaiken takaisin - luultavasti tyhmä pelko lähdekoodini salaamisesta, ikään kuin se olisi jotain vastaavaa kuin Coca-Colan salainen resepti).

Ehkä tämä tyhmä päätös on syynä myös vaikeuksiin yhdistää tuloksena oleva DLL-kirjasto kotitekoisen työaseman olemassa olevaan käyttöliittymään tietojen syöttämiseksi sähköiseen luetteloon (kyllä, en maininnut toista tärkeää tosiasiaa: tästä lähtien kaikki BIRMA "moottorin" koodi oli odotetusti, se on erotettu käyttöliittymäosasta ja pakattu sopivaan DLL:ään). Miksi näihin tarkoituksiin piti kirjoittaa erillinen työasema, joka joka tapauksessa ulkonäöllään ja käyttäjän kanssa vuorovaikutustavallaan kopioi häpeämättömästi saman IRBIS 64 -järjestelmän työaseman "Catalogizer" - tämä on erillinen kysymys. Lyhyesti sanottuna: se antoi tarvittavan lujuuden silloiselle kehitykselleni valmistujaistyötäni varten (muuten sulamaton jäsennysmoottori ei yksin jotenkin riittänyt). Lisäksi kohtasin sitten joitain vaikeuksia Cataloger-työaseman rajapinnan toteuttamisessa omilla moduuleillani, jotka on toteutettu sekä C++:ssa että C#:ssa, ja päästä suoraan koneeseeni.

Yleisesti ottaen, kummallista kyllä, juuri tästä tulevan BIRMA.NETin melko kömpelöstä prototyypistä oli määrä tulla "työhevoseni" seuraavien neljän vuoden ajan. Ei voida sanoa, että en tänä aikana ainakaan yrittänyt löytää tapoja uudelle, täydellisemmälle toteuttamiselle pitkäaikaiselle idealle. Muiden innovaatioiden joukossa olisi jo pitänyt olla sisäkkäisiä syklisiä sarjoja, jotka olisivat voineet sisältää valinnaisia ​​elementtejä - näin aioin herättää henkiin ajatuksen universaaleista malleista julkaisujen bibliografisiin kuvauksiin ja moniin muihin mielenkiintoisiin asioihin. Silloisessa käytännön toiminnassani tälle kaikelle oli kuitenkin vähän kysyntää, ja tuolloinen toteutus oli varsin riittävä sisällysluetteloihin syöttämiseen. Lisäksi kirjastomme kehitysvektori alkoi poiketa yhä enemmän museoarkistojen digitalisoimiseen, raportointiin ja muihin minua vähän kiinnostaviin toimintoihin, mikä lopulta pakotti minut lopulta jättämään sen ja väistymään niille, jotka ole tyytyväisempi tähän kaikkeen.

Paradoksaalista kyllä, juuri näiden dramaattisten tapahtumien jälkeen BIRMA-projekti, jolla oli jo tuolloin kaikki tyypillisen pitkäaikaisen rakennusprojektin ominaispiirteet, näytti alkavan saada kauan odotettua uutta elämäänsä! Minulla oli enemmän vapaa-aikaa jouto-ajatuksille, aloin jälleen kampaamaan World Wide Webiä etsimään jotain vastaavaa (onneksi nyt osasin jo arvata, että etsin kaikkea tätä ei vain mistä tahansa, vaan GitHubista), ja jostain At the tämän vuoden alussa löysin vihdoin vastaavan tuotteen tunnetulta Salesforce-yritykseltä merkityksettömällä nimellä Gorp. Se pystyi yksinään tekemään melkein kaiken, mitä tarvitsin tällaiselta jäsennysmoottorilta - eli eristää älykkäästi yksittäisiä fragmentteja mielivaltaisesta, mutta selkeästi jäsennellystä tekstistä, samalla kun sillä on loppukäyttäjälle melko käyttäjäystävällinen käyttöliittymä, mukaan lukien sellaiset ymmärrettävät olemukset, mallia, mallia ja esiintymää ja samalla käyttämällä tuttua säännöllisten lausekkeiden syntaksia, josta tulee verrattoman luettavampi jäsentämistä varten määrättyihin semanttisiin ryhmiin jakamisen ansiosta.

Yleisesti päätin, että tämä on se Gorp (Ihmettelen, mitä tämä nimi tarkoittaa? Ehkä jonkinlainen "yleisesti suuntautunut tavallinen jäsentäjä"?) - juuri sitä, mitä olen etsinyt pitkään. Totta, sen välittömässä toteutuksessa omiin tarpeisiini oli sellainen ongelma, että tämä moottori vaati liian tiukkaa lähdetekstin rakenteellisen järjestyksen noudattamista. Joillekin raporteille, kuten lokitiedostoille (eli kehittäjät asettivat ne selkeiksi esimerkkeiksi projektin käytöstä), tämä on varsin sopivaa, mutta samoille skannattujen sisällysluetteloiden teksteille se on epätodennäköistä. Loppujen lopuksi sama sivu, jossa on sisällysluettelo, voi alkaa sanoilla "Sisällys", "Sisällys" ja muilla alustavilla kuvauksilla, joita meidän ei tarvitse sijoittaa aiotun analyysin tuloksiin (ja leikkaamalla ne pois käsin). joka kerta on myös epämukavaa). Lisäksi yksittäisten toistuvien elementtien, kuten tekijän nimen, otsikon ja sivunumeron, välissä sivu voi sisältää tietyn määrän roskaa (esimerkiksi piirroksia ja vain satunnaisia ​​merkkejä), joita olisi myös mukava pystyä katkaista. Viimeinen aspekti ei kuitenkaan ollut vielä niin merkittävä, mutta ensimmäisen takia olemassa oleva toteutus ei voinut alkaa etsimään tekstistä tarvittavia rakenteita tietystä paikasta, vaan yksinkertaisesti prosessoi sitä alusta alkaen, ei löytänyt määritellyt kuviot siellä ja... lopetin työni. Ilmeisesti tarvittiin hieman säätämistä, jotta toistuvien rakenteiden väliin jäisi ainakin tilaa, ja se sai minut takaisin töihin.

Toinen ongelma oli, että itse projekti toteutettiin Javalla, ja jos aioin tulevaisuudessa toteuttaa jonkin keinon liittää tämä tekniikka tuttuihin sovelluksiin tietojen syöttämiseksi olemassa oleviin tietokantoihin (kuten Irbiksen "Cataloguer"), niin ainakin ainakin Tee tämä C#:ssa ja .NET:ssä. Ei se tarkoita, että Java itsessään olisi huono kieli – käytin sitä joskus jopa kotimaisen ohjelmoitavan laskimen toiminnallisuuden toteuttavan mielenkiintoisen ikkunasovelluksen toteuttamiseen (osa kurssiprojektia). Ja syntaksilta se on hyvin samanlainen kuin sama C-sharp. No, tämä on vain plussaa: sitä helpompi minun on viimeistellä olemassa oleva projekti. En kuitenkaan halunnut sukeltaa uudelleen tähän melko epätavalliseen ikkuna- (tai pikemminkin työpöytä) Java-tekniikoiden maailmaan - itse kieli ei loppujen lopuksi ollut "räätälöity" sellaiseen käyttöön, enkä halunnut ollenkaan toistoa. aikaisempi kokemus. Ehkä se johtuu juuri siitä, että C# yhdessä WinFormsin kanssa on paljon lähempänä Delphiä, jonka kanssa monet meistä kerran aloittivat. Onneksi tarvittava ratkaisu löytyi melko nopeasti - projektin muodossa IKVM.NET, jonka avulla on helppo kääntää olemassa olevat Java-ohjelmat hallituksi .NET-koodiksi. Totta, itse projekti oli jo tuolloin tekijöiden hylännyt, mutta sen viimeisin toteutus antoi minulle mahdollisuuden suorittaa melko menestyksekkäästi tarvittavat toimenpiteet lähdetekstien suhteen Gorp.

Joten tein kaikki tarvittavat muutokset ja kokosin ne sopivan tyyppiseksi DLL:ksi, jonka kaikki Visual Studiossa luodut .NET Framework -projektit saattoivat helposti "poimia". Sillä välin loin toisen kerroksen palautettujen tulosten kätevää esittelyä varten Gorp, vastaavien tietorakenteiden muodossa, joita olisi kätevä käsitellä taulukkonäkymässä (perustana sekä rivit että sarakkeet; sekä sanakirjaavaimet että numeeriset indeksit). No, itse tarvittavat apuohjelmat tulosten käsittelyyn ja näyttämiseen kirjoitettiin melko nopeasti.

Myöskään uuden moottorin mallien mukauttamisprosessi, jotta se opetetaan jäsentämään olemassa olevia näytteitä sisällysluetteloiden skannatuista teksteistä, ei aiheuttanut erityisiä ongelmia. Itse asiassa minun ei tarvinnut edes viitata aikaisempiin malleihini ollenkaan: tein vain kaikki tarvittavat mallit tyhjästä. Lisäksi, jos järjestelmän aiemman version kanssa toimimaan suunnitellut mallit asettavat melko kapeat puitteet teksteille, jotka voitiin jäsentää niiden avulla oikein, uusi moottori mahdollisti jo melko yleismaailmallisten mallien kehittämisen, joka soveltui useisiin eri merkintöihin. kerran. Yritin jopa kirjoittaa jonkinlaisen kattavan mallin mihin tahansa mielivaltaiseen sisällysluettelotekstiin, vaikka tietysti vaikka kaikki uudet mahdollisuudet avautuivat minulle, mukaan lukien erityisesti rajallinen kyky toteuttaa samoja sisäkkäisiä toistuvia sekvenssejä ( kuten esimerkiksi useiden kirjoittajien sukunimet ja nimikirjaimet peräkkäin), tämä osoittautui utopiaksi.

Ehkä tulevaisuudessa on mahdollista toteuttaa tietty metamallien konsepti, joka pystyy tarkistamaan lähdetekstin yhteensopivuuden useiden käytettävissä olevien mallien kanssa kerralla ja valitse sitten saatujen tulosten mukaisesti sopivin, käyttämällä jotain älykästä algoritmia. Mutta nyt minua huolestutti enemmän toinen kysymys. Jäsentimen kaltainen Gorp, kaikesta monipuolisuudestaan ​​ja tekemistäni muutoksista huolimatta se oli silti luonnostaan ​​kykenemätön tekemään yhtä yksinkertaiselta vaikuttavaa asiaa, jonka itse kirjoittamani jäsentäjä pystyi tekemään heti ensimmäisestä versiosta lähtien. Nimittäin: hänellä oli kyky löytää ja poimia lähdetekstistä kaikki oikeassa paikassa käytetyssä mallissa määritettyä maskia vastaavat fragmentit, eikä hän ollut lainkaan kiinnostunut siitä, mitä annettu teksti sisältää näiden fragmenttien välissä. Toistaiseksi olen vain hieman parantanut uutta moottoria, jolloin se voi etsiä tällaisten maskien tietyn sarjan kaikkia mahdollisia uusia toistoja nykyisestä paikasta, jättäen mahdollisuuden tekstiin mielivaltaisten merkkijoukkojen esiintymiselle, jotka olivat täysin jätetty huomioimatta jäsennykseen, suljettuna havaittujen toistuvien rakenteiden väliin. Tämä ei kuitenkaan mahdollistanut seuraavan maskin asettamista huolimatta edellisen fragmentin etsinnän tuloksista vastaavalla maskilla: kuvatun tekstirakenteen tiukkaus ei silti jättänyt tilaa epäsäännöllisten merkkien mielivaltaisille sisällyttämiselle.

Ja jos kohtaamieni sisällysluetteloesimerkkien kohdalla tämä ongelma ei vielä vaikuttanut niin vakavalta, niin kun yritetään soveltaa uutta jäsennysmekanismia samanlaiseen verkkosivuston sisällön jäsentämiseen (eli samaan jäsennykseen), sen rajoitukset ovat tässä, ne ilmestyivät kaikella ilmeisyydellään. Loppujen lopuksi on melko helppoa asettaa tarvittavat maskit verkkomerkintöjen fragmenteille, joiden väliin etsimämme tiedot (joka on purettava) pitäisi sijaita, mutta kuinka voimme pakottaa jäsentimen siirtymään välittömästi seuraavaan samanlainen fragmentti huolimatta kaikista mahdollisista tunnisteista ja HTML-attribuuteista, jotka voidaan sijoittaa niiden väliin?

Pienen pohdinnan jälkeen päätin ottaa käyttöön pari palvelumallia (%kaikki_ennen) и (%all_after), joiden ilmeinen tarkoitus on varmistaa, että kaikki lähdetekstin sisältämä ohitetaan ennen niitä seuraavaa kuviota (naamiota). Lisäksi jos (%kaikki_ennen) yksinkertaisesti jättänyt huomioimatta kaikki nämä mielivaltaiset sisällytykset (%all_after)päinvastoin, mahdollisti niiden lisäämisen haluttuun fragmenttiin siirryttyään edellisestä fragmentista. Kuulostaa melko yksinkertaiselta, mutta tämän konseptin toteuttamiseksi jouduin kampaamaan gorp-lähteitä uudelleen läpi tarvittavien muutosten tekemiseksi, jotta en rikkoisi jo toteutettua logiikkaa. Lopulta onnistuimme tässä (vaikka jopa aivan ensimmäinen, vaikkakin erittäin buginen jäsentimeni toteutus kirjoitettiin, ja vielä nopeammin - parissa viikossa). Tästä lähtien järjestelmä sai todella yleismaailmallisen muodon - vähintään 12 vuotta sen jälkeen, kun ensimmäiset yritykset saada se toimimaan.

Tämä ei tietenkään ole unelmiemme loppu. Voit myös kirjoittaa gorp-mallin jäsentimen kokonaan uudelleen C#:ssa käyttämällä mitä tahansa saatavilla olevaa kirjastoa ilmaisen kieliopin toteuttamiseen. Mielestäni koodia pitäisi yksinkertaistaa huomattavasti, ja tämä antaa meille mahdollisuuden päästä eroon perinnöstä olemassa olevien Java-lähteiden muodossa. Mutta olemassa olevan moottorityypin avulla on myös täysin mahdollista tehdä erilaisia ​​mielenkiintoisia asioita, mukaan lukien yritys toteuttaa jo mainitsemani metamallit, puhumattakaan erilaisten tietojen jäsentämisestä eri verkkosivustoilta (en kuitenkaan sulje pois että olemassa olevat erikoisohjelmistotyökalut sopivat tähän paremmin – minulla ei vain ole vielä ollut asianmukaista kokemusta niiden käytöstä).

Muuten, tänä kesänä sain jo sähköpostikutsun Salesforce-teknologioita käyttävältä yritykseltä (alkuperäisen Gorp), läpäise haastattelu myöhempää työtä varten Riiassa. Valitettavasti en tällä hetkellä ole valmis sellaisiin uudelleenjärjestelyihin.

Jos tämä materiaali herättää kiinnostusta, yritän toisessa osassa kuvata yksityiskohtaisemmin mallien kokoamisen ja sen jälkeen jäsentämisen tekniikkaa Salesforcessa käytetyn toteutuksen esimerkin avulla. Gorp (Omat lisäykseni muutamaa jo kuvattua funktiosanaa lukuun ottamatta eivät tee käytännössä mitään muutoksia itse mallin syntaksiin, joten lähes kaikki alkuperäisen järjestelmän dokumentaatio Gorp Sopii myös minun versioon).

Lähde: will.com

Lisää kommentti