بیشتر از یه سال پیش، دنبال یه فریمورک میگشتم که بتونم باهاش سرویسهای یه بکاند رو طراحی کنم و از دیتابیس Neo4j استفاده کنم (همینطور که میدونید یه دیتابیس برپایهی گرافه). اینکه این فریمورک آزادی سفارشیسازی رو هم بهم بده، خیلی برام مهم بود. زبان برنامهنویسی که بهش علاقه دارم و باهاش کار میکنم، پایتونه، پس سعی کردم دنبال فریمورکهای پایتون بگردم، از Django گرفته تا Flask و باقی فریمورکها.
بزرگترین مشکل این بود که هیچ کدوم از این فریمورکها از دیتابیسهای گراف بهصورت پیشفرض استفاده نمیکردن و باید خودم همه کار رو انجام میدادم و برای راحتی هم از Object-Graph Mapper (OGM) استفاده میکردم تا بتونم CRUD روی دیتابیس Neo4j رو انجام بدم. این کار با دیتابیسهای SQL و یه سری دیتابیسهای خاص NoSQL مثل MongoDB خیلی راحته و فقط کافیه schema رو تعریف کنید و یه سری route اضافه کنید تا عین هلو، فریمورک باقی کار رو انجام بده. فرض کنید باید روی هر Node و Relationship یه سری کد بزنی و همه چیز رو خودت تعریف کنی واسه هر کاری که قراره با استفاده از HTTP verbs انجام بشه.
خلاصه کلنجار رفتن با فریمورکهای موجود این شد که تصمیم گرفتم خودم کلاسها و متدها رو تعریف کنم تا بتونم viewهامو برای هر endpoint داشته باشم.
چون با Flask تو پروژههای دیگه کار کرده بودم و خروجی قابل قبولی داشت برام، تصمیم گرفتم تو این کار هم از Flask استفاده کنم و از extensionهای موجودش هم استفاده کنم. برای اینکه بتونم viewهارو به شکل کلاس تعریف کنم از Flask-Classy استفاده کردم. بعد متوجه شدم که منسوخ شده پروژهاش و یکی دیگه پروژه رو fork گرفته، تغییر داده اسمشو و کلی هم pull request رو روش patch کرده و داره روش وقت میذاره. پس از Flask-Classful استفاده کردم.
برای اینکه بتونم به قول مایکروسافتیها schema-first پیش برم، از یه OGM استفاده کردم به اسم Neomodel که تقریبا تمام چیزهایی که من میخواستم برای ارتباط با Neo4j بهم میداد و syntax خیلی خوب و راحتی هم داشت به نسبت py2neo.
از ترکیب Flask و Flask-Classful و Neomodel یه کلاس بزرگ نوشتم که همه کارهایی که من میخواستم با اون دیتابیس انجام بدم رو تسهیل میکرد، مثل ساخت Node و برقراری Relationship بین Nodeها. اون کلاسی که ساختم اسمشو گذاشتم generic_view و برای هر Node و Relationshipهاش از اون کلاس ارثبری میکردم و فقط اسم کلاس schema مرتبط با اون Node رو تو یه dictionary تعریف میکردم. این شد که برای هر endpoint نهایت به ده خط کد نیاز بود.
همه چیز داشت خوب پیش میرفت که به ذهنم رسید که باید قرضمو به جامعه نرمافزارهای آزاد/متنباز باید پس بدم. به همین خاطر اون بخش از کد رو از پروژه کندم و تبدیلش کردم به یه پروژه جدید که بشه به عنوان یه extension توی Flask ازش استفاده کرد.
و gREST متولد شد، فریمورکی برای ساخت Restful API بر پایهی پایتون با استفاده از Flask و Neo4j و Neomodel و رفقا! هدف اصلی راحتتر کردن توسعه نرمافزار و کاهش حجم کد بود.
بعد از تولد تبدیلش کردم به یه package پایتون و روی PYPI منتشرش کردم. براش unit-test نوشتم، یه README و دو تا مثال ساده که توسعهدهندهها بتونن بیشتر در موردش بدونن. اخیرا دارم روش مستندات کاملتر هم کار میکنم.
برای unit-testها از pytest، برای CI از Travis و برای code coverage از Coveralls استفاده کردم. برای اینکه بتونم به توسعهدهندهها کمک کنم و همچنین بتونم از کمکشون هم استفاده کنم از Gitter استفاده کردم. چون لایسنس پروژه برام خیلی مهم بود، از GPL v3 استفاده کردم و از سرویس ابری FOSSA برای چک کردن تطابق لایسنس فعلی با کتابخونههای استفاده شده تو پروژه استفاده کردم. تیمی که FOSSA رو ساخته واقعا قابل تشویق و تقدیره، کارشون حرف نداره. جالبه بدونید که یکی از کتابخونههایی که استفاده میکردم تطابق لایسنسی نداشت و مجبور شدم عوضش کنم.
الان که بیشتر از یک سال از انتشار این پروژه میگذره، بر مبنای کوئری که از BigQuery روی دیتابیس دانلود پروژههای PYPI گرفتم، بیش از 36000 بار این پروژه دانلود شده.
چون اون موقع که پروژه رو منتشر کردم در موردش توئیت کردم، بلاگ Neo4j در موردش یه خط نوشت!
در نهایت، خیلی سعی کردم در طول این سال باگهای رو رفع کنم و بهبود بدم کد و قابلیتهای پروژه رو اما به کمک جامعه نیاز دارم تا بتونم بیشتر توسعه بدم کار رو. ایدههای دیگهای هم برای زبانها و فریمورکهای دیگه دارم. امیدوارم که این کار باعث تقویت و پیشرفت جامعه بشه. تو نوشتهی بعدیم در مورد نحوه کار و ساخت یه پروژه ساده بر مبنای gREST مطلب مینویسم.
همین مطلب رو به زبان انگلیسی تو Medium هم قبلا منتشر کردم: