Kisah sebuah proyek kecil selama dua belas tahun (tentang BIRMA.NET untuk pertama kalinya dan sejujurnya langsung)

Kelahiran proyek ini dapat dianggap sebagai ide kecil yang datang kepada saya di suatu tempat pada akhir tahun 2007, yang ditakdirkan untuk menemukan bentuk akhirnya hanya 12 tahun kemudian (pada saat ini - tentu saja, meskipun implementasinya saat ini, menurut bagi penulis, sangat memuaskan).

Semuanya bermula ketika, dalam menjalankan tugas resmi saya di perpustakaan, saya memperhatikan fakta bahwa proses memasukkan data dari teks pindaian daftar isi terbitan buku (dan musik) ke dalam database yang ada, rupanya, dapat disederhanakan dan diotomatisasi secara signifikan, dengan memanfaatkan properti keteraturan dan pengulangan semua data yang diperlukan untuk input, seperti nama penulis artikel (jika kita berbicara tentang kumpulan artikel), judul dari artikel (atau subjudul yang tercermin dalam daftar isi) dan nomor halaman item daftar isi saat ini. Pada awalnya, saya yakin bahwa sistem yang cocok untuk melaksanakan tugas ini dapat dengan mudah ditemukan di Internet. Ketika ada kejutan yang disebabkan oleh kenyataan bahwa saya tidak dapat menemukan proyek seperti itu, saya memutuskan untuk mencoba mengimplementasikannya sendiri.

Setelah waktu yang cukup singkat, prototipe pertama mulai berfungsi, yang segera saya gunakan dalam aktivitas sehari-hari, sekaligus melakukan debug pada semua contoh yang ada di tangan saya. Untungnya, di tempat kerja saya yang biasa, di mana saya sama sekali bukan seorang programmer, saya masih lolos dari "waktu henti" yang terlihat dalam pekerjaan saya, di mana saya secara intensif men-debug gagasan saya - sebuah hal yang hampir tidak terpikirkan dalam kenyataan saat ini, yang menyiratkan laporan harian tentang pekerjaan yang dilakukan pada siang hari. Proses penyempurnaan program ini memakan waktu total tidak kurang dari satu tahun, namun bahkan setelah itu hasilnya hampir tidak dapat disebut sepenuhnya sukses - terlalu banyak konsep berbeda yang awalnya ditetapkan yang tidak sepenuhnya jelas untuk diterapkan: elemen opsional yang dapat dilewati; melihat elemen ke depan (untuk tujuan menggantikan elemen sebelumnya ke dalam hasil pencarian); bahkan upaya kita sendiri untuk mengimplementasikan sesuatu seperti ekspresi reguler (yang memiliki sintaksis unik). Saya harus mengatakan bahwa sebelumnya saya sudah berhenti pemrograman (selama sekitar 8 tahun, jika tidak lebih), sehingga kesempatan baru untuk menerapkan keterampilan saya pada tugas yang menarik dan perlu benar-benar menarik perhatian saya. Tidak mengherankan bahwa kode sumber yang dihasilkan - karena tidak adanya pendekatan yang jelas terhadap desainnya - dengan cepat menjadi campuran yang tak terbayangkan dari bagian-bagian berbeda dalam bahasa C dengan beberapa elemen C++ dan aspek pemrograman visual (awalnya adalah diputuskan untuk menggunakan sistem desain seperti Borland C++ Builder - “hampir Delphi, tetapi dalam C”). Namun, semua ini pada akhirnya membuahkan hasil dalam otomatisasi aktivitas sehari-hari perpustakaan kami.

