داستان یک پروژه کوچک به مدت دوازده سال (درباره BIRMA.NET برای اولین بار و رک و پوست کنده دست اول)

تولد این پروژه را می توان ایده کوچکی دانست که در اواخر سال 2007 به ذهنم خطور کرد، که قرار بود تنها 12 سال بعد شکل نهایی خود را پیدا کند (در این برهه از زمان - البته، اگرچه اجرای فعلی، مطابق با برای نویسنده، بسیار رضایت بخش است).

همه چیز از آنجا شروع شد که در فرآیند انجام وظایف رسمی آن زمان خود در کتابخانه، توجه من را به این واقعیت جلب کردم که فرآیند وارد کردن داده ها از متن اسکن شده فهرست مطالب انتشارات کتاب (و موسیقی) به پایگاه داده موجود، ظاهراً می توان با بهره گیری از خاصیت نظم و تکرارپذیری کلیه داده های مورد نیاز برای ورودی، مانند نام نویسنده مقاله (اگر در مورد مجموعه مقالات صحبت می کنیم)، به طور قابل توجهی ساده و خودکار شود. مقاله (یا زیرنویس منعکس شده در فهرست مطالب) و شماره صفحه آیتم فهرست مطالب فعلی. در ابتدا، من عملاً متقاعد شدم که یک سیستم مناسب برای انجام این کار را می توان به راحتی در اینترنت پیدا کرد. وقتی تعجبی به وجود آمد که من نتوانستم چنین پروژه ای را پیدا کنم، تصمیم گرفتم سعی کنم آن را به تنهایی اجرا کنم.

پس از مدت کوتاهی، اولین نمونه اولیه شروع به کار کرد، که من بلافاصله شروع به استفاده از آن در فعالیت های روزانه خود کردم و همزمان آن را روی تمام نمونه هایی که به دستم رسید اشکال زدایی کردم. خوشبختانه، در محل کار همیشگی‌ام، جایی که به هیچ وجه برنامه‌نویس نبودم، هنوز از «وقوع» قابل مشاهده در کارم خلاص شدم، که در طی آن به شدت در حال رفع اشکال ذهنم بودم - چیزی تقریباً غیرقابل تصور در واقعیت‌های کنونی، که نشان می‌دهد گزارش روزانه از کارهای انجام شده در طول روز. روند صیقل دادن برنامه در مجموع کمتر از یک سال طول کشید، اما حتی پس از آن نیز به سختی می توان نتیجه را کاملاً موفق نامید - در ابتدا مفاهیم بسیار متفاوتی ارائه شد که برای اجرا کاملاً مشخص نبود: عناصر اختیاری که می توانند نادیده گرفته شود؛ مشاهده رو به جلو عناصر (به منظور جایگزینی عناصر قبلی در نتایج جستجو)؛ حتی تلاش خودمان برای پیاده سازی چیزی مانند عبارات منظم (که یک نحو منحصر به فرد دارد). باید بگویم که قبل از این تا حدودی برنامه نویسی را رها کرده بودم (حدود 8 سال، اگر نه بیشتر)، بنابراین فرصت جدید برای به کار بردن مهارت هایم در یک کار جالب و ضروری کاملاً توجه من را به خود جلب کرد. تعجب آور نیست که کد منبع حاصل - در غیاب هیچ رویکرد روشنی برای طراحی آن از طرف من - به سرعت به ترکیب غیرقابل تصوری از قطعات متفاوت در زبان C با برخی از عناصر C++ و جنبه های برنامه نویسی بصری تبدیل شد (در ابتدا این تصمیم گرفته شد از چنین سیستم طراحی مانند Borland C ++ Builder - "تقریبا دلفی، اما در C" استفاده شود). با این حال، همه اینها در نهایت در خودکارسازی فعالیت های روزانه کتابخانه ما به ثمر نشست.

