طرحهای معماری: 4+1 مدل نمایش معماری نرمافزار بخش اول
1. چکیده:
در این مقاله قصد داریم مدلی را برای توصیف معماری سیستمهای نرمافزار با استفاده از نماهای متعدد و همزمان ارائه کنیم. استفاده از چندین نما این امکان را فراهم میآورد تا به صورت جداگانه به نگرانی های ذینفعان مختلف معماری پرداخته شود. کاربر نهایی، توسعه دهندگان، مهندسان سیستم ها، مدیران پروژه و غیره هریک نیازمندیهای خاص خود را دارند. از سوی دیگر به کمک این نماهای مختلف میتوانیم نیازهای عملکردی و غیر عملکردی را نیز به درستی مورد بررسی قرار دهیم. در این مطلب 5 نمای مختلف برای معماری توضیح داده شده که هر یک از این پنج نما به همراه یک روش برای ثبت آن توضیح داده شده است. نماها با استفاده از یک فرآیند توسعه تکراری، مبتنی بر سناریو و معماری محور طراحی شدهاند.
2. مقدمه:
همه ما تا کنون مقالات و کتب زیادی، که قصد داشتهاند لب کلام معماری یک سیستم نرمافزاری را در قالب یک طرح ارائه کنند مشاهده کردهایم. با کمی دقت در طرحهای ارائه شده در این کتب و مقالات در خواهیم یافت که نویسندگان آنها تلاش زیادی انجام دادهاند تا به کمک شکلها و فلشها و علامتها و ... تجمیع شده کنار هم بیش از یک مفهموم را در یک طرح بگنجانند. برای مثال واقعا هر کدام از Boxهای داخل تصویر چه چیزی را نمایش میدهند؟ آیا هدف نمایش بخش اجرایی از نرمافزار است؟ قرار است بخشی از سورس کد را نمایش دهند؟ گروهی از کامپیوترهای فیزیکی همکار را نمایش میدهد؟ هدف از فلشهای این نمودارها چیست؟ نمایش وابستگی سورسکدها هنگام کامپایل؟ جهت کنترل جریان؟ جهت حرکت دادهها؟ در حقیقت این طرحها جواب همه این سوالها هستند. اما آیا معمار نیازی به داشتن یک ابزار و روش جهت انجام کار خود دارد؟ بعضا معماری سیستم از خورد شدن بسیار زیاد در ابتدای کار آسیب میبیند. در برخی موارد تمرکز زیاد از حد روی قسمتی از سیستم میتواند موجب ایراد در معماری شود. مثلا تلاش زیاد برای طراحی بهینه ساختار دادهها از ابتدای کار، یا تمرکز بیش از حد روی سرعت بالای اجرای برنامه از ابتدا. در بسیاری از موارد این چنین طرحهایی نیازهای افراد مختلف درگیر در پروژه را پاسخ نمیدهند. به عنوان یک راه حل در این مقاله قصد داریم طرحها و نماهایی را ارائه کنیم که به طور همزمان باید در مدلهای یک سیستم مبتنی بر نرم افزار ارائه شود تا تمامی نیازهای تمامی افراد درگیر در پروژه پاسخ داده شود.
3. یک مدل معماری:
معماری نرم افزار به طراحی و پیادهسازی ساختار سطح بالای نرم افزار می پردازد. معماری نرمافزار نتیجه کنارهم قراردادن تعدادی اجزای منتخب در یک فرم خوب کنار هم میباشد. این کنارهم قراردادن باید موجب پاسخگویی به نیازهای کاربردی و غیرکاربردی نرمافزار شود. پری و ولف این موارد را در قالب یک فرمول که تغییر یافته فرمول آقای بوهم میباشد ارائه کرده اند.
Software architecture = {Elements, Forms, Rationale/Constraints}
معماری نرمافزار با مواردی مثل انتزاغ، ترکیب، تجزینه، سبک و زیبایی شناسی سر و کار دارد. برای نمایش معماری ما از چندین طرح یا چشم انداز یا نما استفاده میکنیم. برای اینکه بتوانیم معماری یک سیستم بزرگرا نمایش دهیم، ما در مدل خود از 5 طرح اصلی استفاده میکنیم.
- نمای منطقی یا Logical view: هنگام استفاده از OOP مدل طراحی اشیا است.
- نمای فرایند یا Process view: جنبه های همزمانی و همگامسازی طراحی را نشان می دهد،
- نمای فیزیکی Physical view: نگاشت(های) نرم افزار را بر روی سخت افزار توصیف می کند و جنبه توزیع شدن آن را منعکس می کند.
- نمای توسعه یا Development view: سازماندهی ایستای نرم افزار را در محیط توسعه توصیف می کند
توصیف معماری یک سیستم به کمک این چهار طرح قابل ارائه است و در ادامه به کمک تعدادی مورد کاربرد منتخب شرح داده میشود. این موارد کاربرد پنجمین قسمت از پازل ما را تشکیل میدهند. در ادامه به توضیح دقیق تر این موارد میپردازیم.