Pada saat yang sama, untuk berjaga-jaga, saya memutuskan untuk mengambil kursus untuk melatih pengembang perangkat lunak profesional. Saya tidak tahu apakah sebenarnya mungkin untuk belajar “menjadi programmer” dari awal di sana, tetapi dengan mempertimbangkan keterampilan yang sudah saya miliki saat itu, saya bisa menguasai teknologi yang lebih relevan pada saat itu, seperti seperti C#, Visual Studio untuk pengembangan di bawah .NET, serta beberapa teknologi yang terkait dengan Java, HTML, dan SQL. Seluruh pelatihan memakan waktu total dua tahun, dan menjadi titik awal untuk proyek saya yang lain, yang akhirnya berlangsung selama beberapa tahun - tetapi ini adalah topik untuk publikasi terpisah. Di sini hanya pantas untuk dicatat bahwa saya melakukan upaya untuk mengadaptasi perkembangan yang sudah saya miliki pada proyek yang dijelaskan untuk membuat aplikasi jendela lengkap dalam C# dan WinForms yang mengimplementasikan fungsionalitas yang diperlukan, dan menggunakannya sebagai dasar untuk proyek diploma yang akan datang.
Seiring berjalannya waktu, ide ini bagi saya mulai terasa layak untuk disuarakan pada konferensi tahunan dengan partisipasi perwakilan dari berbagai perpustakaan seperti “LIBKOM” dan “CRIMEA”. Idenya ya, tapi bukan implementasi saya saat itu. Kemudian saya juga berharap ada yang menulis ulang dengan pendekatan yang lebih kompeten. Dengan satu atau lain cara, pada tahun 2013 saya memutuskan untuk menulis laporan tentang pekerjaan awal saya dan mengirimkannya ke Panitia Penyelenggara Konferensi dengan permohonan hibah untuk berpartisipasi dalam konferensi tersebut. Yang agak mengejutkan saya, permohonan saya disetujui, dan saya mulai melakukan beberapa perbaikan pada proyek untuk mempersiapkannya untuk presentasi di konferensi.

Pada saat itu, proyek tersebut telah menerima nama baru BIRMA, memperoleh berbagai kemampuan tambahan (tidak terlalu diimplementasikan sepenuhnya, melainkan diasumsikan) - semua detail dapat ditemukan di laporan saya.

Sejujurnya, sulit untuk menyebut BIRMA 2013 sebagai sesuatu yang lengkap; Sejujurnya, itu adalah kerajinan yang sangat rumit dan dibuat dengan tergesa-gesa. Dalam hal kode, praktis tidak ada inovasi khusus sama sekali, kecuali upaya yang agak tidak berdaya untuk membuat semacam sintaksis terpadu untuk parser, yang secara tampilan mengingatkan pada bahasa pemformatan IRBIS 64 (dan pada kenyataannya, juga sistem ISIS - dengan tanda kurung sebagai struktur siklik; mengapa pada saat itu menurut saya itu terlihat cukup keren). Pengurai dengan putus asa menemukan lingkaran tanda kurung dari jenis yang sesuai (karena tanda kurung juga menjalankan peran lain, yaitu menandai struktur opsional selama penguraian yang dapat dilewati). Saya kembali merujuk kepada semua orang yang ingin mengenal sintaksis BIRMA yang sulit dibayangkan dan tidak dapat dibenarkan secara lebih rinci ke laporan saya saat itu.

