آشنایی با ۱۲-فاکتور اپلیکیشن (The twelve-factor app) فاکتور های اول تا سوم

دوازده فاکتور اپلیکیشن
دوازده فاکتور اپلیکیشن - صادق خان

با سلام و درود، امروز با ۱۲ فاکترو اپلیکیشن یا ( The twelve-factor app ) در خدمتتون هستم، احتمالا قبلا در موردش شنیده باشید، خواستم داخل بلاگ یه مطلب در موردش داشته باشم که اگر بعدا حرفی ازش زده شد بتونم ارجاع بدم بهش 🙂

مقدمه: The twelve-factor app

در حال حاضر، نرم افزار معمولا به عنوان سرویس ارائه می شود، software-as-a-service، دوارده فاکتور اپلیکیشن یک روش (متدولوژی) برای ساخت اپلیکیشن ، نرم افزار به عنوان سرویس می باشد، که:

  • استفاده از فرمت های مشخص و روشن جهت راه اندازی اتوماسیون، جهت کمینه کردن زمان و هزینه پیوستن توسعه دهندگان جدید به پروژه
  • داشتن یک قرارداد دقیق با سیستم عاملی که روی آن اجرا داریم، منجر به حداکثر قابلیت حمل بین محیط های اجرا می شود.
  • برای استقرار روی پلتفرم های مدرن ابری مناسب هستند، و نیاز به سرور و مدیران سرور را برطرف می کند.
  • به حداقل رساندن واگرایی (دایورجنس) بین توسعه و تولید (develope and production)، که منجر به امکان استقرار مداوم برای حداکثر چابکی (maximum agility)
  • و توانایی انعطاف پذیری بدون تغییرات قابل توجهی در ابزار، معماری یا شیوه های توسعه

متودولوژی ۱۲ فاکتور می تواند روی اپلیکیشن های نوشته شده به هر زبان برنامه نویسی و ترکیب شده با هر سرویس back ای (database, queue, memory cache, و غیره ) اعمال شود.

پس از مقدمه قبل از اصل بحث 🙂

خب من ابتدا از جانب طراحان فاکتورهای ۱۲ گانه صحبت کنم:

مشارکت کنندگان این سند مستقیماً در توسعه و استقرار صدها برنامه مشارکت داشته اند و به طور غیرمستقیم شاهد توسعه، عملکرد و مقیاس دهی صدها هزار برنامه از طریق کار ما روی پلت فرم Heroku بوده اند.

این سند ترکیبی از تمام تجربیات و مشاهدات ما را در مورد طیف گسترده ای از برنامه های نرم افزاری به عنوان سرویس (software as a service) در دنیای واقعی می باشد. این یک مثلث بر روی شیوه‌های ایده‌آل برای توسعه اپلیکیشن است، توجه ویژه‌ای به پویایی رشد ارگانیک یک برنامه در طول زمان، پویایی همکاری بین توسعه‌دهندگانی که روی پایگاه کد برنامه کار می‌کنند، و اجتناب از هزینه‌های فرسایش نرم‌افزار است.

نگیزه ما افزایش آگاهی از برخی مشکلات سیستمی است که در توسعه برنامه های کاربردی مدرن دیده ایم، واژگان مشترکی برای بحث در مورد آن مشکلات ارائه می دهیم، و مجموعه ای از راه حل های مفهومی گسترده برای آن مشکلات را با اصطلاحات همراه ارائه می دهیم. این فرمت با الهام از کتاب‌های مارتین فاولر Patterns of Enterprise Application Architecture and Refactoring ساخته شده است.

فاکترو های ۱۲ گانه اپلیکیشن به درد چه کسانی می خورد؟

این فاکتورهای ۱۲ گانه اپلیکیشن به درد هر کسی که به توسعه اپلیکیشن به عنوان سرویس می پردازد می خورد. همچنینن بدرد مهندسینی که به استقرار و مدیریت همچون نرم افزارهایی مشغول هستند نیز می خورد.

فاکتورهای ۱۲ گانه

۱- codebase – پایگاه کد

یک codebase در کنترل revision ردیابی می شود و بسیاری از آنها مستقر (deploy) می شوند.

یک اپلیکیشن مبتنی بر فاکتور های دوازده گانه، همواره توسط یه سیستم کنترل ورژن ردیابی می شود، مانند گیت ،  Mercurial, یا  Subversion، یک کپی از پایگاه داده ردیابی revision به عنوان مخزن کد در نظر گرفته می شود، اغلب به code repo یا repo تنها خلاصه می شود.

یک codebase هر repo تنهایی می باشد (در یک سیستم کنترل revision متمرکز مانند subversion)، یا هر مجموعه ای از repo هایی که root commit را به اشتراک گذاشته اند(در سیستم های کنترل revision غیر متمرکز مانند گیت).