در همان زمان، تصمیم گرفتم، فقط در صورت لزوم، دوره هایی را برای آموزش توسعه دهندگان نرم افزار حرفه ای بگذرانم. نمی‌دانم واقعاً می‌توان «برنامه‌نویس بودن» را از ابتدا یاد گرفت، اما با در نظر گرفتن مهارت‌هایی که قبلاً در آن زمان داشتم، توانستم تا حدودی بر فناوری‌هایی مسلط شوم که در آن زمان مرتبط‌تر بودند، مانند به عنوان C#، ویژوال استودیو برای توسعه تحت NET، و همچنین برخی از فناوری های مرتبط با جاوا، HTML و SQL. کل آموزش در مجموع دو سال طول کشید و به عنوان نقطه شروع پروژه دیگری از من بود که در نهایت چندین سال به طول انجامید - اما این موضوع برای یک انتشار جداگانه است. در اینجا فقط مناسب است که توجه داشته باشیم که من سعی کردم پیشرفت هایی را که قبلاً در پروژه شرح داده شده داشتم، برای ایجاد یک برنامه پنجره تمام عیار در C# و WinForms که عملکردهای لازم را اجرا می کند، تطبیق دهم و از آن به عنوان مبنایی برای پروژه دیپلم آینده
با گذشت زمان، این ایده به نظر من شایسته بیان در کنفرانس های سالانه با مشارکت نمایندگان کتابخانه های مختلف مانند "LIBKOM" و "CRIMEA" بود. این ایده، بله، اما نه اجرای آن در آن زمان. سپس من همچنین امیدوار بودم که کسی آن را با استفاده از رویکردهای شایسته تر بازنویسی کند. به هر حال، تا سال 2013 تصمیم گرفتم گزارشی از کارهای مقدماتی خود بنویسم و ​​آن را با درخواست کمک هزینه برای شرکت در کنفرانس به کمیته سازماندهی کنفرانس ارسال کنم. با کمال تعجب، درخواست من مورد تایید قرار گرفت و من شروع به ایجاد برخی بهبودها در پروژه کردم تا آن را برای ارائه در کنفرانس آماده کنم.

در آن زمان ، این پروژه قبلاً نام جدیدی BIRMA را دریافت کرده بود ، قابلیت های مختلف اضافی (نه چندان کاملاً اجرا شده ، بلکه فرضی) را به دست آورده بود - تمام جزئیات را می توان در گزارش من یافت.

صادقانه بگویم، دشوار بود که BIRMA 2013 را چیزی کامل بدانیم. صادقانه بگویم، این یک کاردستی بسیار هک بود که با عجله ساخته شد. از نظر کد، عملاً هیچ نوآوری خاصی وجود نداشت، به جز تلاشی نسبتاً درمانده برای ایجاد نوعی نحو یکپارچه برای تجزیه کننده، در ظاهر یادآور زبان قالب بندی IRBIS 64 (و در واقع، همچنین سیستم داعش - با پرانتز به‌عنوان ساختارهای چرخه‌ای؛ چرا در آن زمان فکر می‌کردم خیلی جالب به نظر می‌رسد). تجزیه کننده ناامیدانه به این دایره های پرانتز از نوع مناسب برخورد کرد (از آنجایی که پرانتزها نقش دیگری را نیز ایفا می کردند، یعنی ساختارهای اختیاری را در حین تجزیه علامت گذاری کردند که می توان آنها را نادیده گرفت). من مجدداً همه کسانی را که می خواهند با نحو غیرقابل تصور و غیرقابل تصور BIRMA با جزئیات بیشتری آشنا شوند به گزارش خود در آن زمان ارجاع می دهم.

به طور کلی، جدای از اینکه با تجزیه کننده خودم دست و پنجه نرم می کنم، در مورد کد این نسخه چیز دیگری برای گفتن ندارم - به جز تبدیل معکوس منابع موجود به C++ با حفظ برخی از ویژگی های معمول کد دات نت (راستش را بخواهید، این درک آن دشوار است، دقیقاً چه چیزی مرا وادار کرد که همه چیز را به عقب برگردانم - احتمالاً یک ترس احمقانه از مخفی نگه داشتن کدهای منبع من، گویی چیزی معادل دستور العمل مخفی کوکاکولا است).

