Příběh jednoho malého projektu dlouhého dvanáct let (o BIRMA.NET poprvé a upřímně řečeno z první ruky)

Zrod tohoto projektu lze považovat za drobnou myšlenku, která se ke mně zrodila někde na konci roku 2007 a která byla předurčena k tomu, aby svou finální podobu nalezla až o 12 let později (v tuto chvíli – samozřejmě, i když současná realizace podle pro autora je velmi uspokojivá).

Vše začalo tím, že jsem v rámci plnění svých tehdejších úředních povinností v knihovně upozornil na skutečnost, že proces vkládání dat z naskenovaného textu obsahových tabulek knižních (a hudebních) publikací do stávající databáze, lze zjevně výrazně zjednodušit a zautomatizovat s využitím vlastnosti uspořádanosti a opakovatelnosti všech údajů potřebných pro zadání, jako je jméno autora článku (pokud mluvíme o sbírce článků), název článek (nebo podnadpis uvedený v obsahu) a číslo stránky aktuální položky obsahu. Zpočátku jsem byl prakticky přesvědčen, že systém vhodný k provedení tohoto úkolu lze snadno najít na internetu. Když bylo překvapením, že jsem takový projekt nenašel, rozhodl jsem se ho zkusit realizovat sám.

Po poměrně krátké době začal fungovat první prototyp, který jsem okamžitě začal používat ve svých každodenních činnostech a současně jej ladil na všech příkladech, které se mi dostaly pod ruku. Naštěstí na mém obvyklém pracovišti, kde jsem v žádném případě nebyl programátorem, mi pak ještě prošly viditelné „prostoje“ ve své práci, během nichž jsem intenzivně ladil své duchovní dítě – v současné realitě téměř nemyslitelné, denní zprávy o práci vykonané během dne. Proces vylepšování programu trval celkem ne méně než asi rok, ale i poté se výsledek jen stěží dal označit za zcela úspěšný – zpočátku bylo stanoveno příliš mnoho různých konceptů, které nebyly zcela jasné pro implementaci: volitelné prvky, které mohou být přeskočen; dopředné prohlížení prvků (za účelem nahrazení předchozích prvků ve výsledcích vyhledávání); dokonce i náš vlastní pokus implementovat něco jako regulární výrazy (které mají jedinečnou syntaxi). Musím říci, že předtím jsem programování poněkud vzdal (asi na 8 let, ne-li déle), takže nová příležitost uplatnit své schopnosti na zajímavém a potřebném úkolu mě zcela zaujala. Není divu, že se výsledný zdrojový kód – při absenci jakýchkoliv jasných přístupů k jeho návrhu z mé strany – poměrně rychle stal nepředstavitelným mišmašem nesourodých kousků v jazyce C s některými prvky C++ a aspekty vizuálního programování (zpočátku to bylo rozhodnuto použít takový návrhový systém jako Borland C++ Builder – „téměř Delphi, ale v C“). To vše však nakonec přineslo své ovoce v automatizaci každodenních činností naší knihovny.

Zároveň jsem se rozhodl, pro každý případ, absolvovat kurzy pro školení profesionálních softwarových vývojářů. Nevím, jestli se tam vlastně dá naučit „programátorem“ od nuly, ale s přihlédnutím ke schopnostem, které jsem v té době už měl, jsem si trochu osvojil technologie, které byly v té době relevantnější, např. jako C#, Visual Studio pro vývoj pod .NET, stejně jako některé technologie související s Javou, HTML a SQL. Celé školení trvalo celkem dva roky a posloužilo jako výchozí bod pro další můj projekt, který se nakonec protáhl na několik let – ale to je téma na samostatnou publikaci. Zde by bylo vhodné pouze poznamenat, že jsem se pokusil přizpůsobit vývoj, který jsem již měl na popsaném projektu, k vytvoření plnohodnotné okenní aplikace v C# a WinForms, která implementuje potřebnou funkcionalitu, a použít ji jako základ pro připravovaný diplomový projekt.
Postupem času se mi tato myšlenka začala zdát hodná zaznít na takových výročních konferencích za účasti zástupců různých knihoven jako „LIBKOM“ a „CRIMEA“. Myšlenka ano, ale ne moje tehdejší realizace. Pak jsem také doufal, že to někdo přepíše pomocí kompetentnějších přístupů. Tak či onak jsem se rozhodl do roku 2013 napsat zprávu o své přípravné práci a poslat ji organizačnímu výboru konference se žádostí o grant na účast na konferenci. K mému mírnému překvapení byla moje žádost schválena a začal jsem projekt vylepšovat, abych ho připravil pro prezentaci na konferenci.