معادله Perry & Wolf را بهطور مستقل روی هر نما اعمال خواهیم میکنیم، یعنی برای هر نما مجموعهای از عناصر قابل استفاده را تعریف میکنیم مثلا کامپوننتها، کانتینرها و رابطها را بیان میکنیم. برای هر نما، الگوها و فرمهای کارامد را میگیریم، منطق را درک میکنیم و محدودیتها را مد نظر قرار میدهیم، و با توجه به همه این شرایط با عناصری که در اختیار داریم معماری را بیان میکنیم. معماری ما در این شرایط برگرفته از نیازمندیهای نرمافزار است.
در این روش هر نما در طرحی که شامل نمادهای خاص خود است ترسیم میشود. برای هر نما معماران میتوانند سبک خاصی از معماری را مورد استفاده قرار دهند و این امکان وجود دارد که سبکهای مختلف معماری در یک کار با هم همزیستی مسالمت آمیز داشته باشند.
حال قصد داریم هریک از نماها را بررسی کنیم و ببینیم هر نما چه هدفی دارد و در مورد هر نما عناصر قابل استفاده در آن و نحوه استفاده از آنها را مشاهده خواهیم کرد. برای ارائه نماها از مثالهای ساده شدهای از یک سیستم کنترل ترافیک هوایی و سیستم PABX که برای Alcatel Business قبلا طراحی کرده بودم، استفاده کردهام. دقت داشته باشید که هدف ما صرفا ارائه نحوه بیان معماری سیستمهای نرم افزاری است، به همین دلیل سیستمی که معماری آنرا تعیین میکنیم ساده در نظر گرفته شده است. مدل 4+1 بسیار عمومی طراحی شده است و این قابلیت وجود دارد که در کنار سایر طرحها مورد استفاده قرار گیرد.
4. نمای منطقی(تجزیه شی گرا):
هدف این طرح پشتیبانی از نیازمندیهای عملکردی است. اینکه چه عملکردی توسط این سیستم باید برای کاربران فراهم شود در حیطه مسئولیتهای این طرح قرار داد. معمولا سیستم به چندین قسمت که از دامنه اصلی تشخیص داده میشود در قالب اشیا یا کلاسها تجزیه میشود. در این تقسیم بندی از اصولی مثل ارثبری انتزاع و کپسوله سازی استفاده میشود. این تجزیه صرفا به خاطر تحلیل عملکردی سیستم نیست. بلکه به ما در شناخت قسمتهای مختلف سیستم و مکانیزمهای موجود نیز کمک میکند. ما برای طراحی این قسمت از روش رشنال/ بوچ استفاده میکنیم یعنی کلاس دیاگرامها و کلاس تمپلیتها. یک کلاس دیاگرام مجموعهای از کلاسها و روابط منطقی آنها مثل تجمیع، ترکیب، استفاده و ... را نمایش میدهد. مجموعهای از کلاسهای مرتبط با هم در قالب class category با هم دسته بندی میشوند. در ادامه کلاس تمپلیت روی جزئیات کلاسها تمرکز میکند. در کلاس تمپلیت ویژگیهای اصلی کلاس و عملکردهای آن تشخیص داده میشود. اگر نیاز داشته باشیم که عملکرد داخلی یک کلاس را مدل کنیم از State Chart یا State Transition diagram استفاده میکنیم. موارد و عملکردهای عمومی در Class Utilities تعریف میشود. در صورتی که نرم افزار ما بیشتر از دادهمحور باشد تا دامنه محور، به جای این دیاگرامها از E-R دیاگرام استفاده میکنیم.
4.1. علامتگذاریهای نمای منطقی:
برای علامت گذاری طرح منطقی از روش بوچ استفاده میکنیم. در این علامتگذاریها به طور قابل توجهی سادهسازی انجام شده است و صرفا علامتهایی که از نظر معماری کمک میکنند در نظر گرفته میشوند.