شاید این تصمیم احمقانه همچنین دلیل مشکلات جفت کردن کتابخانه DLL حاصل با رابط موجود یک ایستگاه کاری خانگی برای وارد کردن داده ها به یک کاتالوگ الکترونیکی باشد (بله، من به واقعیت مهم دیگری اشاره نکردم: از این به بعد همه کد "موتور" BIRMA همانطور که انتظار می رفت، از قسمت رابط جدا شده و در DLL مناسب بسته بندی شده است). چرا لازم بود برای این اهداف یک ایستگاه کاری جداگانه نوشته شود، که به هر حال، در ظاهر و روش تعامل با کاربر، بی شرمانه همان ایستگاه کاری "کاتالوژیزر" سیستم IRBIS 64 را کپی می کرد - این یک سوال جداگانه است. به طور خلاصه: به پیشرفت های آن زمان من برای پروژه فارغ التحصیلی من استحکام لازم را داد (در غیر این صورت موتور تجزیه کننده غیرقابل هضم به تنهایی کافی نبود). علاوه بر این، در پیاده‌سازی رابط ایستگاه کاری Cataloger با ماژول‌های خودم، که در C++ و C# پیاده‌سازی شده‌اند، و دسترسی مستقیم به موتورم با مشکلاتی مواجه شدم.

به طور کلی، به اندازه کافی عجیب، این نمونه اولیه نسبتاً ناشیانه BIRMA.NET آینده بود که قرار بود برای چهار سال آینده به "اسب کار" من تبدیل شود. نمی توان گفت در این مدت حداقل سعی نکردم راه هایی برای اجرای جدید و کامل تر یک ایده دیرینه پیدا کنم. در میان نوآوری‌های دیگر، باید توالی‌های چرخه‌ای تودرتو وجود داشته باشد که می‌توانست شامل عناصر اختیاری باشد - اینگونه بود که می‌خواستم ایده الگوهای جهانی برای توضیحات کتابشناختی نشریات و چیزهای مختلف جالب دیگر را زنده کنم. با این حال، در فعالیت های عملی من در آن زمان، همه اینها تقاضای کمی داشت و اجرای من در آن زمان برای ورود به فهرست مطالب کاملاً کافی بود. علاوه بر این، جهت توسعه کتابخانه ما بیشتر و بیشتر به سمت دیجیتالی کردن آرشیوهای موزه، گزارش و سایر فعالیت هایی که برای من جالب نبود، منحرف شد، که در نهایت مجبور شدم در نهایت آن را ترک کنم و جای خود را به کسانی بدهم که می خواهند. از این همه بیشتر راضی باش .

به طرز متناقضی، پس از این رویدادهای دراماتیک بود که به نظر می رسید پروژه BIRMA، که در آن زمان تمام ویژگی های مشخصه یک پروژه ساخت و ساز درازمدت معمولی را داشت، به نظر می رسید زندگی جدید خود را که مدت ها انتظارش را می کشید، به خود بگیرد! وقت آزاد بیشتری برای افکار بیهوده داشتم، دوباره شروع کردم به جستجوی وب جهانی در جستجوی چیزی مشابه (خوشبختانه ، اکنون می توانم حدس بزنم که همه اینها را نه فقط در هر کجا بلکه در GitHub جستجو کنم) و جایی در At the در اوایل سال جاری، سرانجام با محصولی از شرکت معروف Salesforce به نام ناچیز مواجه شدم. گورپ. به خودی خود، می تواند تقریباً هر کاری را که من از چنین موتور تجزیه کننده ای نیاز داشتم انجام دهد - یعنی به طور هوشمندانه قطعات فردی را از متن دلخواه اما ساختار یافته جدا کند، در حالی که یک رابط کاربری نسبتاً کاربرپسند برای کاربر نهایی دارد، از جمله جوهرهای قابل درک، مانند یک الگو، الگو و رخداد، و در عین حال استفاده از نحو آشنای عبارات منظم، که به دلیل تقسیم به گروه های معنایی تعیین شده برای تجزیه، به طور غیر قابل مقایسه ای قابل خواندن تر می شود.

