GoCasts آموزش Go به زبان ساده

برای ثبت‌نام در بوتکمپ آموزش بکند و گولنگ اینجا را کلیک کنید

معماری نرم افزار

در جلسه اول هفتگی GoCasts در مورد معماری نرم افزار صحبت کردیم. فیلم این جلسه رو میتونید از این لینک تماشا کنید.

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

"The fundamental organization of a system embodied in its components, their relationships to each other, and to the environment, and the principles guiding its design and evolution."


خب شاید تعریفی که مطالعه کردید فهمش خیلی راحت نباشه، واسه همین من چند تا تعریف دیگه از افراد با تجربه در این حوزه خدمتتون ارائه میدم، احتمالا بهتون کمک کنه. اولین نقل قول از آقای Martin Fowler هست که معماری نرم افزار رو اینطوری تعریف میکنه:

"I resolve my concern by emphasazing that good architecture is something that supports its own evolution."

خب آقای Fowler یه معماری خوب رو چیزی میدونه که تغییرات حین حیات خودش (حیات نرم افزار) رو پشتیبانی کنه. شاید اگه تعریف معماری نرم افزار رو از زبان آقای Grady Booch بخونیم، باز به روشن تر شدن موضوع کمک کنه:

"Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change."

آقای Booch معماری نرم افزار رو مجموعه از تصمیمات مهم میدونند که باعث شکل گیری یک سیستم میشه. و معیار مهم بودن یک تصمیم رو هم «هزینه تغییر» در نظر میگیرن.

نه فقط دو فردی که اشاره شد، بلکه تقریبا اکثر افراد مهم این حوزه «هزینه تغییر» رو یکی از مهم ترین عامل های شکل گیری معماری سیستم میدونند. معماری نرم افزار یک استاندارد یا قاعده نیست که شما قبل از پیاده سازی نرم افزار بخواید اونو ملاک قرار بدید. بلکه هر نرم افزار با توجه به ویژگی ها و خصوصیت های منحصر به فرد خودش، دارای نقاط حساس (جاهایی که هزینه تغییر زیاده) متفاوتی ست و نیاز به معماری نرم افزار متفاوتی هم داره. در واقع تمامی پارادایم ها و ابزارهایی که برای معماری نرم افزار وجود دارند مثل TDD و DDD و Clean Architecture و SOA و FaaS و Microservice Architecture، همگی مجموعه قواعدی هستند که به ما کمک میکنند برای نرم افزار مورد نظر خودمان، معماری بهتری را داشته باشیم که «هزینه تغییر» در آن کم باشد. روش های ذکر شده خودشان به هیچ وجه معماری نیستند که ما بخواهیم آن ها را ملاک قرار دهیم، ابزار هستند. ابزاری برای اینکه بتوانیم هزینه تغییر در نقاط مهم سیستم را کاهش دهیم.

برای اینکه درک بهتری از «نقاط مهم سیستم» و «هزینه تغییر» داشته باشیم، من چند مثال میزنم امیداورم که کمک کننده باشه. نقاطی که اشاره میکنم در مورد همه سیستم ها صدق نمیکنه، اما در حوزه نرم افزارهای تحت وب، معمولا این نقاط مشترک هستند.

دیتابیس

منطق برنامه ما، و بخش قابل توجهی از کدهایی که مینویسیم، مربوط به لایه ذخیره سازی داده هاست. اگر در انتخاب دیتابیس و یا orm و کتابخانه ارتباط با دیتابیس اشتباه کنیم، تغییر این قسمت از کدها، هزینه سنگینی برای ما خواهد داشت.

پروتکل ارتباطی بین سرویس ها و کلاینت

سرویس هایی که تحت وب پیاده سازی می شوند برای ارتباط با سرویس های دیگر و یا پاسخگویی به درخواست های مشتریان از پروتکل های متفاوتی استفاده می کنند مانند http1.1 و http2. همچنین نحوه serialize کردن داده ها هم می تواند متفاوت باشد، مثل json و یا protobuf.

