چگونه با نیروی ریموت کار کنیم؟

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

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

برای حل مشکلات این سیستم باید یکسری فرایندهای درون تیمی درست کنیم. من چندتاشون رو می‌نویسم ولی اینها یکسری رفتارهای کلی هست و برای درون شرکت خودتون باید اینهارو بومی سازی کنید.

  • جلساتتون رو حتما به صورت تصویری برگزار کنید. این تصویری دیدن همدیگه باعث میشه بچه‌ها حس تعلق بیشتری باهم داشته باشن.
  • اگر از متد اسکرام استفاده می‌کنید احتمالا جلسات دیلی دارید، بیاید قبل جلسات دیلی با بچه‌های ریموت یک مقداری راجب چیزهایی غیر کار صحبت کنید. موضوعاتی مثل اب‌و‌هوا، مسائل انسانی فردی یا هرچیزی که هرروز با بقیه همکاران داخل شرکت خودتون حرف می‌زنید.
  • یکی از ابزارهای مهم ارتباط درون تیمی اسلک هست. توی اسلک به ازای هر epic یک چنل مخصوص داشته باشید و هرکسی که به اون epic مربوط هست رو داخلش اضافه کنید. میتونید برای راحتی کار حتی id جیرای اون epic رو هم اول چنل اضافه کنید.
  • یک سیستم afk راه بندازید. این سیستم اینجوریه که اگر یکی از بچه‌ها خواست برای چند دقیقه نباشه توی یکی از چنل‌های اسلک که مخصوص این کار درست کردیم میاد میگه من برای n دقیقه نیستم.
    اینجوری بقیه بچه‌ها میدونن که هرکسی کی هست و کی نیست. از طرفی باعث میشه ادم‌ها خودش، خودشون رو تِرَک کنن که چقد حواسشون جمع بوده و سرکار بودن و چقدر نبودن.
  • کلا جلسات دیلی برای این نیست که بخوایم از ادم‌ها جواب پس بگیریم. برای اینه که بچه‌ها اگر مانعی دارن اون مانع رو مطرح کنن و بقیه در جریان باشن تا اگر می‌تونن کمکی بکنن
    ۳تا سوال رو باید جواب بدیم:‌ اول اینکه امروز قراره چیکار بکنی – دوم اینکه اگر مانعی برای کارای امروزت پیش‌بینی میکنی بگی – و سوم اینکه دیروز چه‌کار کردی و اگر اونجوری که میخای پروگرس نداشتی چه چیزی باعث‌ش بوده
scrum team
  • یادمون باشه اسکرام اومده که تیم، خودش خودش رو مدیریت کنه. اومده که تیم‌های خود مدیریت کن درست کنه.
    ما اگر تسک‌هارو تا میتونیم در حد امکان ریز کنیم به شکلی که هر تسک فقط برای یک روز باشه، دوتا دستاورد مهم داریم: اول اینکه اگر کاری اون طوری که می‌خوایم پروگرس نداشته باشه زودتر اینو می‌فهمیم و دوم اینکه وقتی توی جلسات دیلی همه یک تسک رو تموم کردن و رفتن سراغ تسک دوم، بچه‌هایی که عقب هستن و نتونستن تسک‌شون رو تموم کنن حسی میده که سریع تر تسک‌م رو تموم کنم تا به بقیه دوستام برسم
  • سعی کنیم چالش‌هارو خیلی شفاف بگیم و از هم تشکر کنیم که چالش رو به ما یاداوری کردن.
  • حتما راه ارتباطی جایگزین داشته باشیم و این خیلی شفاف باشه
    مثلا اگر فلانی بعد ۱۵ دقیقه توی اسلک جواب نداد بهش اسمس بزنیم و بازهم اگر جواب نداد بعد زنگ بزنیم یا از این قبیل گاین‌لاین ها
پومودورو

  • و در اخر حتما حتما از تکنیک پومودورو استفاده کنیم.

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

اگر شماهم نکته‌ای داشتید خوشحال میشم توی کامنت‌ها برام بنویسید.

چگونه برنامه cloud-native بنویسیم؟

برنامه‌های cloud-native برنامه‌هایی هستن که انعطاف پذیری بالایی دارن، میشه خیلی سریع تغییرات‌مون رو روشون اعمال کنیم و می‌تونیم اون‌هارو scale کنیم.