V té době již projekt dostal nové jméno BIRMA, získal různé další (ne tak plně implementované, ale spíše předpokládané) schopnosti - všechny podrobnosti najdete v mé zprávě.

Abych byl upřímný, bylo těžké nazvat BIRMU 2013 něčím úplným; Upřímně řečeno, bylo to velmi otřesné řemeslo vyrobené ve spěchu. Co se týče kódu, prakticky nedošlo k žádným speciálním inovacím, kromě dosti bezmocného pokusu o vytvoření jakési jednotné syntaxe pro parser, vzhledově připomínající formátovací jazyk IRBIS 64 (a vlastně i systém ISIS - se závorkami jako cyklické struktury; proč V té době jsem si myslel, že to vypadá docela dobře). Parser beznadějně narazil na tyto kruhy závorek příslušného typu (protože závorky plnily i další roli, totiž označovaly volitelné struktury při analýze, které lze přeskočit). Znovu odkazuji všechny, kteří se chtějí s tehdy těžko představitelnou, neopodstatněnou syntaxí BIRMA blíže seznámit, na svou tehdejší zprávu.

Obecně, kromě toho, že se potýkám s vlastním parserem, nemám ke kódu této verze co říci - kromě zpětné konverze existujících zdrojů do C++ při zachování některých typických rysů kódu .NET (abych byl upřímný, je to těžko pochopitelné, co mě přesně vedlo k tomu, abych vše přesunul zpět - pravděpodobně nějaký hloupý strach z utajení svých zdrojových kódů, jako by to bylo něco ekvivalentního tajnému receptu Coca-Coly).

Možná právě toto hloupé rozhodnutí spočívá i v obtížích při spárování výsledné DLL knihovny se stávajícím rozhraním podomácku vyrobené pracovní stanice pro zadávání dat do elektronického katalogu (ano, nezmínil jsem další důležitý fakt: od nynějška budou všechny kód „enginu“ BIRMA byl podle očekávání, je oddělen od části rozhraní a zabalen do příslušné knihovny DLL). Proč bylo pro tyto účely nutné napsat samostatnou pracovní stanici, která svým vzhledem a způsobem interakce s uživatelem bezostyšně kopírovala stejnou pracovní stanici „Katalogizátor“ systému IRBIS 64 - to je samostatná otázka. Stručně řečeno: dodalo to potřebnou pevnost mému tehdejšímu vývoji pro můj absolventský projekt (jinak samotný nestravitelný parser engine jaksi nestačil). Navíc jsem se poté setkal s určitými potížemi při implementaci rozhraní pracovní stanice Kataloger s mými vlastními moduly, implementovanými v C++ i C#, a přímým přístupem k mému enginu.

Obecně, kupodivu, to byl tento poněkud neohrabaný prototyp budoucího BIRMA.NET, který byl předurčen stát se mým „pracovním koněm“ na další čtyři roky. Nedá se říci, že bych se za tuto dobu alespoň nepokusil najít cesty k nové, ucelenější realizaci dlouholeté myšlenky. Mezi další novinky by již měly být vnořené cyklické sekvence, které mohly obsahovat volitelné prvky – takto jsem chtěl uvést do života myšlenku ​univerzálních šablon pro bibliografické popisy publikací a různé další zajímavosti. To vše však bylo v mé tehdejší praktické činnosti málo žádané a implementace, kterou jsem tehdy měl, byla pro zadávání obsahů zcela dostačující. Vektor rozvoje naší knihovny se navíc začal stále více odklánět směrem k digitalizaci muzejních archivů, zpravodajství a dalším pro mě málo zajímavým činnostem, což mě nakonec donutilo ji definitivně opustit a ustoupit těm, kteří by buď s tím vším spokojenější.

Paradoxně právě po těchto dramatických událostech jako by projekt BIRMA, který měl v té době již všechny charakteristické rysy typického dlouhodobého stavebního projektu, začal nabírat svůj dlouho očekávaný nový život! Měl jsem více volného času na plané myšlenky, začal jsem zase pročesávat World Wide Web a hledat něco podobného (naštěstí už jsem tušil, že to všechno budu hledat nejen někde, ale na GitHubu) a někde v At the začátkem letošního roku jsem konečně narazil na odpovídající produkt od známé společnosti Salesforce pod nevýznamným názvem Gorp. Sám o sobě uměl téměř vše, co jsem od takového parserového enginu potřeboval – totiž inteligentně izolovat jednotlivé fragmenty z libovolného, ​​ale jasně strukturovaného textu, a přitom mít pro koncového uživatele poměrně uživatelsky přívětivé rozhraní, včetně tak srozumitelných esencí, jako je např. vzor, ​​šablonu a výskyt a zároveň používat známou syntaxi regulárních výrazů, která se díky rozdělení do určených sémantických skupin pro parsování stává nesrovnatelně čitelnější.