همیشه یک همبستگی (correlation) یک به یک بین codebase و app وجود دارد:

  • اگر چندین codebase وجود دارد، این یک app نیست، یک سیستم توزیع شده است (distributed system). هر مولفه (component) در سیستم توزیع یک app می باشد و هر کدام به تنهایی می تواند با دوازده فاکتور مطابقت داشته باشد.
  • چندین app که کد یکسانی را به اشتراک می گذارند نقض دوازده فاکتور هستند.راهکار در اینجا این است که کدهای مشترک را درون کتابخانه ها (libraries) فاکتور کنید که بتواند در dependency manager گنجانده شود.

به ازای هر app فقط یک codebase وجود دارد، اما چندین استقرار(deploy) از یک app وجود دارد. یک استقرار (deploy) اجرا کردن یک نمونه از app می باشد. معمولا یک سایت production است و یک یا چند سایت stage. علاوه بر این، هر توسعه دهنده یک کپی از app که در محیط توسعه لوکال خودش اجرا شده است را دارد.

codebase در همه deployها یکسان است، اگرچه ممکن است ورژن های مختلفی از آن در هر استقرار فعال شده باشند. برای مثال، یک توسعه دهنده تعدادی commitداشته است که هنوز روی staging مستقر نشده است، staging تعدادی commitدارد که روی production هنوز مستقر نشده است. اما همه آنها یک codebase یکسانی را به اشتراک می گذارند، بنابراین آنها به عنوان استقرارهای مختلف یک برنامه قابل شناسایی می شوند.

بهترین ابزارهای مدیریت ورژن:

۲ – Dependencies – وابستگی ها

وابستگی ها را با صراحت اعلام و جدا کنید.

اکثر زبان های برنامه نویسی، یک سیستم بسته بندی برای پشتیبانی توزیع کتابخانه ها ارائه می دهند، مانند CPAN برای زبان Perl یا Rubygems برای زبان Ruby. کتابخانه های نصب شده از طریق سیتم های بسته بندی (packaging system) میتوانند در سراسر سیستم نصب شوند (به عنوان site-package شناخته می شوند) یا درون دایرکتوری حاوی app نصب شوند (به عنوان vendoring یا bundling شناخته می شوند).

یک app دوازده عاملی (twelve-factor) هرگز به وجود ضمنی بسته های سیستمی متکی نیست. تمام وابستگی ها را از طریق یک مانیفست اعلام وابستگی، اعلام می کند. علاوه بر این، از یک ابزار جداسازی وابستگی در طول اجرا استفاده می کند تا اطمینان حاصل کند هیجچ وابستگی ضمنی از اطراف سیستم نشت نمی کند.مشخصات وابستگی کامل و صریح به طور یکسان برای تولید و توسعه اعمال می شود.

برای مثال، Bundler برای Ruby مانیفست با فرمت Gemfile را برای اعلان واستگی پیشنهاد می کند و bundle exec را برای dependency isolation پیشنهاد می کند. در پایتون دو ابزار مختلف برای انجام این مراحل وجود دارد، Pip برای اعلان(declaration) و Virtualenv برای ایزوله سازی استفاده می شود. حتی زبان C نیز Autoconf را برای اعلان و استفاده از static linking را برای فراهم کردن ایزوله سازی dependencyها استفاده می کند.

مهم نیست که از چه زنجیره ابزاری استفاده می شود، اعلان وایستگی ها (dependency declaration) و ایزوله سازی (isolation) باید همیشه باهم انجام شوند. فقط یکی از آنها برای برآورده کردن دوازده فاکتور، کافی نیست.

کی از مزایای اعلام وابستگی صریح این است که راه اندازی را برای توسعه دهندگانی که تازه وارد برنامه شده اند، ساده می کند. توسعه دهنده جدید، می تواند codebase مرتبط با app را check-out کند روی سیستم (کامپیوتر، لپتاپ) خودش، و فقط نیاز به زمان اجرای زبان برنامه نویسی و مدیریت dependencyها برای نصب وابستگی های مورد نیاز دارد.