4.2. سبکی برای نمای منطقی:
برای این نما از سبک Object Oriented استفاده کردهایم. راهنمای اصلی برای طراحی نمای منطقی این است که سعی کنید یک مدل شی منسجم و واحد را در کل سیستم نگه دارید و از تخصصی شدن بیش از حد و زودهنگام کلاسها دوری کنید. نمونهای از طرح منطقی مرتبط با مثال را در تصویر زیر مشاهده میکنید.

سیستم PABX ارتباطات بین Terminlها را برقرار می کند. یک ترمینال میتواند یک دستگاه تلفن، یک خط ارتباط اصلی، یک ارتباط خصوصی، یک خط ارتباطی ویژه یا ... باشد. خطوط مختلف توسط کارتهای رابط خط مختلف پشتیبانی می شوند. مسئولیت یک شی Controller خط، رمزگشایی و تزریق تمام سیگنال های روی کارت رابط خط است. Controller سیگنالهای مخصوص کارتها را به مجموعه کوچکی از رویدادهای یکدست تبدیل میکند. رویدادهایی مانند Start, Stop, Digit و ... در مجموعه رویدادهای یکدست وجود دارند. این کلاس زیرکلاسهای متعددی برای انواع اینترفیسها دارد. مسئولیت شی terminal حفظ وضعیت یک terminal و مذاکره در مورد خدمات از طرف آن خط است.برای مثال، از خدمات Numbering Plan برای تفسیر شماره گیری در مرحله انتخاب استفاده می کند. Conversation مجموعه ای از Terminalهای درگیر در یک مکالمه را نشان می دهد. conversation از Translation Service (دایرکتوری، نقشه برداری آدرس فیزیکی منطقی، مسیرها) و Connection Service برای ایجاد یک مسیر صوتی بین Terminal ها استفاده می کند.
برای مثالی از یک سیستم بزرگتر هم به تصویر دوم دقت کنید. این تصویر مربوط به سیستم کنترل ترافیک هوایی است که کلاسهای مهم در سطح معماری آن در این تصویر مشاهده میشود. کلاسهای مهم این طرح شامل 8 گروه کلاس میشود که در تصویر قابل مشاهده است.
5. نمای فرایند ( تجزیه فرایند):
هنگامی که در مورد معماری و نمای فرایند صحبت به میان میآیند هدف ما ویژگیهای غیرکاربردی نرمافزار مثل بهرهوری و دردسترس بودن است. وقتی در مورد مباحثی مانند همزمانی، توزیعپذیری، یکپارچگی، تحمل خطا، در دسترس بودن صحبت میکنیم همیشه نمای فرایند به کمک ما میآید. معماری فرایند را در چندین سطح میتوان بیان کرد که هر سطح به نگرانیهای خاصی توجه کرده و به آنها پاسخ میدهد. در بالاترین سطح، معماری فرایند را می توان به عنوان مجموعهای از شبکههای منطقی برنامههایی دید که به طور مستقل اجرا می شوند (که «فرایندها» نامیده می شوند)، و این شبکههای منطقی از برنامهها در مجموعه ای از منابع سخت افزاری که در یک LAN یا یک WAN در کنار هم قرارگرفتهاند، توزیع شده اند. برای مثال شبکههای منطقی ممکن است برای جدا سازی سیستمهای عملیاتی و آنلاین از سیستمهای آفلاین مورد استفاده قرارگیرند. هر از تعدادی وظیفه که یک واحد اجرایی را تشکیل میدهد ساخته شده است. فرایندها نشان دهنده سطحی هستند که در آن معماری فرایند را می توان به صورت تاکتیکی کنترل کرد. مثلا شروع کرد، پایان داد، بازیابی یا خاموش کرد. در کنار این شرایط فرایندها را میتوان برای توزیع بار یا بالابردن دسترس پذیری تکثر کرد.
نرم افزار به مجموعه ای از وظایف (Task) مستقل تقسیم می شود. یک وظیفه یک رشته کنترل جداگانه است که می تواند به صورت جداگانه در یک گره پردازشی برنامه ریزی شود.
با این شرایط میتوانیم گروههای متفاوتی از وظایف را تشخیص دهیم. برخی از آنها وظایف اصلی هستند که از منظر معماری قابل بررسی و هستند و برخی دیگر وظایف جزئی هستند که معمولا به دلایل فنی و جزئی ایجاد میشوند. وظایف اصلی و نحوه ارتباط بین آنها مهم است. ارتباط بین این دسته از وظایف باید به خوبی شناسایی و پیاده سازی شود که معمولا از روشهای RPC یا Event base برای ارتباط بین آنها استفاده میشود. این درحالی است که وظایف جزئی معمولا داخل یک برنامه ایجاد میشوند ارتباط و عملکرد آنها برای دنیای خارج از برنامه اهیمت چندانی ندارد. وقتی وظایف اصلی طراحی میشوند نباید در مورد نحوه قرارگیری آنها در یک یا چند جای مختلف فرضی در نظر گرفته شود. جریان پیامها و باری که روی سیستم قرار میگیرد از روی طرحهایی که برای نمای فرایند ایجاد میشود قابل تخمین و درک است.
5.1. علامتگذاریهای نمای فرایند:
نمادها و علامتگذاریهایی که برای نمای فرایند استفاده میکنیم ابتدا توسط بوچ برای وظایف Ada پیشنهاد شده بود. در این جا باز هم تاکید میکنم که نمادهای استفاده شده بر عناصری متمرکز است که از نظر معماری مهم هستند.

