گزارش نهایی پروژه معماری نرمافزار دانشگاه شهید بهشتی
این پست به بررسی معماری یک سیستم نرمافزاری فرضی در قالب درس معماری نرمافزار میپردازد. در این نوشتار، به تشریح چالشها و تصمیمگیریهای اتخاذ شده در فرآیند طراحی معماری این سیستم خواهیم پرداخت. کلیه فایلهایی که در این پست به آنها اشاره شده در یک مخزن گیتهاب به صورت عمومی در دسترس میباشد.
این سیستم به منظور تسهیل فرآیند جستجوی کار و یافتن فرصتهای شغلی مناسب طراحی شده است. سیستم با استفاده از کراولر، آگهیهای استخدام را از سایتهای مختلف کاریابی جمعآوری و در یک سامانه ذخیره میکند. کاربران با استفاده از برنامه موبایل یا وبسایت میتوانند به آسانی به این آگهیها دسترسی داشته باشند و نیاز به جستجوی جداگانه در هر سایت را نخواهند داشت.
ویژگیها:
جستجوی یکپارچه: جستجوی آگهیهای استخدام از تمام سایتهای کاریابی در یکجا
ذخیره و دستهبندی: ذخیره و دستهبندی آگهیهای مورد علاقه برای دسترسی آسان
اطلاعرسانی آنی: دریافت نوتیفیکیشن برای آگهیهای جدید مطابق با علایق کاربر (ویژه)
گزارش تحلیل پیشرفته بازار: دسترسی به گزارشهای تحلیلی از بازار کار، حقوق و تقاضا برای تخصصهای مختلف و... . (ویژه)
بهبود رزومه: ارائه ابزارها و راهکارهایی برای ارتقای کیفیت رزومه و افزایش شانس یافتن شغل (ویژه)
مزایا:
صرفهجویی در زمان: جستجوی سریع و آسان آگهیهای استخدام
دسترسی به فرصتهای بیشتر: یافتن آگهیهای استخدامی از تمامی سایتهای کاریابی
شخصیسازی: دریافت آگهیهای مرتبط با علایق و مهارتهای کاربر
افزایش شانس یافتن شغل: استفاده از ابزارهای تخصصی برای ارتقای رزومه و یافتن شغل مناسب
مخاطبان:
جویندگان کار: افراد در جستجوی شغل جدید یا ارتقای شغلی
دانشجویان: فارغالتحصیلان جویای کار
کارفرمایان: شرکتها و سازمانها به دنبال استخدام نیروی کار
جمعبندی:
این سیستم با ارائه یک راهکار جامع برای جستجوی آگهیهای استخدام، به کارجویان در یافتن شغل مناسب و کارفرمایان در جذب نیروی کار مورد نیازشان کمک میکند.
گام اول: تحلیل نیازمندیها و طراحی پایه
برای توسعه سیستم فرضی مورد نظر، ابتدا باید به سراغ تحلیل نیازمندیها و طراحی پایه سیستم نرمافزار میرفتیم. این فرآیند شامل مراحل زیر بود:
1. تحلیل اولیه:
تعیین محدوده کلی سیستم
شناسایی محدودیتها
مشخص کردن ویژگیهای کارکردی و غیرکارکردی (کیفی) سیستم
2. تدوین سند SRS:
بر اساس اطلاعات جمعآوری شده در مرحله تحلیل اولیه، سندی به نام Software Requirements Specification (SRS) تدوین شد. این سند شامل شرح کاملی از نیازمندیهای سیستم، از جمله اهداف، کارکردها، محدودیتها و معیارهای کیفی بود.
محدوده سیستم:
این پروژه به تعریف یک سیستم جمعآوری و دستهبندی آگهیهای استخدامی از منابع مختلف میپردازد. این سیستم امکان جمعآوری و نمایش آگهیهای استخدامی از وبسایتها، رسانهها و منابع دیگر را فراهم میکند. کاربران قادرند با استفاده از این سیستم آگهیها را بر اساس معیارهای مختلفی مانند مهارتها، مکان، هزینه و سابقه کاری جستجو و فیلتر کنند. همچنین، امکان جستجوی پیشرفته و سفارشیسازی برای کاربران در نظر گرفته شده است. کاربران میتوانند اشتراک ویژه خریداری کنند تا اعلانهای استخدامی جدید را دریافت کنند. سیستم از لاگهای جستجو و تنظیمات شخصیسازی کاربران نیز پشتیبانی میکند. محدوده این پروژه به توسعه و بهبود این قابلیتها و ارائه یک سامانه جامع برای جستجو و انتشار آگهیهای استخدامی ادامه دارد و میتواند در آینده با توجه به نیازمندیها و بازخوردهای مشتریان گسترش یابد.
3. طراحی معماری:
در این مرحله ما وارد بحث معماری نرمافزار شدهایم و کلیه کارهای قبلی برای طراحی معماری این سیستم لازم بودند. با استفاده از اطلاعات موجود در سند SRS، معماری مطلوب برای سیستم طراحی شد. این معماری شامل ساختار کلی سیستم، اجزای تشکیل دهنده آن و نحوه تعامل آنها با یکدیگر بود.
مزایای این رویکرد:
تضمین میکند که سیستم نهایی بر اساس نیازهای واقعی کاربران و با در نظر گرفتن محدودیتها و معیارهای کیفی طراحی و توسعه یافته است.
به عنوان یک نقشه راه برای توسعه سیستم عمل میکند و از بروز خطاها و انحرافات در طول فرآیند توسعه جلوگیری میکند.
امکان برآورد دقیقتر زمان و هزینه توسعه را فراهم میکند.
در این بخش، به بررسی تصمیمات معمارانه اتخاذ شده برای سیستم فرضی بر اساس نیازمندیهای غیرکارکردی (کیفی) میپردازیم.
نیازمندیهای غیرکارکردی:
در این بخش، مثالهایی از نیازمندیهای غیرکارکردی (ویژگیهای کیفی) به همراه یکی از معیارهای سنجش برای آنها که در سند وجود داشته، آمده است. کلیه ویژگیهای کیفی و جزئیات بیشتر مربوط به آنها در سند معماری (SAD) موجود در مخزن گیتهاب وجود دارد.
در دسترس بودن بالا (Availability): سیستم باید به طور مداوم در دسترس کاربران باشد و در صورت بروز خطا، میانگین زمان بازیابی (MTTR) خطا کمتر از یک ساعت باشد.
امنیت (Security): سیستم باید از اطلاعات کاربران در برابر دسترسیهای غیرمجاز، سوء استفاده و افشا محافظت کند.
قابلیت نگهداری (Maintainability): سیستم باید به گونهای طراحی شود که به راحتی قابل نگهداری و ارتقا باشد.
کارایی (Performance): این ویژگی به سرعت پاسخدهی سیستم به درخواستهای کاربران مربوط میشود. عملیاتهای حیاتی سیستم باید در کمتر از 2 ثانیه پاسخ داده شوند تا تجربه کاربری سریع و روانی را فراهم آورد.
قابلیت مقیاسپذیری (Scalability): این سامانه باید قادر باشد تا حداقل ۱۰۰۰۰ کاربر و تراکنش را به صورت همزمان پشتیبانی کند، بدون آنکه عملکرد آن دچار افت شود.
یکپارچگی (Integration): سیستم باید توانایی پشتیبانی از حداقل ۵+ سیستم خارجی را داشته باشد و به راحتی بتواند با APIهای مختلف ارتباط برقرار کند.
قابلیت استفاده (Usability): این ویژگی به آسانی استفاده از سیستم توسط کاربران اشاره دارد. نرخ خطا باید کمتر از 1% باشد و کاربران بتوانند بدون نیاز به کمک و تنها با استفاده از رابطکاربری، سیستم را یاد بگیرند و از آن استفاده کنند.
قابلیت اطمینان (Reliability): سیستم باید بتواند بین شکستهای خود فاصلهی زمانی مناسبی داشته باشد (میانگین زمان بین شکستها باید حداقل ۱۰۰۰ ساعت باشد) تا اطمینان حاصل شود که کاربران میتوانند به طور مداوم از سرویس استفاده کنند.
دسترسپذیری (Availability): سیستم باید توانایی فراهم کردن دسترسی مداوم به سرویسهای خود را داشته باشد. هدف این است که سیستم بالا بودن بیش از 99.9% زمان را حفظ کند.
یکنواختی (Consistency): دادهها و اطلاعات باید در سراسر سیستم یکنواخت و بدون تضاد باشند. این بدان معناست که در هر بخشی از سیستم که اطلاعاتی ثبت، بروزرسانی یا حذف میشوند، تغییرات باید به صورت همزمان در تمامی بخشهای دیگر اعمال شوند.
اکنون با توجه به محدوده سیستم، ویژگیهای کارکردی و غیرکارکردی (کیفی و محدودیتها) گفته شده، باید معماریهای مختلفی را بررسی کرده و تصمیمات معمارانه و کلانی بگیریم و با استفاده از این تصمیمها، بین آنها trade off انجام دهیم. در ادامه معماری و تصمیمات اتخاذ شده به صورت کلی مرور میکنیم. جزئیات و سند کامل معماری در مخزن گیتهاب وجود دارد:
برای مستند کردن جزئیات معماری، از قالب نمودارهای مدل C4 و جداولی استفاده کردیم (روش 4+1).
نمودار System Context:
این نمودار سیستم را در بالاترین سطح انتزاع نشان میدهد و تعاملات آن با سیستمهای خارجی، کاربران و محیط را به تصویر میکشد.
نمودار مورد کاربری:
نمودار Container Diagram:
این نمودار ساختار داخلی سیستم را به تفکیک containerها (مخازن) مانند برنامههای وب، برنامههای موبایل، پایگاه دادهها و … نشان میدهد.
نمودار Component Diagram:
این نمودار اجزای داخلی هر container را به تفکیک مؤلفههای منطقی مانند کلاسها، توابع و ماژولها نشان میدهد.
نمودار Deployment Diagram:
این نمودار چگونگی استقرار سیستم در محیط عملیاتی را نشان میدهد.
نمودار Dynamic Diagram:
تعامل اجزای مختلف سیستم در طول زمان را نشان میدهد.
این نمودارها با استفاده از ابزار structurizr و با زبان structurizr DSL ایجاد شدهاند. فایل DSL تولید این نمودارها در مخزن گیتهاب وجود دارد.
استفاده از این زبان برای تولید نمودارها و قرار دادن کد آن در کنار سند معماری باعث میشود که در هنگام عوض شدن معماری و به طبع، بروز کردن سند معماری، با اعمال تغییرات در آن کد، بتوانیم کلیه نمودارها را بروز کنیم.
4. ابزارها و تکنولوژی استفاده شده:
پیادهسازی کلاینت گوشی: ANDROID/IOS، Flutter
پیادهسازی کلاینت وب: Java / Spring MVC
پیادهسازی کلاینت وب به صورت: PWA، ReactJS
پیادهسازی بکاند اصلی که با باقی قسمتها در ارتباط است: Java/Spring Boot
فراخوانی APIهای سیستمهای پیامک، ایمیل و تلفن گویا: NodeJS
استفاده به عنوان پایگاه داده NoSQL به دلیل اینکه آگهیها ممکن است ساختارمند نباشند و ساختار خاص خود را داشته باشند: MongoDB
برای Cache کردن requestها و کاهش زمان پاسخدهی: Redis
سیستم تحلیلگر با تکنیکهای دادهکاوی و یادگیری ماشین همراه است: Python
برای ذخیرهسازی و مدیریت لاگها: ELK Stack (Elasticsearch, Logstash, Kibana)
برای ذخیرهسازی اطلاعات اساسی مانند کاربران: PostgreSQL
5. مهمترین تصمیمات معماری
باید به این نکته توجه شود که معماری حال حاضر ما، براساس نسل اول مایکروسرویسها است که جداسازی ساده مؤلفهها در آن انجام شده است و محیط توسعه و استقرار در آن، مستقل است. دلیل انتخاب این معماری، این بوده است که با توجه به محدودیتهایی که با آنها سر و کار داشتیم (مانند بودجه، تیم، زیرساخت و ...)، اتخاذ یک رویکرد سطح بالاتر مایکروسرویس مثل نسل سوم، برای شروع چنین سیستمی مناسب نبود. از طرفی دیگر، معماری حال حاضر ما، جدای از اینکه برای شرایط فعلی ما مناسب و پاسخگوی نیازهای فعلی ما است، در آینده میتواند با دشواریهای کمتری، نسبت به monolithic، به نشلهای جدیدتر تغییر یابد.
استفاده از معماری Microservices: تقسیم بندی منطقی سرویسها برای افزایش قابلیت نگهداری و مقیاسپذیری. از معماری modular monolithicبه معماری microserviceکوچ کردیم.
مؤلفه Single Page Application: برای بهبود تجربه کاربری با بارگذاری سریعتر و کمتر.
استفاده از Redis: برای Caching برای کاهش بار بر سرورهای پایگاه داده و بهبود زمان پاسخگویی.
استفاده از API Gateway: مدیریت و ایجاد نقطه مرکزی برای routing درخواستها و مسائل مرتبط با امنیت.
انتخاب استک فناوری: انتخاب زبانهای برنامه نویسی مثلاً جاوا اسپرینگ بوت برای API، Node.js برای سرویس اعلان.
انتخاب تکنولوژی وب برای کاربران ادمین و مشتریان برای برنامه وب (ReactJS)
انتخاب Flutter برای کلاینت موبایل.
استفاده از درگاه API: استفاده از درگاه API برای ارتباط کلاینتها با بکاند و دیتابیسها.
انتخاب دیتابیس و مدلسازی داده: تصمیمگیری برای استفاده از PostgreSQL برای دادههای رابطی و MongoDB برای ذخیره سازی اسناد، پیروی از ACID
یکپارچهسازی با سیستم پرداخت: تصمیمگیری برای ادغام درگاههای پرداخت شخص ثالث (ZarinPal’s APIs).
سیستمهای اعلان و ارتباط: انتخاب سرویس اطلاعرسانی (Node.js) که بتواند چندین کانال ارتباطی (پیام کوتاه، ایمیل، push notification و تلفن گویا) را پشتیبانی کند.
نظارت و ثبت وقایع: ادغام یک استک ثبت و نظارت مانند Elasticsearch برای ذخیرهسازی وقایع، Logstash برای پردازش وقایع و Kibana برای گرافیکی کردن عمل نظارت بر عملکرد سیستم.
تدابیر امنیتی: تعیین استراتژیهای احراز هویت و مجوز برای امن کردن دسترسی به APIها و استفاده از توکن JWT برای احرازهویت در کلاینتها. ذخیره توکن در Cookie و ایجاد SSL برای امنیت بیشتر. استفاده از Access Token با ماندگاری ۵ دقیقه و Refresh Tokenبا ماندگاری ۱ روز برای اوج امنیت.
بازیابی پس از فاجعه و پشتیبانگیری: برنامهریزی برای پشتیبانگیریهای منظم، استفاده از RAID10 برای از دست نرفتن Integrity.
استراتژی استقرار: استفاده از Docker و Kubernetes برای مدیریت استقرار Containerهای مختلفمان (اصطلاح C4).
توسعه برنامه کاربردی موبایل با flutter: انتخاب استفاده از flutter برای ساخت کلاینت موبایل و build گرفتن دو نسخه IOS و ANDROID.
6. ریسکها و بدهیهای فنی (Risks and Technical Debts)
ریسکها:
تغییرات مداوم در منابع آگهی: ممکن است از منابع خارجی که آگهیها را تامین میکنند، دادههای غیرقابل پیشبینی دریافت شود که میتواند روی دقت جستجو و فیلترها تاثیر بگذارد.
پیچیدگی مدیریت میکروسرویسها: با افزایش تعداد میکروسرویسها، مدیریت و هماهنگی بین آنها میتواند پیچیده شود.
مسائل مربوط به امنیت دادهها: اطلاعات حساس کاربران و آگهیها نیاز به حفاظت دقیق دارند و هر گونه نقص در امنیت میتواند به مشکلات جدی منجر شود.
بدهیهای فنی:
نیاز به توسعهی مداوم واسطهای API: در صورتی که APIها با تغییرات مکرر در منابع داده بهروز نشوند، ممکن است دچار کندی یا از کار افتادن شوند.
بستگی به زیرساختهای خارجی: استفاده از سرویسهای کلود و بسترهای مدیریت شده ممکن است سیستم را به این سرویسها وابسته کند.
مدیریت حالتهای خطا و بازیابی: برخورد با حالتهای خطا و اطمینان از بازیابی سریع سیستم در زمان بروز مشکلات میتواند به تدریج به بدهی فنی تبدیل شود.
سخن پایانی:
این پروژه که ما انتخابش کردیم، یک پروژه تقریبا عملی بود و معماری آن از صفر توسط خودمان طراحی و مستند شد و برخلاف پروژههای پیشنهادی دیگر (که بیشتر جنبه بررسی معماری یک سیستم یا نرم افزار معروف را داشتند)، این پروژه بیشتر شبیه به کارهای صنعتی معماری نرمافزار بوده و حاصل آن، یک سند معماری مطابق با آموختههای درس معماری نرمافزار بوده است.
طراحی معماری این سیستم، با توجه به نیازمندیهای کارکردی و محدودیتهای سیستم تعریف شده، انجام شده است و بسیاری از ابزارها، تاکتیکها و الگوهای معماری که در ابتدای طراحی در نظر داشتیم، مناسب نبودند و لذا، استفاده نشدند.