تقاطع زیرساخت و تیم توسعه در کیفیت نرم‌افزار

مقدمه

ما در همروش، به شرکت‌های مختلفی خدمات زیرساختی ارائه می‌کنیم. مشتریان ما، تیم‌های توسعه‌ای هستند که نرم‌افزارشون رو با زبان و معماری دلخواه خودشون پیاده‌سازی، و در بستر ما مستقر می‌کنند. در این مطلب، تلاش می‌کنیم برخی از مواردی که طبق تجربه رعایتشون به افزایش کیفیت نهایی سرویس کمک می‌کنه رو بررسی کنیم. سعی می‌کنیم این موارد رو در قالب تعدادی سؤال در حوزه‌های مختلف بیان کنیم و بررسی مختصری بر تاکتیک‌های ممکن برای برآورده کردن این نیازها داشته باشیم.

کیفیت در معماری

سؤال: آیا مؤلفه‌ها تا حد ممکن stateless هستند؟

انگیزه: مؤلفه‌هایی که در خود state ذخیره نمی‌کنند، معمولاً ساده‌تر مدیریت می‌شوند. برای نمونه، این مؤلفه‌ها می‌توانند به راحتی تکثیر، جابجا و یا متوقف شوند، بدون آن که در عملکرد عادی سیستم اختلالی ایجاد کنند.

تاکتیک‌ها:

  • استفاده از s3 به جای فایل‌سیستم: گاهی توسعه‌دهنده برای ذخیره‌سازی محتوای کاربری (مانند عکس پروفایل) از فایل‌سیستم استفاده می‌کند. معمولاً با تغییرات محدودی، امکان استفاده از (پروتکل) s3 جهت نگهداری و دسترسی به فایل‌ها وجود دارد.
  • استفاده از کش‌های خارجی (مانند redis) جهت ذخیره‌سازی session

کیفیت در مصنوعات (Artifacts)

سؤال: آیا امکان دسترسی به نسخه‌ی قدیمی‌تر محصول به سادگی فراهم است؟

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

تاکتیک‌ها:

  • استفاده از سیستم‌های کنترل نسخه: مانند گیت
  • استفاده از ابزارهای مختص زبان جهت مدیریت بسته‌ها: مانند npm, pip, gradle
  • استفاده از داکرفایل جهت ثبت نحوه‌ی ساخته شدن ایمج داکر
  • ذخیره و نگهداری نسخ مختلف از ایمج‌های داکر


سؤال: آیا سرعت ساخت/انتقال مصنوعات قابل قبول است؟

  • تولید مصنوعات به صورت مینیمال: جلوگیری از نصب بسته‌های غیرضروری، و استفاده از base imageهای مناسب این کار، مانند alpine
  • بهره‌گیری از امکانات caching: توسعه‌دهنده‌ها می‌توانند با استفاده از امکانات caching موجود در زیرساخت CI موجود، گام‌های تکراری را skip کنند و سرعت بیلد را افزایش دهند. کاری که انجام نشود، کمتر از هر کاری طول می‌کشد!

کیفیت در استقرار (Deployment)

سؤال: آیا نرم‌افزار، امکان بروزرسانی بدون وقفه را پشتیبانی می‌کند؟

تاکتیک‌ها:

  • پیاده‌سازی علائم حیاتی: به جهت انجام rolling update و جلوگیری از بروز وقفه در هنگام اعمال آن، نیاز هست تا مؤلفه‌ها وضعیت آمادگی و حیات خود را به نحوی اعلام کنند. در کوبرنیتیز، این موضوع از طریق مکانیزم readinessProbe و livenessProbe صورت می‌گیرد.
  • اعمال data migration به صورت تدریجی


سؤال: آیا امکان استقرار چند نسخه از نرم‌افزار به صورت هم‌زمان وجود دارد؟

تاکتیک‌ها:

  • خودداری از hardcode کردن مقدارهای وابسته به محیط (نام دامنه، مختصات دیتابیس، ...)
  • رویکرد infrastructure-as-code در استقرار سامانه: معمولاً راه‌اندازی یک محیط استقرار و یا اعمال تغییرات در آن، می‌تواند همراه با خطاهایی باشد. اگر چه این خطاها (همانند خطاهای توسعه‌ی نرم‌افزار) اجتناب‌ناپذیر هستند، امکان جلوگیری از تکرار آن‌ها وجود دارد.

کیفیت در مشاهده (Observability)

سؤال: در صورت بروز مشکل، آیا اطلاعات کافی جهت پیگیری این مشکل وجود دارد؟

انگیزه: معمولاً در دسترس بودن این اطلاعات کمک زیادی به بررسی و کشف علت وقوع خطاهای سیستم می‌کند، و نبود این اطلاعات، ساده‌ترین باگ‌ها را به مجموعه‌ای از گمانه‌های بدون پاسخ تبدیل خواهد کرد.

تاکتیک‌ها:

  • ثبت خطاها با استفاده از sdkهای مخصوص این کار (مانند sentry)
  • ثبت لاگ‌های مناسب، و تجمیع آن‌ها
  • ارائه‌ی متریک‌های مناسب، و تجمیع آن‌ها

کیفیت در مقیاس‌پذیری (Scalability)

سؤال: آیا گلوگاه‌های سیستم در حالت عملیاتی شناسایی شده؟

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

تاکتیک‌ها:

  • شبیه‌سازی رفتار کاربران و اجرای تست بار

جمع‌بندی

اگر چه بستر استقرار نقش زیادی از فراهم آوردن کیفیت مناسب سرویس را به عهده دارد، اما رعایت برخی نکات کم‌هزینه در هنگام توسعه‌ی محصول، تفاوت چشم‌گیری را در کیفیت سرویس نهایی به همراه خواهد داشت.