برنامه های دوازده عاملی نیز به وجود ضمنی هیچ ابزار سیستمی متکی نیستند. به عنوان مثال می توان به ارسال به ImageMagick یا curl اشاره کرد. در حالی که این ابزارها ممکن است در بسیاری از سیستم‌ها یا حتی اکثر سیستم‌ها وجود داشته باشند، هیچ تضمینی وجود ندارد که در همه سیستم‌هایی که برنامه ممکن است در آینده اجرا شود وجود داشته باشند، یا اینکه نسخه موجود در سیستم آینده با برنامه سازگار باشد یا خیر. اگر برنامه نیاز به پرداخت به یک ابزار سیستمی داشته باشد، آن ابزار باید در برنامه عرضه شود.

  • Composer: (PHP, Packagist, composer.json, composer.lock)
  • Gradle: (Java, Maven Central, build.gradle, gradle/dependency-locks/*.lockfile)
  • Node Package Manager (NPM): (NodeJS, NPM, package.json, package-lock.json)
  • Yarn: (NodeJS, NPM, package.json, yarn.lock)
  • Bundler: (Ruby, RubyGems, Gemfile, Gemfile.lock)
  • Pipenv: (Python, PyPI, Pipfile, Pipfile.lock)

۳ – config – کانفیگ

دخیره کردن کانیفیگ در محیط (environment) برنامه نویسی

کانفیگ یا پیکربندی app هر چیزی است که احتمالا بین استقرارها متفاوت است (staging، production، developer environment و غیره) که شامل:

  • مدیریت منابع به پایگاه داده، Memcached و دیگر سرویس های backend
  • اعتبارنامه خدمات خارجی مانند آمازون s3 یا توییتر
  • مقادیر به ازای هر استقرار، مانند نام میزبان- hostname متعارف برای استقرار

اپلیکیشن ها گاهی اوقات کانفیگ را به صورت ثابت در کد ذخیره می کنند. این یک نقض برای فاکتورهای دوازده گانه می باشد، که نیاز به جداسازی دقیق بین پیکربندی (config) و کد دارد. کانفیگ به صورت قابل توجهی بین استقرار ها متفاوت است اما کد اینطور نیست.

یک تست litmus برای اینکه app تمامی کانفیگ ها را به درستی خارج از کد کرده است یا خیر این است که می توان basecode را در هر لحظه و بدون به خطر انداختن هیچ اعتباری به صورت متن باز (open-source) تبدیل کرد؟

توجه داشته باشید که تعریف انجام شده از «config» شامل کانفیگ های داخلی اپلیکیشن نمی شوند، مانند config/routes.rb در زبان Railsیا طریق ارتباط ماژ>ل ها در Spring. این نوع از کانفیگ در بین استقرارها متفاوت نیست و درنتیجه بهتر است که داخل کد انجام شود.

رویکردی دیگر برای config ، استفاده از کانفیگ فایل هایی است که در revision control بررسی نمی شوند، مانند config/database.yml در زبان Rails . این یک پیشرفت بزرگ نسبت به استفاده از ثابت‌هایی است که در code repo (مخزن کد) بررسی می‌شوند، اما همچنان دارای نقاط ضعفی است: خیلی راحته که اشتباهه فایل کانفیگ را در repo قرار داد، این تمایل وجود دارد که فایل های کانفیگ در مکان های مختلف با فرمت های مختلف پراکنده شوند، که دیدن و مدیریت تمام کانفیگ ها در یک مکان را دشوار می‌کند. علاوه بر این، این فرمت ها معمولاً مختص زبان یا چارچوب(framework) هستند.

twelve-factor app کانفیگ را در متغیر های environment ذخیره می کند (اغلب به env vars یا env کوتاه می شوند). متغیرهای Env به راحتی بین استقرارها بدون تغییر هیچ کدی قابل تغییر هستند.برخلاف فایل های پیکربندی، احتمال کمی وجود دارد که به طور تصادفی در مخزن کد بررسی شوند. و برخلاف فایل‌های پیکربندی سفارشی (custom log file)، یا مکانیزم‌های پیکربندی دیگر مانند ویژگی‌های سیستم جاوا، آنها یک استاندارد زبان و سیستم عامل هستند.

از دیگر جنبه های مدیریت فایل کانفیگ، گروه بندی می باشد. گاهی اوقات برنامه ها کانفیگ ها را در گروه های نامگذاری شده ای (اغلب environment نامیده می شوند) پس از استقرار های خاص، نامگذاری می شوند، مانند محیط های development، test و productionدر زبان Rails. این روش به صورت تمیز مقیاس نمی شود: با ایجاد تعداد بیشتری از استقرار ها، نام های جدید environment ضروری می باشد، مانند staging یا qa. همانطور که پروژه بزرگتر می شود، توسعه دهنده ها ممکن است محسط های خاص خودشان را اضافه کنند، مانند joes-staging، که منجر به انفجار ترکیبی از کانفیگ ها می شود که مدیریت استقرار app را بسیار شکننده می کند.

در یک برنامه دوازده عاملی، env vars کنترل‌های دانه‌ای هستند که هر کدام کاملاً متعامد با سایر env vars هستند. آنها هرگز به عنوان “محیط” گروه بندی نمی شوند، بلکه به طور مستقل برای هر استقرار مدیریت می شوند. این مدلی است که به آرامی افزایش می یابد زیرا برنامه به طور طبیعی در طول عمر خود به تعداد بیشتری گسترش می یابد.

تعدادی از ابزارهای مدیریت پیکربندی برای اپلیکیشن شما:

مرجع

برای نوشتن ۱۲ فاکتور اپلیکیشن از مرجع اصلی این موضوع یعنی وب سایت با همین عنوان، 12factor.net استفاده کردم

دوازد فاکتور اپلیکیشن و توسعه نرم افزار به عنوان سرویس

فاکتورهای ۱ الی ۳ از فاکتور های دوازدهگانه

فاکتورهای ۴ الی ۶ از فاکتور های دوازدهگانه