نقاطی که به آنها اشاره کردم فقط بخش کوچکی از نقاط مهم سیستم هستند، خیلی از جزییات کوچک و یا بزرگ می توانند جزء تصمیمات مهم و معماری باشند. به عنوان مثال اگر codebase شما بزرگ است، یا در آینده بزرگ می شود، انتخاب کتابخانه لاگ و نحوه پس دادن خطا، خودش میتواند یک آیتم مهم از معماری باشد، زیرا که «هزینه تغییر» این بخش در codebase بزرگ بسیار زیاد است و انجام آن به این راحتی ها نیست. توجه داشته باشید که تصمیم گیری در مورد این نقاط مهم نباید صفر یا یکی باشد، منظور از نقاط مهم معماری این نیست که ما باید حتما در مورد نقاط مهم مثل دیتابیس در ابتدای کار تصمیم بگیریم و تا انتها آن را تغییر ندهیم، خیر، منظور این نیست. بلکه منظور از معماری خوب این است که ما در مورد نقاط حساس سیستم بگونه ای تصمیم گیری کنیم و کد بنویسیم که بعدا، هزینه تغییر آنها کم باشد.

یکی از راه هایی که معمولا در این رابطه به ما کمک می کند استفاده از Interface و Abstraction است. اگر ما به جای استفاده از یک orm یا کتابخانه دیتابیس خاص، منطق برنامه رو فقط به یک سری متد از یک interface وابسته کنیم، در آینده هیچ نگرانی ای بابت تغییر دیتابیس نخواهیم داشت، یا بهتر است بگویم نگرانی بسیار کمتری خواهیم داشت.

برای داشتن یه معماری نرم افزار خوب چه نکاتی رو باید مورد توجه قرار بدیم؟

Context

یکی از نکاتی که در طراحی یک سیستم باید به آن توجه شود Context است. برای سیستم نرم افزاری معیارهای مختلفی وجود دارد که در زیر به برخی از آنها اشاره می کنم:

  • Availability
  • Efficiency
  • Integrity
  • Maintainability
  • Performance
  • Portability
  • Reliability
  • Safety
  • Usability

لیست کامل تر این معیارها را می توانید در اینجا ببینید.

نکته بسیار مهمی که وجود دارد این است که شما نمی توانید نرم افزاری طراحی کنید که از نظر تمامی معیارهای مهم نرم افزار بهینه باشد، بلکه context نرم افزار شماست که تعیین می کند شما کدام معیارها را باید مورد توجه قرار دهید و سیستمی طراحی کنید که در آن معیارها خوب باشد. به عنوان مثال اگر دارید سیستمی طراحی می کنید که در یک embedded system خاص مورد استفاده قرار می گیرد در آنجا portability مهم نیست و لازم نیست در معماری سیستم به این معیار توجه کنید، اما efficiency بسیار مهم است زیرا که منابع سیستمی مثل RAM و CPU در یک embedded system محدود است و نرم افزار شما باید به شکل بهینه ای از این منابع استفاده کند.

Granularity

برای داشتن یک سیستم ماژولار که در آن بتوان کامپوننت های بسیار خاص منظوره تعریف کرد، به گونه ای که این کامپوننت ها در کنار هم تشکیل یک سیستم را بدهند، ابتدا شما باید معیار و اندازه کامپوننت را مشخص کنید، اصطلاحا باید granularity سیستم را تعیین کنید. برخی از granularityهای پرکاربرد این ها هستند:

  • Function
  • Service
  • Container

وقتی که granularity سیستم شما function باشد، آن وقت احتمالا بهتر است از Function as a service Architecture استفاده کنید، جایی که در آن هر function یک کار خاص را انجام می دهد بدون اینکه به بخش های دیگر سیستم وابستگی داشته باشد. اما اگر granularity سیستم شما service باشد آنوقت object oriented paradigms و معماری هایی مثل SOA می تواند به شما کمک کند. و اگر granularity برای سیستم container هست آن وقت cloud native design patterns و microservice architecture می تواند به طراحی یه سیستم خوب کمک کند.

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

اگر در طول مسیر یادگیری احتیاج به کمک دارید می توانید با بنده از طریق ایمیل در ارتباط باشید. همچنین برای اطلاع از مطالب جدید می توانید کانال تلگرام GoCasts را دنبال کنید.