تعریف خود CNCF رو از داکیومنت رسمی‌ بخونید:

Cloud-native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach

These techniques enable loosely coupled systems that are resilient, manageable, and observable. Combined with robust automation, they allow engineers to make high-impact changes frequently and predictably with minimal toil

یک روشی که تقریبا به طور گسترده‌ای همه پذیرفتن برنامه‌های cloud-native رو طبق اون اصول بنویسن 12factor هست. این مجموعه، اصول و روش‌هایی رو توصیف می‌کنه که توسعه دهنده‌ها برای ساخت برنامه‌های بهینه شده برای cloud باید اونهارو رعایت کنن. و توجه ویژه‌ای روی قابلیت جابه‌جایی و اتومیت کردن برنامه داره.

برنامه‌های نوشته شده با این قواعد به سرعت می‌تونن deploy و scale بشن و خیلی سریع تغیرات‌شون رو به دست کاربر برسونن.

بیاید ببینیم قواعد 12factor چیا هستن:

۱. Code Base : مایکروسرویس شما به هرشکلی که می‌خواد باشه باید روی یک کدبیس قرار بگیره و با version controlها مدیریت بشه که این کدبیس می‌تونه روی محیط های مختلف deploy بشه.
۲. Dependencies : هر مایکروسرویس ایزوله هست و وابستگی‌های خودش صریحا توی یک فایل مشخص می‌کنه.
۳. Configurations : همه configها به خارج کد اصلی منتقل می‌شن و توی env ذخیره می‌شن.
۴. Backing Services : منابع جانبی مورد نیاز به صورت جداگانه اجرا می‌شن و از طریق URL در دسترس هستن.
۵. Build, Release, Run : مراحل build و release و run کاملا از هم جدا هستن. هرکدوم باید با یک unique id برچسب گذاری بشن تا بتونیم راحت role back کنیم.
۶. Processes : برنامه باید به صورت stateless باشد یعنی یک رکوئست هیچ ارتباطی با رکوئست قبلی نداشته باشد و دیتاها روی backing serviceهای متصل شده ذخیره بشن.
۷. Port Binding :‌ هر مایکروسرویس باید روی یک پورت شبکه سرویس‌دهی کند.
۸. Concurrency : مایکروسرویس باید بتونه بر اساس تعداد پراسس‌ها scale بکند.
۹. Disposability :‌ مایکروسرویس ها باید به راحتی انهدام بشن تا ورژن جدید به سرعت بالا بیاد.
۱۰. Dev/Prod Parity : محیط‌ توسعه باید تا حد امکان با محیط staging و production شبیه باشد.
۱۱. Logging : مایکروسرویس‌ها باید لاگ هاشون رو بریزن روی stdout.
۱۲. Admin Processes : تسک‌های ادمین باید به صورت یک‌بار مصرف و روی پروسس جدا اجرا بشن و روی برنامه اصلی نباشن.

البته توی کتاب Beyond the Twelve-Factor App علاوه بر توضیح کامل ۱۲فاکتور، ۳فاکتور دیگه رو هم برای برنامه‌های مدرن امروزی مطرح می‌کنه.

۱۳. API First
۱۴. Telemetry
۱۵. Authentication/ Authorization

علاوه بر قواعد 12factor، چندین تصمیم مهم دیگه در زمینه طراحی وجود دارد که زمان ساخت برنامه‌های cloud-native باید به اونا توجه کنیم.

Communication
اینکه front-end چجوری با back-end ما ارتباط برقرار می‌کنه؟ اجازه می‌دیم که به طور مستقیم وصل شه به سرویس‌های back-end؟ یا ممکنه یک سرویس دیگه به اسم api gateway داریم که برنامه‌ها برای کنترل پذیری و امنیت و قابل انعطاف بودن با اون ارتباط برقرار می‌کنن؟
یا مثلا back-end سرویس‌ها چطور باهم ارتباط برقرار می‌کنن؟ اجازه می‌دیم که با http متد باهم ارتباط بگیرن؟ یا از message queue ها استفاده می‌کنیم؟

Resiliency
توی معماری مایکروسرویس اگر وضعیت یک سرویس down شد، چه اتفاقی می‌افته اگر سرویس B روی شبکه جوابی از سرویس A دریافت نکنه؟ یا چه اتفاقی می‌افته اگر سرویس C به صورت موقت از دسترس خارج بشه و سرویس‌های دیگه که با اون تماس می‌گیرن مسدود بشن؟