به طور کلی، من تصمیم گرفتم که این یکی است گورپ (من نمی دانم این نام به چه معناست؟ شاید نوعی "تجزیه کننده معمولی با محوریت عمومی"؟) - دقیقاً همان چیزی است که مدت طولانی به دنبال آن بودم. درست است، اجرای فوری آن برای نیازهای خودم چنین مشکلی داشت که این موتور نیاز به رعایت دقیق توالی ساختاری متن منبع داشت. برای برخی گزارش‌ها مانند فایل‌های گزارش (یعنی آنها توسط توسعه‌دهندگان به عنوان نمونه‌های واضح استفاده از پروژه قرار داده شده‌اند)، این کاملاً مناسب است، اما برای متون مشابه فهرست‌های اسکن شده محتویات، بعید است. از این گذشته ، همان صفحه با فهرست مطالب می تواند با کلمات "فهرست مطالب" ، "مطالب" و هر توضیحات اولیه دیگری که نیازی به قرار دادن آنها در نتایج تجزیه و تحلیل مورد نظر نداریم (و قطع کردن آنها به صورت دستی) شروع شود. هر بار نیز ناخوشایند است). علاوه بر این، بین عناصر تکرار شونده منفرد، مانند نام نویسنده، عنوان و شماره صفحه، صفحه ممکن است حاوی مقدار معینی زباله باشد (مثلاً نقاشی‌ها و کاراکترهای تصادفی) که همچنین خوب است که بتوانید قطع کردن با این حال، جنبه آخر هنوز چندان قابل توجه نبود، اما به دلیل اولی، اجرای موجود نتوانست از یک مکان خاص جستجوی ساختارهای لازم در متن را آغاز کند، بلکه به سادگی آن را از همان ابتدا پردازش کرد، آن را پیدا نکرد. الگوهای مشخص شده در آنجا و ... به کار من پایان داد. بدیهی است که به اصلاحاتی نیاز بود تا حداقل فضایی بین ساختارهای تکراری ایجاد شود و این باعث شد که من به کار برگردم.

مشکل دیگر این بود که خود پروژه در جاوا پیاده‌سازی شد و اگر من در آینده برنامه‌ریزی می‌کردم که ابزاری برای ارتباط این فناوری با برنامه‌های کاربردی آشنا برای وارد کردن داده‌ها به پایگاه‌های داده موجود (مانند «کاتالوگ» Irbis) پیاده‌سازی کنم، حداقل حداقل این کار را در سی شارپ و دات نت انجام دهید. این طور نیست که جاوا خود زبان بدی باشد - من حتی یک بار از آن برای پیاده سازی یک برنامه پنجره جالب استفاده کردم که عملکرد یک ماشین حساب قابل برنامه ریزی داخلی (به عنوان بخشی از یک پروژه دوره) را اجرا می کرد. و از نظر نحو بسیار شبیه به همان سی شارپ است. خوب، این فقط یک مزیت است: نهایی کردن یک پروژه موجود برای من آسان تر خواهد بود. با این حال ، من نمی خواستم دوباره وارد این دنیای نسبتاً غیرمعمول فناوری های جاوا پنجره (یا بهتر است بگوییم دسکتاپ) شوم - از این گذشته ، خود زبان برای چنین استفاده ای "طراحی" نشده بود و من اصلاً آرزوی تکرار آن را نداشتم. تجربه قبلی شاید دقیقاً به این دلیل باشد که سی شارپ در ارتباط با WinForms بسیار به دلفی نزدیک‌تر است که بسیاری از ما زمانی با آن شروع کرده‌ایم. خوشبختانه، راه حل لازم به سرعت - در قالب پروژه - پیدا شد IKVM.NET، که ترجمه برنامه های جاوا موجود را به کد NET مدیریت شده آسان می کند. درست است، خود پروژه قبلاً توسط نویسندگان تا آن زمان رها شده بود، اما آخرین اجرای آن به من اجازه داد تا اقدامات لازم را برای متون منبع کاملاً با موفقیت انجام دهم. گورپ.