از ابزارهای مختلفی میتوان برای رسم طرحهای این سطح استفاده کرد که برخی از آنها میتوانند با توجه به طرح کدها مربوط به ارتباط فرایندهای مختلف را هم ایجاد کنند.
5.2. سبکی برای نمای فرایند:
سبکهای متفاوتی را برای طرحهای این سطح میتوان در نظر گرفت. برای مثال Pip و Filter یا Client/Server که خود میتواند به دستههایی مثل، چندین Client با یک Server، چندین Client با چندین Server تقسیم شود.

همه پایانه ها توسط یک Terminal process واحد مدیریت می شوند که توسط پیام هایی در صف های ورودی آن هدایت می شود. اشیاء کنترلر بر روی یکی از سه وظیفه ای که فرایند کنترل کننده را تشکیل می دهد اجرا می شوند: یک low cycle rate task تمام پایانههای غیرفعال (200 میلیثانیه) را اسکن میکند، هر پایانهای که فعال میشود را در لیست اسکن high cycle rate task (10 میلیثانیه) قرار میدهد، که هر تغییر قابل توجهی از حالت را تشخیص میدهد، و آنها را به main controller task منتقل میکند. main controller task تغییرات را تفسیر کرده و آنها را از طریق پیام به ترمینال مربوطه منتقل می کند. در اینجا ارسال پیام در فرایند کنترلر از طریق حافظه مشترک انجام می شود.
6. جمع بندی:
مطلبی بالا ترجمه مقاله Architectural Blueprints—The “4+1” View Model of Software Architecture نوشته آقای Philippe Kruchten است که نسخه اصلی از اینجا امکان دانلود دارد. به علت طولانی بودن مقاله در بیش از یک قسمت نوشته را منتشر میکنم.
نوشته اصلی کمی طولانی هست و اینکه به دلیل قدیمی بودن مطلب بعضا نشانهگذاری هایی که استفاده شده یا از رده خارج شدن یا بسیار به روز رسانی شدن و با نسخه به کار برده شده در مقاله متفاوت هستن! در کنار این مسئله، نکته قابل توجه دیگه در مورد قدیمیبودن مقاله این هست که سبکهای معماری جدیدی در نماهای مختلف بعد از این مقاله به دنیای توسعه نرمافزار معرفی شدن. بعضا این سبکهای جدید بسیار پر استفاده هستن یا برعکس بعد از چند سال از رده خارج شدن و دیگه مورد استفاده قرار نمیگیرن که هیچ مثال و حرفی از این سبکها توی این مقاله نیست مثلا میکروسرویسها که این روزهای بسیار مورد توجه هستن.
اما با همه این تفاسیر به جای استفاده از مثالهای به روز و استفاده از منابعی که به روزتر باشن از مطلب اصلی استفاده کردم. برای انجام این کار چند دلیل داشتم! اول اینکه با اینکه بعضا نشانهها و ... قدیمی شدن ولی کاملا قابل فهم و کاربردی هستن. نکته بعدی اینکه به نظرم در بین منابع مختلفی که به بیان این موضوع پرداختن نوشته اصلی بسیار بیان جامع و شیوایی توی این کار داره. و آخرین نکته جالب از نظر خود من این هست که با اینکه الان میشه در نظر گرفت سالیان زیادی از مطلب اصلی گذشته اما هنوز هم که هنوز مسئلهها، چالشها، نکات مثبت، الگوها و ... یکسان قابل درک و لمس هستن. یعنی هیچ مسئله و دغدغهای در مقاله وجود نداره که بتونیم بگیم 30 سال از مطلب گذشته و این موضوع دیگه حل شده است!
این موضوع برای خود من جذابه!
چطور ممکنه مسائلی ثابت با نیازمندیهای ثابت به روشهای ثابت قرار باشه حل بشه و باز هم نشه در مورد اون مسئله قطعی صحبت کرد! این جاذبه دنیای توسعه نرمافزار چیزیه که فکر کنم تا 80 سالگی هم بتونم در موردش فکر کنم، مطالعه کنم، کار کنم، آزمایش کنم و بازهم هیچ چیزی در موردش ندونم! مثل یه پازل تکراری که هر روز حل میکنی و هر روز ممکنه خروجی جدیدی بده یا اصلا نتونی حلش کنی! :-D
خوشحالم تو عصری زندگی میکنم که این دسته از مسائل وجود داره! نه اونقدر زود به دنیا اومدم که بشر به دانش امروزی نرسیده باشه و اصلا همچین مسئلههایی مطرح نباشه! نه اونقدر دیر که همه این ها حل شده باشه!
اگر دوست داشتید در مورد معماری نرمافزار بیشتر بدونید و این مقاله رو هم به صورت تشریح شده ببینید پیشنهاد میکنم حتما به این سایت سری بزنید https://lecture2go.uni-hamburg.de/ و درس معماری نرمافزار رو ببینید! حدود 23 ساعت هست. دانشگاه خوب و استاد خوب و ارائه هم مال سال 2020-2021 هست و بسیار جدید و جذاب! کلاسهای زیادی داره! ولی Lecture Software Architectures حتما ببینید!
مطلبی دیگر از این انتشارات
هوش مالی، راهکار گذر از روزهای سخت
مطلبی دیگر از این انتشارات
مصلحتطلبی جمعی؛ راهکار برونرفت از تعارض کار تیمی
مطلبی دیگر از این انتشارات
آموزش Spring Boot / بخش نخست