Distributed Data
اینکه هر مایکروسرویس دیتا‌ی خودش رو خودش ذخیره می‌کنه و با یک اینترفیس عمومی با بقیه ارتباط میگیره. توی این حالت هر مایکروسرویس چجوری با بقیه ارتباط می‌گیره و دیتایی که می‌خواد رو بدست میاره؟

پ.ن: این مطلب برداشتی هست از Defining cloud native

چرا Cloud-Native برنامه بنویسیم؟

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

شما این شغل رو قبول می‌کنید و پس از چند هفته توی یک جلسه طراحی قرار می‌شود یک سایت eCommerce طراحی کنید که از نظر نرم افزار توانایی رقابت با بقیه رقبای تراز اول رو داشته باشه.

شما چجوری می‌سازید؟

اگر مثل متدهای ۱۵ سال پیش بخواهید بسازید، شبیه به شکل زیر خواهید ساخت.

Traditional monolithic design
Traditional monolithic design

یک برنامه که یک هسته بسیار بزرگ نرم‌افزاری شامل احراز هویت، دسته بندی محصولات،‌ ثبت سفارش،‌سبد خرید و خیلی امکانات دیگه رو داخل خودش جا داده و با یک دیتابیس بزرگ relational برای ذخیره دیتا ارتباط برقرار می‌کنه.

تبریک! شما یک برنامه مونولیتیک ساختید.

همه چیز اینطور که می‌گن بد نیست. برنامه های مونولیتیک یک سری مزایای مشخص دارن. اگر بخوایم به چندتا مزیت سرراستش اشاره کنیم:

  • بیلد آسان
  • تست آسان
  • دیپلوی آسان
  • نگهداری آسان

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

با این حال شما بعد از مدتی احساس ناراحتی می‌کنید. شما می‌بینید که برنامه از کنترل‌تون خارج شده. با گذشت زمان این حس شدیدتر می شود و در نهایت وارد حالتی می‌شوید که به چرخه ترس معروف است.

  • این برنامه به قدری بزرگ شده که کسی قادر به درک کامل‌ش نیست.
  • تغییر دادن این برنامه ترسناکه،‌ هر تغییر عوارض جانبی زیادی داره.
  • اضافه کردن فیچر جدید یا حل یک باگ خیلی سخت، زمان‌بر و پیاده‌سازی‌ش پرهزینه هست.
  • یک تغییر کوچیک نیازمند بیلد و دیپلوی کل برنامه هست.
  • یک کامپوننت unstable می‌تونه منجر به کرش کردن کل برنامه بشه.
  • دیگه از تکنولوژی‌های جدید یا فریم‌ورک های جدید نمیشه استفاده کرد.
  • متدولوژی اجایل روی این برنامه پیاده سازی نمی‌شه.
  • در نهایت مشاوران به شما می‌گویند این برنامه رو باید از اول بنویسید.

راهکار چیه؟

بسیاری از شرکت‌ها برای فرار از این چرخه ترس، شروع به ساخت برنامه‌ها به صورت cloud-native کردن. شکل زیر یک سیستم با استفاده از تکنیک‌ها و متد‌های cloud-native رو نشون میده.

Cloud-Native Design
Cloud-native design

ببینید چطور برنامه شکسته شده به سرویس‌های کوچک و کاملا ایزوله. هر سرویس مستقل هست و کدها، دیتاها و وابستگی‌های خودش رو توی یک محیط ایزوله محصور می‌کنه. به‌جای یک دیتابیس بزرگ رابطه‌ای، هر سرویس دیتابیس خودش رو داره که حتی نوع این دیتابیس هم بر اساس نیاز می‌تونه متفاوت باشه. بعضی سرویس‌ها نیاز به دیتابیس‌های SQLبیس دارن و بعضی‌ها می‌تونن از NoSQLها استفاده کنن. تمام ترافیک به وسیله یک API Gateway به سرویس مورد نظر می رسه. اگر یک سرویس کرش کرد فقط همون بخش سیستم از کار میوفته. و از همه مهم‌تر این برنامه خیلی راحت اسکیل میشه و خیلی راحت میشه انتظار availability رو ازش داشت.

پ.ن: این مطلب برداشتی هست از Introduction to cloud-native applications