Obecně jsem se rozhodl, že to je ten pravý Gorp (Zajímalo by mě, co tento název znamená? Možná nějaký „obecně orientovaný pravidelný analyzátor“?) – přesně to, co jsem dlouho hledal. Pravda, jeho okamžitá implementace pro vlastní potřebu měla takový problém, že tento engine vyžadoval příliš striktní dodržení strukturní posloupnosti zdrojového textu. Pro některé zprávy, jako jsou soubory protokolu (konkrétně je vývojáři umístili jako jasné příklady použití projektu), je to docela vhodné, ale pro stejné texty naskenovaných obsahů je to nepravděpodobné. Koneckonců, stejná stránka s obsahem může začínat slovy „Obsah“, „Obsah“ a dalšími předběžnými popisy, které nemusíme umístit do výsledků zamýšlené analýzy (a ručně je odříznout pokaždé je to také nepohodlné). Kromě toho mezi jednotlivými opakujícími se prvky, jako je jméno autora, název a číslo stránky, může stránka obsahovat určité množství odpadků (například kresby a jen náhodné znaky), které by bylo také hezké umět odříznout. Poslední aspekt však ještě nebyl tak výrazný, ale díky tomu prvnímu nemohla stávající implementace začít hledat potřebné struktury v textu od určitého místa, ale místo toho jej jednoduše zpracovávala od samého začátku, nenacházela specifikoval tam vzory a... ukončil mou práci. Očividně bylo potřeba nějaké vyladění, aby bylo mezi opakujícími se strukturami alespoň trochu prostoru, a to mě vrátilo do práce.

Dalším problémem bylo, že samotný projekt byl implementován v Javě, a pokud bych do budoucna plánoval implementovat nějaký způsob propojení této technologie se známými aplikacemi pro zadávání dat do existujících databází (jako je Irbisův „Katalog“), pak alespoň udělejte to v C# a .NET. Ne, že by Java sama o sobě byla špatný jazyk – kdysi jsem ji dokonce použil k implementaci zajímavé okenní aplikace, která implementovala funkcionalitu domácí programovatelné kalkulačky (v rámci projektu kurzu). A pokud jde o syntaxi, je velmi podobný stejnému C-sharp. No, to je jen plus: tím snazší pro mě bude dokončit existující projekt. Nechtěl jsem se však znovu vrhat do tohoto poněkud neobvyklého světa okenních (nebo spíše desktopových) Java technologií - ostatně jazyk sám nebyl pro takové použití „šitý na míru“ a vůbec jsem netoužil po opakování předchozí zkušenost. Možná je to právě tím, že C# ve spojení s WinForms má mnohem blíže k Delphi, se kterým mnozí z nás kdysi začínali. Potřebné řešení se naštěstí našlo celkem rychle – v podobě projektu IKVM.NET, což usnadňuje překlad existujících programů Java do spravovaného kódu .NET. Je pravda, že samotný projekt byl v té době již autory opuštěn, ale jeho poslední implementace mi umožnila poměrně úspěšně provést potřebné akce pro zdrojové texty Gorp.

Provedl jsem tedy všechny potřebné změny a vše sestavil do DLL příslušného typu, kterou by snadno „sebral“ jakýkoli projekt pro .NET Framework vytvořený ve Visual Studiu. Mezitím jsem vytvořil další vrstvu pro pohodlnou prezentaci vrácených výsledků Gorp, ve formě odpovídajících datových struktur, které by bylo vhodné zpracovávat v tabulkovém zobrazení (za základ budou brát řádky i sloupce; jak slovníkové klíče, tak číselné indexy). No a samotné potřebné utility pro zpracování a zobrazení výsledků byly napsány celkem rychle.

Také proces adaptace šablon pro nový engine, aby se naučil analyzovat existující vzorky naskenovaných textů obsahu, nezpůsobil žádné zvláštní komplikace. Ve skutečnosti jsem ani nemusel odkazovat na své předchozí šablony: jednoduše jsem vytvořil všechny potřebné šablony od začátku. Pokud navíc šablony navržené pro práci s předchozí verzí systému nastavily poměrně úzký rámec pro texty, které by bylo možné s jejich pomocí správně analyzovat, nový engine již umožnil vyvinout poměrně univerzální šablony vhodné pro několik typů značek na jednou. Dokonce jsem se pokusil napsat jakousi komplexní šablonu pro libovolný text obsahu, i když samozřejmě i se všemi novými možnostmi, které se mi otevírají, včetně zejména omezené schopnosti implementovat stejné vnořené opakující se sekvence ( jako např. příjmení a iniciály více autorů za sebou), to se ukázalo jako utopie.

