چرا هر پروژه نرمافزاری به یک سند معماری نیاز داره؟
تا حالا شده یه پروژه نرمافزاری بسازین و وسطای راه یادتون نیاد چرا فلان تصمیم رو گرفتین؟ یا وقتی یه نفر جدید میاد تو تیم، باید کلی وقت بذارین تا براش توضیح بدین این سیستم چطوری کار میکنه؟ یا بعد از چند ماه دوباره به کدها نگاه کنین و هیچی نفهمین چرا اون بخش رو اینطوری نوشتین؟ خلاصه اینکه، اگه این سوالها برات آشنا هستن، یعنی وقتشه یه سند معماری نرمافزار درست و حسابی داشته باشی.
اول از همه ببینیم خود معماری نرمافزار (Software Architecture) چیه؟ چند تا تعریف داره ولی میتونیم بگیم تصمیمات مهم و کلیدی طراحی هستند که باید خیلی زود و در همون اوایل پروژه گرفته بشن و در کل طراحی و توصیف کامپوننتهای اصلی سیستم و ارتباطات بین آنها رو به صورت high level برای فهم مشترک بین افراد فنی (و تا حدی غیر فنی!) تیم نشون میده که حالا تو این پست قراره دو دیدگاه ۴+۱ ویو و C4 رو مورد بررسی قرار بدیم و کاملترش کنیم.
سند معماری نرمافزار (SAD)، معماری یک سیستم رو در سطح تصمیمات فنی و سطح بالا نشون میده. این سند باید از دید کلان و معماری نوشته بشه (نه در سطح جزئیات). همچنین باید در طول فرایند توسعه هم آپدیت نگه داشته بشه.(زنده باشه) کلا سند معماری با توجه به دلایلی که جلوتر هم میگیم خیلی مهمه و نبودش یک Technical Debt محسوب میشه که در آینده هم اثر منفی داره.
میتونیم این سند رو به دو بخش اصلی و مهم تقسیم کنیم که در ادامه قسمتهای هر بخش رو هم بیشتر توضیح میدیم:
فضای مسئله یا problem space که شامل نیازمندیهای اصلی (functional و non-functional)، بیان مسئله و Architecturally Significant Requirements خواهد بود. (شامل بخشهای مقدمه، نمای موارد کاربرد و ویژگیهای کیفی)
فضای راهحل یا solution space که شامل راهحل یا طراحی جواب برای پوشش نیازمندیها و همچنین توصیف تصمیمات کلان و مرتبط به معماری خواهد بود. (شامل بخشهای نمای منطقی، استقرار، پردازه، توسعه، تست، لاگ، پایش و …)
اهمیت و فواید مستندسازی سند معماری نرمافزار
چون یک سند بالا دستیه که تصمیمات فنی، کلیدی و تاثیرگذار رو داخل خودش داره و این تصمیمات مهم هستند باید برای ذینفعان حال و آینده شفاف و مورد توافق باشه پس مستند کردنش خیلی مهمه.
یکی از موارد مهم اینه که این سند ذینفعهای زیاد و متنوعی داره و باید طوری نوشته بشه که تمام این ذینفعان بتونن بخونن، ارزیابی کنن و نظر بدن. (عملا یک رسانه تعاملیه بین معمار و بقیه ذینفعها) هم شامل ذینفعهای فنی مثل طراح، برنامهنویس، تیم توسعه و … هم غیر فنی مثل کارفرما، مدیرعامل و …
کاهش وابستگی به افراد (یا همون Bus Factor که یعنی چقدر از افراد تیم باید برن زیر اتوبوس تا پروژه منحل بشه و دیگه کسی از پروژه سر در نیاره 😂)
تسهیل امکان ارزیابی و مشورت معماری
آشنایی و آموزش افراد جدیدی که به تیم اضافه میشن (یعنی تسهیل و تسریع فرایند onboarding فرد جدید)
صریح کردن دانش ضمنی معمار (یا مدیران و رهبران ارشد)
مبنای عمل تیم توسعه هم دقیقا همین سنده. (در زمانهای ریفکتور یا تغییراتی در معماری باید سند رو هم آپدیت کنن)
نکته ۱: سند معماری نرمافزار با فرایندهای agile تعارضی نداره و در واقع این سند باید خیلی مختصر، موجز، مفید و چابک تهیه، نگهداری و بروزرسانی بشه تا هم روابط بین کلی ذینفع رو تسهیل کنه و همچنین خودش باعث بشه که فرایند چابکتر بشه. (مثل RUP و نمودارهای عجیب و غریب UML نباید افراط داشته باشه.)
نکته ۲: برای هر سامانه نرمافزاری میتونیم سند معماری ارائه بدیم ولی باید توجه داشته باشیم که قالب سند خیلی مهمه و بهتره در یک سازمان با چندین پروژه قالبهای مشترکی داشته باشیم. (اعضای تیم راحتتر بتونن بین پروژههای مختلف جابجا بشن.) این سند باید خیلی high level مثلا در سطح کامپوننت باشه و خوبه از ابرازهای wiki مثل confluence استفاده بشه چون برای کار تیمی مناسبترن.
بهتره داخل این سند نماهای معماری یا همون Architectural View ذکر بشن. این یعنی چی؟ مثل بدن ما یا نقشه ساختمان که ویوهای متفاوتی داره، معماری نرمافزار رو هم از نماهای مختلفی میشه تفسیر کرد. (یکی از این مدلها ۴+۱ ویو هست که کافی نیست!) حالا تو این قسمت انواع ویوها رو مورد بررسی قرار میدیم که بهتره داخل سند معماری بیان.
مقدمه (فضای مسئله): فصل کوتاهی که همون اول میاد و بهتره به صورت فهرستوار شامل مواردی همچون توصیف کوتاه از پروژه، محدوده یا scope، تعاریف و واژهنامه، اهداف کلان معماری، محدودیتها، استانداردها و مراجع باشه. (نیازمندیها = کارکردی + ویژگیهای کیفی + محدودیتها)
نمای موارد کاربرد (فضای مسئله): شامل use case ها، سناریوها و کارکردهای اصلی سامانه هستند. برای مثال در این بخش در مورد نیازهای کلان کارکردی، توجه به تناسب معماری با نیامندیها و توصیف این موارد در قالب usecase diagram یا جدولی خواهد بود. در این بخش باید دو موجودیت رو بشناسیم یکی کنشگر یا actor که به دو دسته تقسیم میشن یکی اکتور انسانی و یکی سیستمی که میان آنها روابطی هم میتونه وجود داشته باشه (مثل generalization) و مورد دیگه موارد کاربرد یا usecase که شامل شناسه، عنوان، شرح مورد کاربرد و اکتور خواهند بود.
ویژگیهای کیفی (Quality Attribute) (فضای مسئله): یک ویژگی قابل اندازهگیریه که نشون میده سیستم چقدر خوب کار میکنه مانند availability ، performance Scalablity ، security ، modifiability ، interoperability یا testability. برای درج این موارد داخل سند باید جدولی از عنوان ویژگی کیفی، معیار سنجش و مقدار یا بازه مطلوب در سناریوهای مختلف داشته باشیم. (معمولا در SLA ها میان) همچنین سناریوها به ازای source و محیط یا بافتار خاص بیان میشن. (بخوام یک سناریو رو مثال بزنم مثلا "وقتی مدیر ارشد در ساعات اوج با اینترنت موبایل وارد داشبورد گزارشها میشه، سیستم باید طی حداکثر ۵ ثانیه نسخه سبکتری از داشبورد رو نمایش بده و بارگذاری کامل نمودارها رو به صورت lazy انجام بده." در این مثال، سورس، گزارشگیری توسط مدیر ارشد و بافتار، ساعت اوج هست.)
نکته ۳: راهحل باید حتما در کنار نیازمندیهای مسئله مورد ارزیابی قرار بگیره و بررسی بشه. (در واقع ممکنه یک راهحل برای مسئلهای مناسب و برای دیگری نامناسب باشه)
نمای منطقی (فضای راهحل): بخشی از سند معماریه که یک نمای مفهومی سطح بالا از معماری رو ارائه میکنه و شامل توصیف Building Block ها، اجزای اصلی معماری (مولفهها، زیرسیستمها، سرویسها) و ارتباطات بین آنها خواهد بود. (مثلا در یک معماری میکروسرویس، سرویسهای مختلف و نحوه ارتباطشون رو نشون میدیم.)
نمای استقرار (Physical View یا Deployment View): توصیف معماری از دید محیط اجرایی، سختافزاری، فیزیکی در محیط بهرهبرداری مثلا فهرست سرورها و محیطهای اجرایی مانند ماشینهای مجازی و docker ها و … که این شامل توضیحاتی در مورد جدول استقرار، فرایند نصب، زیرساختها و مجازیسازی خواهد بود.
نمای پردازه (Process View): گزارشی در مورد برنامههای اجرایی (Executables) که در سرورها و محیط عملیاتی اجرا میشن. (مثل تامکت، دیتابیس اوراکل و برنامه مانیتورینگ) مثلا توصیف وضعیت نرمافزار در زمان اجرا شامل خود پردازهها، سروری که روش ران میشن و ارتباطات بین اونها(دغدغهمون Concurrency, distribution, performance, scalability, … هست.)
نکته ۴: در برخی سیستمها ممکنه محل پردازهها روی سرورهای مختلف جابجا شه و باید با پیچیدگی بیشتری این موارد بیان بشه. (مثلا در سیستمهای کوبرنتیزی پادها پس از ریاستارت ممکن است رو یه نود دیگهای بیان بالا)
نمای پیادهسازی (implementation view یا development view): توصیف معماری از منظر پیادهسازی و برنامهنویسی. یعنی توصیف Development-time Modules شامل ساختار پروژه و زیرپروژهها، تصمیمات مربوط به برنامهنویسی و توسعه، توصیف package ها و لایههای پیادهسازی.
نکته ۵: خوبه که نماها رو از چند جنبه بررسی کنیم و تقاطع بدیم. (همونطور که در ادامه هم میگیم)
4+1 view model
تحقق برخی موارد کاربرد (use case realization): چگونگی تحقق یک مورد کاربردی کلیدی (ساختار پویا رو نشون میده و میگه که هر ماژول کیو کال میکنه، کجا میره و از اینجوری داستانا شامل روند و ترتیب و اینا مثل sequence diagram) به صورت کلی چند مورد رو توصیف کنیم کافیه.
نمای تست (Test View): معماری تست پروژه رو بیان میکنیم. (بیان رویکردها و تصمیمات اصلی) به خصوص جنبههایی از تست که روی معماری اثر دارن (مثلا A/B Testing)، بیان انواع، سطوح، ابزارهای تست و همچنین رویکردها. (unit, load test)
نمای لاگ (Log View): ثبت رخدادها در حین اجرای نرمافزار شامل شرح ساختار و فرمت (مثلا سطوح لاگ از Debug گرفته تا Fatal)، توصیف سیستم مدیریت لاگ مثل ELK، نحوه و رویکرد استفاده از لاگ، در اوردن kpi و مثلا چیزهایی بیشتری اگر سیستم نیاز داره مثلپشتیبانی از Distributed Tracing.
نمای پایش (monitoring view): توصیف معماری پایش (وضعیت سامانه نرمافزاری) برای مثال پایش مداوم تروپوت و latency و همچنین میزان استفاده از cpu و ram. مثلا توصیف ابزارها و زمانهای بررسی.
نمای داده (data view): معماری داده شامل تصمیمات مهم در زمینه دادهها برای مثال نوع پایگاهداده (sql یا NoSql)، الگوها و تکنیکها در لایه داده (مثل cache و CQRS)، مدیریت دادهها و ابزارهای گزارشگیری، فرایندهای پشتیبانگیری و بازیابی و امنیتداده، تصمیماتی برای data integration و data migration
الگوها و تکنیکها: مرور روشها و تاکتیکهای مورد استفاده برای دستیابی به هر ویژگی کیفی.
ابزارها و فناوریها: مجموعه ابزارها، استانداردها، الگو و فناوریهای مورد استفاده شامل ابزارهای توسعه، تست، مانیتورینگ
مهمترین تصمیمات معماری: مهمترین تصمیمات معماری و همچنین راههای جایگزین و تاریخچه تصمیم
ریسکها و بدهیهای فنی (Risks and Technical debt): مخاطرات و بدهیهای فنی شناخته شده
سایر بخشها: نماهای متقاطع، گزارشگیری و بهبود پیشنهادهای آینده
نمای گزارشگیری: توصیف تصمیمات اصلی فنی برای تسهیل و تسریع گزارشگیری
فصل بهبود پیشنهادهای آینده: علاوه بر As-Is، توضیح To-Be رو هم اضافه کنیم. مثلا در کنار اینکه میگیم وضعیت موجودمون الان اینه ولی بعدا قراره کارهایی که دوست داریم انجام بدیم رو هم اضافه کنیم.
از اینجا به بعد در مورد مستند کردن معماری نرمافزار به روش مدل C4 از دیدگاه سیمون براون صحبت میکنیم. براون میگه با وجود اهمیت مستندسازی معماری نرمافزار، بسیاری از تیمها از UML استفاده نمیکنن بخاطر پیچیدگی UML و تمرکز زیاد بر جزئیات فنی که درکش رو برای افراد غیر متخصص یا حتی برخی از توسعهدهندگان دشوار میکنه. (کلا حرفش این نیست که UML بده، بلکه میگه معمولا درست ازش استفاده نمیشه و چون ماهیت فنی داره برای همه ذینفعان مثل مدیر محصول لزوما خوب نیست و در نتیجه میاد مدل سادهتر C4 رو معرفی میکنه.)
نکته ۶: باید هنگام ترسیم نمودارهای معماری، مانند یک توسعهدهنده فکر کنیم، نه صرفا یک معمار. یعنی باید بر روی جنبههای عملی و قابل درک معماری تمرکز کنیم که برای ساخت و نگهداری سیستم مهم هستند.
مدل C4 یک روش ساده و سطحبندی شده (مثل زوم نقشه) برای ترسیم و مستندسازی معماری نرمافزاره که شامل چهار سطح است:
نمودار Context: این نمودار مثل یه نمای کلی از بالا نشون میده که سیستم ما چیه، کی ازش استفاده میکنه و با چه سیستمهای دیگهای در ارتباطه. خیلی ساده است و برای همه، حتی کسایی که فنی نیستن هم قابل فهمه.
نمودار Container: این نمودار یه کم زوم میکنه و نشون میده که سیستم ما از چه قسمتهای اصلی تشکیل شده، مثلا یک وبسایت، یک دیتابیس یا یه اپلیکیشن موبایل. همچنین نشون میده این قسمتها چطوری با هم ارتباط دارن و از چه تکنولوژیهایی استفاده میکنن. این نمودار بیشتر به درد برنامهنویسا و کسایی میخوره که یه کم فنیترن.
نمودار Component: این نمودار باز هم زوم میکنه و نشون میده که هر کدوم از اون قسمتهای اصلی (container) از چه اجزای کوچیکتری تشکیل شده، مثلا یه بخش برای لاگین کردن، یه بخش برای پرداخت یا یه بخش برای نشون دادن محصولات. این نمودار خیلی به درد برنامهنویسا میخوره که میخوان بدونن ساختار داخلی هر قسمت چطوریه.
نمودار Code: این نمودار دیگه خیلی زوم میکنه و جزئیات کد رو نشون میده، مثلا کلاسها و رابطها. براون میگه این سطح معمولاً خیلی لازم نیست و میشه از ابزارهای UML یا حتی نمودارهای خودکار IDE ها استفاده کرد در واقع توصیش نمیکنه.
در ادامه نکات تکمیلی بیان میشه که تجربه براون از تیمهای نرمافزاریه. مثل چی؟ رسم اشکال ساده و قابل درک و نه نمادهای پیچیده، ثبات در استفاده از اشکال، استفاده از Legend برای نمودارها، تمرکز بر معنا و نه رنگ و ظاهر و توضیح دقیق خطوط ارتباطی.
ساختار مدل C4
برای بررسی بیشتر این مدل هم میتونین به سایت C4Model سر بزنین که روند استفاده از مدل C4 رو تشریح میکنه. و دقیقتر در مورد مستند کردن سیستمهای نرمافزاری، کانتینرها، کامپوننتها، کد، میکروسرویسها، صفها و اطلاعاتی در مورد نمادها، ابزارها، مثالها و آموزش ارائه میکنه که میتونه تکمیلکننده صحبتهای براون باشه.