بنابراین من تمام تغییرات لازم را انجام دادم و همه آنها را در یک DLL از نوع مناسب مونتاژ کردم، که به راحتی توسط هر پروژه ای برای چارچوب دات نت ایجاد شده در ویژوال استودیو قابل "انتخاب" بود. در همین حین، یک لایه دیگر برای ارائه راحت نتایج برگشتی ایجاد کردم گورپ، به شکل ساختارهای داده متناظر که پردازش آنها در نمای جدولی راحت باشد (با استفاده از هر دو ردیف و ستون؛ هم کلیدهای فرهنگ لغت و هم شاخص های عددی). خوب، خود ابزارهای ضروری برای پردازش و نمایش نتایج به سرعت نوشته شدند.

همچنین فرآیند تطبیق قالب‌ها برای موتور جدید به منظور آموزش تجزیه نمونه‌های موجود از متون اسکن شده فهرست مطالب، عارضه خاصی ایجاد نکرد. در واقع، من حتی مجبور نبودم به قالب های قبلی خود مراجعه کنم: من به سادگی تمام قالب های لازم را از ابتدا ایجاد کردم. علاوه بر این، اگر قالب‌هایی که برای کار با نسخه قبلی سیستم طراحی شده‌اند، چارچوب نسبتاً باریکی را برای متون تنظیم می‌کنند که می‌توان با کمک آنها به درستی تجزیه و تحلیل شوند، موتور جدید امکان توسعه الگوهای نسبتاً جهانی مناسب برای چندین نوع نشانه‌گذاری را فراهم کرده است. یک بار. من حتی سعی کردم برای هر متن دلخواه فهرست مطالب، نوعی الگوی جامع بنویسم، اگرچه، البته، حتی با وجود تمام امکانات جدیدی که برای من باز شده است، از جمله، به ویژه، توانایی محدود اجرای همان توالی های تکراری تو در تو ( مانند نام خانوادگی و حروف اول چندین نویسنده پشت سر هم)، این یک مدینه فاضله بود.

شاید در آینده امکان پیاده‌سازی مفهوم خاصی از متاالگوها وجود داشته باشد که بتواند متن منبع را برای انطباق با چندین الگوی موجود به طور همزمان بررسی کند و سپس مطابق با نتایج به‌دست‌آمده، مناسب ترین، با استفاده از نوعی الگوریتم هوشمند. اما حالا بیشتر نگران سوال دیگری بودم. تجزیه کننده مانند گورپبا وجود همه کاره بودن و تغییراتی که انجام دادم، هنوز ذاتاً قادر به انجام یک کار به ظاهر ساده نبود که تجزیه کننده خودنویس من از همان نسخه اول قادر به انجام آن بود. یعنی: او این توانایی را داشت که تمام قطعاتی را که با ماسک مشخص شده در قالب استفاده شده در جای مناسب مطابقت دارند، پیدا کند و از متن اصلی استخراج کند، در حالی که اصلا علاقه ای به محتوای متن داده شده در فاصله های بین این قطعات نداشت. تا کنون، من فقط اندکی موتور جدید را بهبود بخشیده ام، و به آن اجازه داده ام که تمام تکرارهای جدید ممکن از یک دنباله معین از چنین ماسک هایی را از موقعیت فعلی جستجو کند، و امکان حضور در متن مجموعه هایی از شخصیت های دلخواه را که کاملاً بودند، باقی بگذارد. در تجزیه به حساب نیامده، بین ساختارهای تکرار شونده شناسایی شده محصور شده است. با این حال، این امکان تنظیم ماسک بعدی را بدون توجه به نتایج جستجوی قطعه قبلی با استفاده از ماسک مربوطه فراهم نکرد: سختگیری ساختار متن توصیف شده هنوز جایی برای درج دلخواه کاراکترهای نامنظم باقی نمی گذارد.