Možná bude v budoucnu možné implementovat určitý koncept meta-šablon, které budou schopny kontrolovat zdrojový text, zda vyhovuje několika dostupným šablonám najednou, a poté v souladu se získanými výsledky vybrat nejvhodnější pomocí nějakého inteligentního algoritmu. Ale teď mě víc znepokojovala jiná otázka. Jako parser Gorp, přes veškerou svou všestrannost a modifikace, které jsem provedl, stále nebyl ze své podstaty schopen udělat jednu zdánlivě jednoduchou věc, kterou můj vlastní analyzátor dokázal od první verze. Totiž: měl možnost na správném místě najít a extrahovat ze zdrojového textu všechny fragmenty, které odpovídají masce uvedené v použité šabloně, přičemž ho vůbec nezajímalo, co daný text v mezerách mezi těmito fragmenty obsahuje. Nový engine jsem zatím jen mírně vylepšil a umožnil mu vyhledávat všechna možná nová opakování dané sekvence takových masek z aktuální pozice, ponechávám možnost přítomnosti v textu sad libovolných znaků, které byly zcela nezohledněný při analýze, uzavřený mezi detekované opakující se struktury. To však neumožnilo nastavit další masku bez ohledu na výsledky hledání předchozího fragmentu pomocí odpovídající masky: přísnost popisované struktury textu stále neponechávala prostor pro svévolné vkládání nepravidelných znaků.

A pokud se u příkladů obsahů, na které jsem narazil, tento problém ještě nezdál tak závažný, pak při pokusu o aplikaci nového mechanismu analýzy na podobnou úlohu analýzy obsahu webové stránky (tj. stejné analýzy) omezení jsou zde, objevila se se vší svou samozřejmostí. Koneckonců, je docela snadné nastavit potřebné masky pro fragmenty webových značek, mezi nimiž by se měla nacházet data, která hledáme (která je třeba extrahovat), ale jak donutit analyzátor okamžitě přejít na další podobný fragment, navzdory všem možným značkám a atributům HTML, které lze umístit do mezer mezi nimi?

Po krátkém přemýšlení jsem se rozhodl představit pár vzorů služeb (%all_before) и (%all_after), sloužící zjevnému účelu zajistit, že vše, co může být obsaženo ve zdrojovém textu, bude přeskočeno před jakýmkoliv vzorem (maskou), který za nimi následuje. Navíc pokud (%all_before) jednoduše ignoroval všechny tyto svévolné inkluze (%all_after), naopak umožnil jejich přidání k požadovanému fragmentu po přesunutí z předchozího fragmentu. Zní to celkem jednoduše, ale pro implementaci tohoto konceptu jsem musel znovu pročesat gorp zdroje, abych provedl potřebné úpravy, abych neporušil již implementovanou logiku. Nakonec jsme to zvládli (i když i úplně první, i když velmi zabugovaná implementace mého parseru byla napsána a ještě rychleji - za pár týdnů). Od nynějška nabyl systém skutečně univerzální podoby – ne méně než 12 let po prvních pokusech o jeho zprovoznění.

Tím naše sny samozřejmě nekončí. Analyzátor šablony gorp můžete také zcela přepsat v C# pomocí kterékoli z dostupných knihoven pro implementaci bezplatné gramatiky. Myslím, že kód by se měl výrazně zjednodušit a to nám umožní zbavit se dědictví v podobě existujících zdrojů Java. Se stávajícím typem enginu se ale také celkem dají dělat různé zajímavé věci, včetně pokusu o implementaci již zmíněných meta-šablon, nemluvě o parsování různých dat z různých webů (nevylučuji však že stávající specializované softwarové nástroje jsou k tomu vhodnější – jen jsem ještě neměl patřičné zkušenosti s jejich používáním).

Mimochodem, letos v létě jsem již obdržel e-mailem pozvánku od společnosti, která používá technologie Salesforce (vývojář originálu Gorp), absolvovat pohovor pro další práci v Rize. Bohužel v tuto chvíli nejsem na takové přesuny připraven.

Pokud tento materiál vzbudí určitý zájem, pak se v druhé části pokusím podrobněji popsat technologii kompilace a následného parsování šablon na příkladu implementace použité v Salesforce Gorp (moje vlastní doplňky, s výjimkou několika již popsaných funkčních slov, nezpůsobují prakticky žádné změny v samotné syntaxi šablony, takže téměř veškerá dokumentace k původnímu systému Gorp Vhodné i pro mou verzi).

Zdroj: www.habr.com

Přidat komentář