Secara umum, selain berjuang dengan parser saya sendiri, tidak ada lagi yang bisa saya katakan mengenai kode versi ini - kecuali konversi terbalik dari sumber yang ada ke C++ sambil mempertahankan beberapa fitur khas kode .NET (sejujurnya, itu's sulit untuk dipahami, apa sebenarnya yang mendorong saya untuk mengembalikan semuanya - mungkin ketakutan bodoh karena merahasiakan kode sumber saya, seolah-olah itu adalah sesuatu yang setara dengan resep rahasia Coca-Cola).

Mungkin keputusan bodoh ini juga menjadi penyebab kesulitan dalam memasangkan perpustakaan DLL yang dihasilkan dengan antarmuka yang ada dari stasiun kerja buatan sendiri untuk memasukkan data ke dalam katalog elektronik (ya, saya tidak menyebutkan fakta penting lainnya: mulai sekarang, semuanya kode "mesin" BIRMA seperti yang diharapkan, dipisahkan dari bagian antarmuka dan dikemas dalam DLL yang sesuai). Mengapa perlu untuk menulis workstation terpisah untuk tujuan ini, yang, dalam penampilan dan metode interaksinya dengan pengguna, tanpa malu-malu menyalin workstation "Catalogizer" yang sama dari sistem IRBIS 64 - ini adalah pertanyaan terpisah. Singkatnya: ini memberikan soliditas yang diperlukan untuk perkembangan saya saat itu untuk proyek kelulusan saya (jika tidak, mesin parser yang tidak dapat dicerna saja tidak cukup). Selain itu, saya kemudian mengalami beberapa kesulitan dalam mengimplementasikan antarmuka stasiun kerja Cataloger dengan modul saya sendiri, diimplementasikan dalam C++ dan C#, dan mengakses mesin saya secara langsung.

Secara umum, anehnya, prototipe BIRMA.NET masa depan yang agak kikuk inilah yang ditakdirkan untuk menjadi “pekerja keras” saya selama empat tahun ke depan. Tidak dapat dikatakan bahwa selama ini saya setidaknya tidak mencoba mencari cara untuk implementasi baru yang lebih lengkap dari ide lama saya. Di antara inovasi lainnya, seharusnya sudah ada urutan siklik bersarang yang dapat menyertakan elemen opsional - inilah cara saya mewujudkan gagasan templat universal untuk deskripsi bibliografi publikasi dan berbagai hal menarik lainnya. Namun dalam kegiatan praktek saya saat itu, semua itu kurang diminati, dan implementasi yang saya miliki saat itu sudah cukup untuk masuk ke daftar isi. Selain itu, vektor perkembangan perpustakaan kita mulai semakin menyimpang ke arah digitalisasi arsip museum, pelaporan, dan kegiatan lain yang kurang menarik bagi saya, yang pada akhirnya memaksa saya untuk meninggalkannya, memberi jalan kepada mereka yang mau. menjadi lebih senang dengan semua ini.

Paradoksnya, setelah peristiwa-peristiwa dramatis inilah proyek BIRMA, yang pada saat itu sudah memiliki semua ciri khas proyek konstruksi jangka panjang, tampaknya mulai menjalani kehidupan baru yang telah lama ditunggu-tunggu! Saya memiliki lebih banyak waktu luang untuk memikirkan hal-hal yang tidak berguna, saya kembali mulai menyisir World Wide Web untuk mencari sesuatu yang serupa (untungnya, sekarang saya sudah dapat menebak untuk mencari semua ini tidak hanya di mana saja, tetapi di GitHub), dan di suatu tempat di Di awal tahun ini, saya akhirnya menemukan produk terkait dari perusahaan Salesforce terkenal dengan nama yang tidak penting Gorp. Dengan sendirinya, ia dapat melakukan hampir semua yang saya perlukan dari mesin parser seperti itu - yaitu, dengan cerdas mengisolasi fragmen individual dari teks yang sewenang-wenang namun terstruktur dengan jelas, sekaligus memiliki antarmuka yang cukup ramah pengguna untuk pengguna akhir, termasuk esensi yang dapat dimengerti seperti sebuah pola, templat, dan kemunculan, dan pada saat yang sama menggunakan sintaksis ekspresi reguler yang sudah dikenal, yang menjadi jauh lebih mudah dibaca karena pembagian ke dalam kelompok semantik yang ditentukan untuk penguraian.

Secara umum, saya memutuskan bahwa ini adalah satu-satunya Gorp (Saya ingin tahu apa arti nama ini? Mungkin semacam “parser reguler berorientasi umum”?) – persis seperti yang sudah lama saya cari. Benar, implementasi langsungnya untuk kebutuhan saya sendiri mempunyai masalah sehingga mesin ini memerlukan kepatuhan yang terlalu ketat terhadap urutan struktural teks sumber. Untuk beberapa laporan seperti file log (yaitu, ditempatkan oleh pengembang sebagai contoh jelas penggunaan proyek), ini cukup cocok, tetapi untuk teks yang sama dari daftar isi yang dipindai, hal ini tidak mungkin dilakukan. Lagi pula, halaman yang sama dengan daftar isi dapat diawali dengan kata “Daftar Isi”, “Isi” dan uraian awal lainnya yang tidak perlu kita tempatkan dalam hasil analisis yang dimaksud (dan memotongnya secara manual. setiap kali juga merepotkan). Selain itu, di antara elemen-elemen yang berulang, seperti nama penulis, judul, dan nomor halaman, halaman tersebut mungkin berisi sejumlah sampah (misalnya, gambar, dan hanya karakter acak), yang juga akan menyenangkan untuk dapat memotong. Namun aspek yang terakhir ini belum begitu signifikan, namun karena yang pertama maka implementasi yang ada tidak bisa mulai mencari struktur yang diperlukan dalam teks dari tempat tertentu, melainkan hanya mengolahnya dari awal, tidak menemukan titik temunya. pola yang ditentukan di sana dan... mengakhiri pekerjaan saya. Jelas, beberapa penyesuaian diperlukan untuk setidaknya memberikan ruang di antara struktur berulang, dan itu membuat saya kembali bekerja.

Masalah lainnya adalah bahwa proyek itu sendiri diimplementasikan di Java, dan jika di masa depan saya berencana untuk mengimplementasikan beberapa cara untuk menghubungkan teknologi ini dengan aplikasi yang sudah dikenal untuk memasukkan data ke dalam database yang ada (seperti “Katalog” Irbis), maka setidaknya Setidaknya lakukan ini di C# dan .NET. Bukan berarti Java sendiri adalah bahasa yang buruk – Saya bahkan pernah menggunakannya untuk mengimplementasikan aplikasi jendela menarik yang mengimplementasikan fungsionalitas kalkulator domestik yang dapat diprogram (sebagai bagian dari proyek kursus). Dan dari segi sintaksis sangat mirip dengan C-sharp yang sama. Nah, ini hanya nilai plusnya: semakin mudah bagi saya untuk menyelesaikan proyek yang sudah ada. Namun, saya tidak ingin terjun lagi ke dunia teknologi Java window (atau lebih tepatnya, desktop) yang agak tidak biasa ini - lagi pula, bahasanya sendiri tidak "disesuaikan" untuk penggunaan seperti itu, dan saya sama sekali tidak ingin mengulanginya. pengalaman sebelumnya. Mungkin justru karena C# dan WinForms lebih mirip dengan Delphi, yang banyak dari kita pernah memulainya. Untungnya, solusi yang diperlukan ditemukan cukup cepat - dalam bentuk proyek IKVM.NET, yang memudahkan penerjemahan program Java yang ada ke dalam kode .NET yang dikelola. Benar, proyek itu sendiri telah ditinggalkan oleh penulisnya pada saat itu, tetapi implementasi terbarunya memungkinkan saya untuk cukup berhasil melakukan tindakan yang diperlukan untuk teks sumber. Gorp.

Jadi saya membuat semua perubahan yang diperlukan dan mengumpulkan semuanya menjadi DLL dengan tipe yang sesuai, yang dapat dengan mudah "diambil" oleh proyek apa pun untuk .NET Framework yang dibuat di Visual Studio. Sementara itu, saya membuat layer lain untuk memudahkan presentasi hasil yang dikembalikan Gorp, dalam bentuk struktur data terkait yang mudah diproses dalam tampilan tabel (menggunakan baris dan kolom sebagai dasar; kunci kamus dan indeks numerik). Ya, utilitas yang diperlukan untuk memproses dan menampilkan hasilnya ditulis dengan cukup cepat.

Selain itu, proses mengadaptasi templat untuk mesin baru untuk mengajarkannya mengurai sampel teks daftar isi yang dipindai tidak menyebabkan komplikasi khusus. Faktanya, saya bahkan tidak perlu merujuk ke template saya sebelumnya sama sekali: Saya cukup membuat semua template yang diperlukan dari awal. Selain itu, jika templat yang dirancang untuk bekerja dengan sistem versi sebelumnya menetapkan kerangka kerja yang cukup sempit untuk teks yang dapat diurai dengan benar dengan bantuannya, mesin baru telah memungkinkan untuk mengembangkan templat yang cukup universal yang cocok untuk beberapa jenis markup di sekali. Saya bahkan mencoba menulis semacam templat komprehensif untuk teks daftar isi apa pun, meskipun, tentu saja, bahkan dengan semua kemungkinan baru yang terbuka bagi saya, termasuk, khususnya, kemampuan terbatas untuk mengimplementasikan urutan berulang bersarang yang sama ( seperti misalnya nama keluarga dan inisial beberapa penulis berturut-turut), hal ini ternyata hanya utopia.

Mungkin di masa depan akan dimungkinkan untuk menerapkan konsep meta-templat tertentu, yang akan dapat memeriksa kesesuaian teks sumber dengan beberapa templat yang tersedia sekaligus, dan kemudian, sesuai dengan hasil yang diperoleh, pilih yang paling cocok, menggunakan semacam algoritma cerdas. Tapi sekarang saya lebih khawatir tentang pertanyaan lain. Seperti parser Gorp, terlepas dari semua keserbagunaannya dan modifikasi yang saya buat, ia masih belum mampu melakukan satu hal yang tampaknya sederhana yang dapat dilakukan oleh parser yang saya tulis sendiri sejak versi pertama. Yaitu: dia memiliki kemampuan untuk menemukan dan mengekstrak dari teks sumber semua fragmen yang cocok dengan topeng yang ditentukan dalam templat yang digunakan di tempat yang tepat, tanpa tertarik sama sekali dengan isi teks yang diberikan di spasi di antara fragmen tersebut. Sejauh ini, saya hanya sedikit meningkatkan mesin baru, memungkinkannya untuk mencari semua kemungkinan pengulangan baru dari urutan tertentu dari topeng tersebut dari posisi saat ini, meninggalkan kemungkinan kehadiran dalam teks kumpulan karakter arbitrer yang sepenuhnya tidak terhitung dalam penguraian, tertutup di antara struktur berulang yang terdeteksi. Namun, hal ini tidak memungkinkan untuk menyetel topeng berikutnya terlepas dari hasil pencarian fragmen sebelumnya menggunakan topeng yang sesuai: ketatnya struktur teks yang dijelaskan masih tidak memberikan ruang untuk penyertaan karakter tidak beraturan secara sewenang-wenang.

Dan jika untuk contoh daftar isi yang saya temui, masalah ini tampaknya belum terlalu serius, maka ketika mencoba menerapkan mekanisme parsing baru untuk tugas serupa mengurai konten situs web (yaitu parsing yang sama), itu keterbatasan di sini mereka muncul dengan segala kejelasannya. Lagi pula, cukup mudah untuk mengatur topeng yang diperlukan untuk fragmen markup web, di mana data yang kita cari (yang perlu diekstraksi) harus ditempatkan, tetapi bagaimana kita bisa memaksa parser untuk segera melanjutkan ke yang berikutnya? fragmen serupa, terlepas dari semua kemungkinan tag dan atribut HTML yang dapat ditempatkan di spasi di antara keduanya?

Setelah berpikir sebentar, saya memutuskan untuk memperkenalkan beberapa pola layanan (%semua_sebelum) и (%semua_setelah), dengan tujuan yang jelas untuk memastikan bahwa segala sesuatu yang mungkin terkandung dalam teks sumber dilewati sebelum pola (topeng) apa pun yang mengikutinya. Apalagi jika (%semua_sebelum) abaikan saja semua penyertaan sewenang-wenang ini (%semua_setelah), sebaliknya, mengizinkannya untuk ditambahkan ke fragmen yang diinginkan setelah berpindah dari fragmen sebelumnya. Kedengarannya cukup sederhana, namun untuk mengimplementasikan konsep ini saya harus menyisir sumber gorp lagi untuk melakukan modifikasi yang diperlukan agar tidak merusak logika yang sudah diterapkan. Pada akhirnya, kami berhasil melakukan ini (walaupun implementasi parser saya yang pertama, meskipun sangat bermasalah, telah ditulis, dan bahkan lebih cepat - dalam beberapa minggu). Mulai sekarang, sistem tersebut mengambil bentuk yang benar-benar universal - tidak kurang dari 12 tahun setelah upaya pertama untuk membuatnya berfungsi.

Tentu saja ini bukanlah akhir dari impian kita. Anda juga dapat sepenuhnya menulis ulang parser template gorp di C#, menggunakan salah satu perpustakaan yang tersedia untuk mengimplementasikan tata bahasa gratis. Saya pikir kodenya harus disederhanakan secara signifikan, dan ini akan memungkinkan kita menghilangkan warisan dalam bentuk sumber Java yang ada. Namun dengan jenis engine yang ada, juga tidak menutup kemungkinan untuk melakukan berbagai hal menarik, termasuk upaya mengimplementasikan meta-template yang telah saya sebutkan, belum lagi parsing berbagai data dari berbagai website (namun tidak menutup kemungkinan bahwa perangkat lunak khusus yang ada saat ini lebih cocok untuk hal ini – hanya saja saya belum memiliki pengalaman yang tepat dalam menggunakannya).

Ngomong-ngomong, musim panas ini saya sudah menerima undangan melalui email dari perusahaan yang menggunakan teknologi Salesforce (pengembang aslinya Gorp), lulus wawancara untuk pekerjaan selanjutnya di Riga. Sayangnya, saat ini saya belum siap untuk pemindahan seperti itu.

Jika materi ini menarik minat, maka pada bagian kedua saya akan mencoba menjelaskan lebih detail teknologi kompilasi dan selanjutnya parsing template menggunakan contoh implementasi yang digunakan di Salesforce Gorp (tambahan saya sendiri, dengan pengecualian beberapa kata fungsi yang telah dijelaskan, hampir tidak membuat perubahan pada sintaks templat itu sendiri, sehingga hampir semua dokumentasi untuk sistem asli Gorp Cocok untuk versi saya juga).

Sumber: www.habr.com

Tambah komentar