و اگر برای مثال هایی از فهرست مطالبی که من با آنها برخورد کردم، این مشکل هنوز آنقدر جدی به نظر نمی رسید، پس هنگام تلاش برای اعمال یک مکانیسم تجزیه جدید برای کار مشابه تجزیه محتوای یک وب سایت (یعنی همان تجزیه)، محدودیت ها اینجاست که با تمام بدیهیات ظاهر شدند. از این گذشته، تنظیم ماسک های لازم برای قطعات نشانه گذاری وب، که بین آنها داده های مورد نظر ما (که باید استخراج شوند) باید بین آنها قرار گیرند، بسیار آسان است، اما چگونه می توانیم تجزیه کننده را مجبور کنیم که فوراً به سراغ بعدی برود. قطعه مشابه، با وجود تمام تگ های ممکن و ویژگی های HTML که می توان در فاصله های بین آنها قرار داد؟

بعد از کمی فکر تصمیم گرفتم چند الگوی خدماتی را معرفی کنم (%all_before) и (% all_after)، در خدمت هدف آشکار اطمینان از اینکه همه چیزهایی که ممکن است در متن منبع وجود داشته باشد قبل از هر الگوی (نقاب) که از آنها پیروی می کند نادیده گرفته می شود. علاوه بر این، اگر (%all_before) پس به سادگی تمام این شمول های دلخواه را نادیده گرفت (% all_after)برعکس، این امکان را به آنها داد که پس از جابجایی از قطعه قبلی به قطعه مورد نظر اضافه شوند. خیلی ساده به نظر می رسد، اما برای پیاده سازی این مفهوم، مجبور شدم دوباره منابع gorp را بررسی کنم تا تغییرات لازم را انجام دهم تا منطق قبلاً اجرا شده را شکسته نشوم. در پایان، ما موفق به انجام این کار شدیم (اگرچه حتی اولین، هرچند بسیار باگ، پیاده سازی تجزیه کننده من نوشته شد، و حتی سریعتر - در چند هفته). از این پس، این سیستم یک شکل واقعاً جهانی به خود گرفت - نه کمتر از 12 سال پس از اولین تلاش ها برای عملکرد آن.

البته این پایان رویاهای ما نیست. همچنین می‌توانید تجزیه‌کننده قالب gorp را در سی شارپ با استفاده از هر یک از کتابخانه‌های موجود برای پیاده‌سازی گرامر رایگان بازنویسی کنید. من فکر می کنم کد باید به طور قابل توجهی ساده شود، و این به ما اجازه می دهد تا از شر میراث موجود در منابع جاوا خلاص شویم. اما با نوع موتور موجود، انجام کارهای مختلف جالب نیز کاملاً امکان پذیر است، از جمله تلاش برای پیاده سازی متا قالب هایی که قبلاً ذکر کردم، و نه تجزیه و تحلیل داده های مختلف از وب سایت های مختلف (البته من رد نمی کنم. که ابزارهای نرم افزاری تخصصی موجود برای این کار مناسب تر هستند - من هنوز تجربه مناسبی از استفاده از آنها نداشته ام).

به هر حال، تابستان امسال من قبلاً دعوت نامه ای از طریق ایمیل از یک شرکت که از فناوری های Salesforce استفاده می کند (توسعه دهنده نسخه اصلی) دریافت کردم. گورپ) برای کارهای بعدی در ریگا مصاحبه کنید. متأسفانه، در حال حاضر برای چنین جابجایی ها آماده نیستم.

اگر این مطالب باعث جلب توجه شود، در قسمت دوم سعی خواهم کرد با استفاده از مثال پیاده سازی مورد استفاده در Salesforce، فناوری کامپایل و متعاقبا تجزیه قالب ها را با جزئیات بیشتری شرح دهم. گورپ (اضافه‌های خود من، به استثنای چند کلمه تابعی که قبلاً توضیح داده شد، عملاً هیچ تغییری در نحو الگو ایجاد نمی‌کند، بنابراین تقریباً تمام اسناد برای سیستم اصلی گورپ برای نسخه من هم مناسب است).

منبع: www.habr.com

اضافه کردن نظر