علیرضا صفافرد
علیرضا صفافرد
خواندن ۲۷ دقیقه·۱ سال پیش

مرور فصل‌های ۱۵ تا ۲۹ و فصل‌های ۳۰ تا ۳۴ کتاب Clean Architecture

معماری (۱۵)

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

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

توسعه

یک رابطه مهمی که در این موضوع حائز اهمیت است این است که هر چقدر توسعه یک نرم‌افزاری سخت باشد عمر طولانی و سالمی نخواهد داشت بنابرین باید معماری نرم‌افزار به گونه‌ای باشد که توسعه نرم‌افزار را برای برنامه‌نویسان و کارمندان راحت‌تر بکند

استقرار

یک رابطه مهمی که در این بخش مهم است آن است که هر چقدر استقرار یک نرم‌افزار هزینه کمتر و زمان کمتری باشد می‌شود گفت که نرم‌افزار مفید‌تر است. این بخش معمولا در فاز‌های اولیه پروژه در نظر گرفته نمی‌شود و بعدها به مشکل برخواهند خورد. به عنوان مثال شما برای اینکه توسعه یک نرم‌افزار بهتر و راحت‌تر باشد ممکن است به سمت معماری میکروسرویس بروید و سعی کنید تعداد سرویس‌های سیستم را بیشتر بکنید اما در نظر داشته باشید که ارتباط بین این سرویس‌ها می‌تواند خود منشا بروز مشکلاتی شود.

عملکرد

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

نگهداری

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

یکی از ویژگی‌های نرم‌افزار نرم بودن آن است این ویژگی با باز گذاشتن گزینه‌های مختلف در نرم‌افزار است اما موضوعی که مطرح است این است که چه گزینه‌هایی باز نگهداشته بشوند؟ آن‌ها جزئیاتی هستند که اهمیت خاصی ندارند. تمام سیستم‌های نرم‌افزاری را می‌توان به دو عنصر اصلی تقسیم کرد: سیاست‌ها و جزئیات.

سیاست‌: این بخش معمولا از قوانین حاکم بر کسب‌وکار گرفته می‌شود و ارزش واقعی سیستم در آن قرار دارد

جزئیات:جزئیات زیربخش‌هایی هستند که برای توانمندسازی انسان‌ها، سایر سیستم‌ها و برنامه‌نویسان برای برقراری ارتباط با سیاست‌ها ضروری هستند، یعنی به نوعی ارتباط بین کاربران و سهامداران را با سیاست‌های نرم‌افزار برقرار می‌کند ولی به هیچ وجه بر سیاست‌ها تأثیر نمی‌گذارند. اگر بخواهیم چند مثال نام ببریم می‌توانیم بگویم دستگاه‌های IO، پایگاه‌های داده، سیستم‌های وب، سرورها، چارچوب‌ها، پروتکل‌های ارتباطی و ... هستند.

یک معمار خوب وظیفه این را به عهده دارد که تا جای ممکن جزئیات را از سیاست‌ها جدا کند.معماران خوب سیاست را طوری طراحی می‌کنند که تصمیم‌گیری در مورد جزئیات را می‌توان تا زمانی که ممکن است به تعویق انداخت.

یک مثالی نیز نویسنده از تاریخچه زندگی خود میزند و آن این است که در زمان قدیم آنها یک برنامه‌ای نوشته بودند که سیاست‌ها متصل به جزیئات (ماشین چاپ)بودند و زمانی که آن‌ها می‌خواستند به نحو دیگری تبلیغات خود را انجام‌دهند باید کل کد را مجددا می‌نوشتند لذا شرکت زیر بار این هزینه‌ نمی‌رفت و مدت‌های زیادی شرکت به همان روال پرهزینه و قدیمی خود تبلیغات را انجام می‌داد

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

خوشبختانه، ما از نصیحت او استفاده کردیم. ما سیاست سطح بالای سیستم را تغییر دادیم تا بی‌تفاوت نسبت به ساختار فیزیکی دیسک باشد(بخش‌های جزئی سیستم). این به ما امکان می‌داد تصمیم در مورد ساختار درایو دیسک را از برنامه جدا کنیم.

استقلال (فصل ۱۶)

استفاده‌ها(use case)

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

عملکرد

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

توسعه

یک قانون مهم در این بخش قانون Conway’s هست که می‌گوید:هر سازمانی که یک سیستم را طراحی می‌کند، به نوعی ساختار سازمان خود را در آن کپی کرده است. سیستمی که باید توسط یک سازمان با تعدادی تیم و نگرانی‌های مختلف توسعه داده شود، باید یک معماری داشته باشد که به تیم‌ها اجازه عملیات مستقل در طول توسعه را می‌دهد تا تداخلی با یکدیگر نداشته باشند. این امر از طریق تقسیم صحیح سیستم به اجزای مستقل و قابل توسعه به صورت مستقل انجام می‌شود. سپس این اجزا به تیم‌هایی اختصاص داده می‌شوند که مستقل از یکدیگر کار می‌کنند.لذا شما خواهید دید که تعداد ماژول‌های توسعه داده شده یا بخش‌های مستقل به نوعی به تعداد تیم‌های موجود در شرکت ربط دارد

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

گذاشتن گزینه‌ها باز

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

لایه بندی مستقل در این بخش می‌خواهیم درباره معماری لایه‌ای صحبت بکنیم در این جا معمار قصد دارد که از اصل‌های زیر نیز استفاده بکند

اصل مسئولیت‌های تکی (Single Responsibility Principle)

اصل اتمام مشترک (Common Closure Principle)

تا آنچه که به دلایل مختلف تغییر می‌کند را جدا کند و آنچه که به دلایل یکسان می‌تواند تغییر کند را جمع‌آوری کند - با توجه به متن واقعی سیستم معمار باید رابط‌کاربری را که به دلایل مختلف ممکن است تغییر کند را با بخش قوانین حاکم بر تجارت را جدا کند تا بتواند آن‌ها را به صورت مستقل از هم تغییر دهد. همچنین پایگاه داده و زبان جستجویی که می‌خواهیم استفاده بکنیم خود نیز جزو جزئیات فنی سیستم هستند که ارتباطی با قوانین تجارت ندارند لذا این‌ها نیز باید جدا شوند لذا سیستم ما اگر قرار باشد به صورت لایه‌های افقی جدا شوند می‌شود: رابط کاربری، قوانین تجاری مخصوص به سیستم، قوانین تجاری مستقل از برنامه و پایگاه داده

جداسازی از طریق موارد استفاده

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

وضعیت جداسازی

اگر موارد بالا رعایت شده باشد دیگر دیتابیس و قوانین و رابط کاربری از یکدیگر جدا هستند و هر یک می‌تواند در سروری با مشخصات فنی متفاوت و مورد نیاز خود قرار بگیرند و آن‌هایی که نیاز به پهنای باند بالاتری دارند می‌تواند در چندین سرور کپی شوند. بسیاری از معماران این رویکرد را میکروسرویس‌‌ها می‌نامند.یک معماری مبتنی بر سرویس‌ها اغلب معماری مبتنی بر سرویس (Service-Oriented Architecture) نامیده می‌شود.

توانایی توسعه مستقل

به وضوح معلوم است که اگر اجزا به طور قوی از یکدیگر جدا باشند تداخل بین تیم‌ها بسیار کاهش می‌یابد و توسعه نرم‌افزار بسیار راحت‌تر می‌شود.لذا تا زمانی که لایه‌ها و مورد استفاده‌ها جدا شوند(معماری لایه‌ای که برش افقی را ایجاد می‌کردند و جداکننده عمودی که استفاده موردی نام داشت)، معماری سیستم پشتیبانی از سازماندهی تیم‌ها را به هر شکلی که باشد (تیم‌های ویژگی، تیم‌های اجزا، تیم‌های لایه، یا ترکیبی از آن‌ها)، ارائه خواهد داد.

قابلیت انتشار مستقل

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

تکثیر

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

کاهش اتصال حالت‌ها (دوباره)

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

سطح کد منبع: باید سعی کنیم ماژول‌ها بگونه‌ای نباشند که با تغییر یکی از آن‌ها بقیه کد نیز باید بازکامپایل شوند در این حالت کاهش اتصال خیلی مهم می‌باشد و فراخوانی توابع یکدیگر و استفاده غیر مستقیم از متغییر‌ها کمک بسیار زیادی می‌کند

سطح نصب:اگر وابستگی‌های بین فایل‌های DLL ,Jar را کنترل کنیم و با تغییر یک فایل بقیه موارد لازم نباشد تغییر کنند ما شاهد این خواهیم بود که بسیاری از مولفه‌ها همچنان در فضای آدرس گذشته خود قرار خواهند داشت.

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

مرزها: رسم خطوط (فصل ۱۷)

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

کدام خطوط را در چه زمانی بکشیم؟

بین هر دو موردی که نسبت به یک دیگر از اهمیت یکسانی برخوردار نیستد باید خط کشید به عنوان مثال بین رابط کاربری و قوانین تجارت

آیا خروجی و ورودی های سیستم نیز مهم هستند؟

به طور کلی بله ولی آن‌ها بسیار بخش بدون اهمیت سیستم را تشکیل می‌دهند ولی اقلب کاربران انتظار دارند که این بخش اصلی نرم افزار باشد ولی اگر شما موس یا کیبورد را نداشته باشید باز‌هم سیستم بخش مدلینگ یک بازی را انجام می‌دهد و به درستی کار می‌کند لذا خوب است یک خط بین این دو هم قرار بدهیم.(IO , قوانین تجارت)

معماری پلاگین

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

اگر معماری دو شرکت visiual studio , ReSharper را در نظر بگیرید این دو وابستگی نامتقارن دارند یعنی اگر ماکروسافت بخواهد می‌تواند شرکت دیگر را زمین بزند و این اصلا برای ما مطلوب نیست و باید از این حالت پرهیز کنیم.

آناتومی مرزی(فصل ۱۸)

در این فصل به چند مثال از کشیدن خط‌های جداساز می‌پردازیم.شما ممکن است به کمک یک تابع از این مرزها عبور کنید ولی باید حتما یک فایروالی داشته باشید تا تغییرات کد منبع باعث تغییر بقیه کدها نباشد. و الگوی پولیمورفیس باعث برعکس کردن حرکت نیازمندی است و می‌شود از آن استفاده کرد.همچنین راه ارتباطی بین چند پروسس را بیان می‌کند و می‌گوید می‌شود از socket استفاده کرد تا کمی ایزولاسیون بهتر باشد.و همچنین ارتباط بین سرویس‌ها را بیان می‌کند و می‌گوید معمولا این ارتباط از طریق شبکه انجام می‌شود و می‌گوید این ارتباط نباید وزن زیادی داشته باشد زیرا تاخیر در این مدل زیاد است و مانند فراخوان یک تابع نیست.

خط مشی و سطح(فصل ۱۹)

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

قوانین کسب و کار فصل ۲۰

اگر بخواهیم قوانین موجود در کسب و کار را دسته بندی کنیم و در نرم‌افزار خود بر این اساس بخش‌بندی بکنیم لازم است که در مرحله اول اشراف خوبی نسبت به مطالب موجود در کسب‌و‌کار داشته باشیم. معمولا قوانین اصلی هر کسب‌وکاری به اطلاعات بیرونی وابسته است به عنوان مثال یکی از قوانین اصلی بانک‌داری بحث وام و سود آن است به عنوان مثال باید سیستم به عنوان ورودی بداند که سود یک وام چند درصد باید باشد و یا زمان‌بندی پرداخت آن به چه صورت است. به این دیتا‌های بیرونی در کتاب (Critical Business Data) می‌نامند. به مجموعه قوانین مرتبط به دیتاهای خاص می‌توانیم یک (Entities) نام‌ببریم. یک مثال از نحوه نمایش آن در شکل زیر آمده است

البته همه چیز و قوانین کسب‌وکار لزوما یک (Entities) نیست برخی از آن‌ها به صورت یک چرخه و مسیر هستند که لازم است اتوماسیون برایشان انجام شود و آن‌ها را با اسنادی به نام use case به نمایش می‌گذارند. ساختار آن به این صورت است که ورودی‌های این پروسه را نوشته و خروجی‌های آن و قوانین حاکم بر نحوه تولید خروجی و سپس به عنوان یک سند ضبط می‌شود و برای تولید این سند لازم به داشتن اطلاعاتی از نحوه تولید و کد‌نویسی آن نیست.

معماری فریاد (فصل ۲۱)

باید معماری فایل‌ها و پوشه‌های کد‌های سطح بالا به نوعی باشد که به نوعی فریاد بزند که پروژه چیست و قرار است چه کاری را انجام دهد مانند سند معماری آبی رنگ ساختمان و نقشه‌کشی. لذا در نرم‌افزار نیز ما باید براساس موارد استفاه نرم‌افزار فایل‌های سطح بالای خود را بسازیم.همچنین یک معمار خوب سعی می‌کند موارد استفاده را معلوم کند و براساس آن تصمیم بگیرد و تصمیماتی که مرتبط به ابزار و نحوه تولید است را تا جایی‌ که بتواند به تاخیر‌ می‌اندازد. همچنین فریمورک‌ها صرفا یک ابزار هستند برای راحت تر شدن کدنویسی نباید به آن‌ها وابسته باشیم باید به موارد استفاه وابسته باشیم. اگر معماری را درست انجام داده‌باشیم باید بدون پیاده‌سازی کد و فریمورک بتوانیم آن را تست بکنیم و بررسی بکنیم که آیا Entities با کلاس‌ها سازگاری دارد یا خیر

معماری تمیز ( فصل ۲۲)

در سال‌های اخیر این موضوع خیلی مهم شده‌‌است و کتاب‌های زیادی در این باره نوشته شده است و تقریبا

  • همه به نوعی به دنبال اهداف زیر هستند
  • به فریمورک‌ها وابسته نباشد
  • نرم‌افزار قابلیت تست‌پذیری داشته باشد
  • به ظاهر UI وابسته نباشد
  • به دیتابیس و مدل‌های آن وابسته نباشد
  • مستقل از هر آژانس خارجی باشد

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

  • تعریف interface adapter: به طور کلی این بخش وظیفه دارد به نوعی دیتاهای خروجی را به فرمت دلخواهی که سیستم و مشتری نیاز دارد به نمایش بگذارد و شاید به نوعی GUI از این دسته قرار بگیرند.

اگر بخشی از موارد استفاده لازم بود یک استفاده از لایه‌های بیرونی در هسته انجام شود بهتر از از dynamic polymorphism استفاده شود

ارائه دهندگان و اشیاء فروتن (فصل ۲۳)

در این بخش یک پترن معرفی می‌کند که کار را برای تست آسان می‌کند می‌گوید ما چند مدل بخش داریم برخی هستند که به راحتی تست می‌شوند که هیچی آن‌ها را تست می‌کنیم ولی برخی مثل GUI کار بسیار سختی است که تست کنیم لذا می‌گوید آن‌ها را به عناصر داده‌ای که آن‌ها را میسازند تجزیه کنیم و آن‌ها را تست کنیم به عنوان مثال متنی که قرار است به نمایش گذاشته شود را قبل از به نمایش گذاشتن اندازه گیری کنیم. در دیتابیس نیز برای اینکه این موضوع برطرف گردد از یک gateway استفاده می‌شود.

مرزهای جزئی (فصل ۲۴)

در برخی از موارد ایجاد مرز‌ها بسیار کار سخت و دشواری است و نگهداری و تولید این مرز در حال حاضر ضرورتی ندارد لذا معماران سعی می‌کنند یک مرز جزئی را ایجاد کنند که بعدا اگر لازم شد آن را عمیق‌تر بکنند.به عنوان مثال ما تمام کارها را برای جداسازی دو بخش از کد انجام دادیم ولی فعلا آن‌ها را در دل یک کامپوننت قرار می‌دهیم تا بعدا در صورت نیاز بتوانیم آن‌ها را از یک دیگر جدا کنیم.البته یکی از مشکلات این رویکرد این است که به مرور زمان این مرزهای جزئی شروع به شکستن می‌شود و fitness رخ می‌دهد که در این صورت دیگر جداسازی و تشکیل دو کامپوننت مجزا کار بسیار سختی می‌شود.در این فصل سه مدل متفاوت توضیح داده‌ می‌شود که هر کدام از آن‌ها مزایا و خطراتی را در پی دارند

لایه‌ها و مرزها ( فصل ۲۵)

شاید در یک نرم‌افزار ساده شما فقط سه لایه دیتابیس و UI و قوانین کسب و کار را داشته باشید اما در بسیاری از نرم‌افزارها این لایه‌ها به شدت زیاد می‌شوند به عنوان مثال در یک بازی کامپیوتری این موضوع عوض می‌شود.همچنین در این فصل بیان می‌کند که ایجاد یک مرز گران است اما گران‌تر از آن ایجاد یک مرز بعد از انجام‌کار است زیرا تفکیک آن‌ها بسیار سخت است همچنین چندین مثال کاربردی بیان می‌شود که دسته‌بندی آن‌ها را در نمودارهایی آورده است.لذا شما به عنوان یک معمار خوب بیاد یک مقایسه و trade off انجام دهید شما باید هزینه ها را بسنجید و تعیین کنید که مرزهای معماری کجاست، و کدام مرزها باید کامل اجرا شوند و کدام یک به صورت جزئی و کدام یک بخاطر هزینه انجام نشوند و همه این‌ها در اول کار معلوم نیست بلکه بعد از گذشت زمان به مرور شفاف می‌شوند

کامپوننت اصلی (فصل ۲۶)

به طور کلی در بیشتر نرم‌افزار‌ها یک بخشی دارد که بقیه بخش‌ها را می‌سازد و فراخوان می‌کند ما به این بخش کامپوننت اصلی می گوییم و به نوعی نقطه شروع سیستم است. به طور کلی ممکن است که شما برای سناریو‌های مختلف مثل تست یا محصول یا توسعه خود main های مختلفی داشته باشید که inistal اولیه را به طور خاص اجرا کند و ریسورس‌های لازم را برای اجرای نرم‌افزار فراهم کند یا برای مشتریان و یا کشورهای مختلف نیز ما می‌توانیم Main متفاوتی را اجرا کنیم

خدمات:کوچک و بزرگ (فصل ۲۷)

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

مرز آزمون (فصل ۲۸)

بخش تست جزوی از سیستم است و اهمیت آن مانند بقیه بخش‌های یک سیستم نرم‌افزاری است. در معماری ما تمام مدل‌های تست را یک مدل در نظر می‌گیریم لذا وارد جزئیات این بخش‌ها نمی‌شویم. همواره تست است که به کد وابسته است و رابطه برعکس هرگز وجود ندارد به نوعی دیگر تست را شما می‌توانید در بیرونی‌ترین لایه در نظر بگیرید همچنین آن‌ها برای عملکرد کامل سیستم توسعه نیافتند و ضرروی نیستند و آمده‌اند که به برنامه‌نویسان کمک کنند نه به کاربران. تست هایی که به خوبی در طراحی سیستم ادغام نشده اند، معمولا شکننده هستند و سیستم را سفت و سخت می کنند و تغییر آن را دشوار می کنند. یعنی به نوعی تست‌ها با نرم‌افزار رشد و تغییر می‌کنند و هیچگاه رشد‌ آنها نباید از رشد نرم‌افزار عقب بیوفتد. تست نباید به GUI وابسته باشد زیرا این بخش بسیار آسیب‌پذیر و تغییر پذیر است

معماری جاسازی شده پاک (فصل ۲۹)

داگ ادعای زیر را داشت:"اگرچه نرم افزار فرسوده نمی شود، سیستم عامل و سخت افزار منسوخ می شوند و در نتیجه نیاز به تغییرات نرم افزاری دارند." اگر شما بر روی سیستم‌های سخت‌افزاری کد نوشته باشید این را به خوبی درک‌ می‌کنید و متوجه می‌شوید که به سرعت این تغییر‌ها به نرم‌افزار شما اعمال می‌شود لذا شما برای ایجاد عمر طولانی برای نرم‌افزار خود باید این نکته را به خوبی در نظر داشته باشید شاید جمله بهتری که می‌توانیم بگوییم این باشد:"اگرچه نرم افزار فرسوده نمی شود، اما می تواند از درون توسط وابستگی های مدیریت نشده به سیستم عامل و سخت افزار از بین برود."

یک تعریفی نیز درباره سیستم‌عامل بیان می‌کند:سیستم عامل به این معنی نیست که کد در ROM ذخیره سازی می‌شود و به دلیل جایی که ذخیره می شود، سیستم عامل است. بلکه به دلیل اینکه به چیزی بستگی دارد و تغییر آن با تکامل سخت افزار است، یک سیستم عامل است. سخت‌افزار تکامل می‌یابد ، بنابراین باید کد تعبیه‌شده‌مان را با در نظر گرفتن این واقعیت مجددا ساختار دهیم. و در انتها یک معماری لایه‌ای را نشان می‌دهد که در پایین سخت افزار و سپس لایه بعدی نحوه درایو آن و در لایه بعدی ارتباطات و در لایه بعدی سیستم عامل و در انتها نرم‌افزار شما قرار میگیرد که با این رویکرد شما بدون در نظر گرفتن سخت افزار می‌توانید نرم‌افزار خود را تست کنید و شاید برایتان سوال شود که چه مدل OS مدنظر است در این بخش اقلب RTOS ها قرار می‌گیرند

پایگاه داده به عنوان یک جزئیات (فصل ۳۰)

رابطه پایگاه داده با معمار نرم‌افزار بسیار ناچیز است و چیزی شبیه به ارتباط دستگیره در ساختمان با معمار نرم‌افزار است. و پایگاه داده صرفا یک ابزار است برای رسیدن به داده‌ها نه چیز بیشتری و یک معمار خوب هیچگاه اجازه نمی‌دهد که یک جزئیات تغییراتی در معماری نرم‌افزار ایجاد کند.سپس تاریخچه شروع دیتابیس‌ها از نوشتن بر روی دیسک تا ایجاد RDBMS را مطرح می‌کند که وظیفه ذخیره‌سازی دیتاها در فایل‌های داکیومنت را بر عهده داشت. و بیان می کند که پایگاه داده رابطه‌ای نیاز به جدول دارد و به کمک زبان sql شما می‌توانید اطلاعات را بدست بیاورید و در زمان قدیم که این موضوع نبود ما به کمک ساختار‌هایی مانند linklist و pointer می‌توانستیم اطلاعات مورد نیاز را از داخل رم استخراج کنیم.

وب یک جزئیات است (فصل ۳۱)

وب یک حرکت نوسانی است در ابتدا ما سعی کردیم تمام قدرت را از کامپیوتر‌ها به سمت سرور‌ها ببریم سپس مرورگرها آمدند و برخی موارد مجدد برگشتند به این سمت مثل js ولی حالا سعی داریم این بخش را به کمک node به سمت back بازگردانیم و این مدل شبیه به یک آونگ است.به نظر نمی رسد ما بفهمیم که قدرت کامپیوتر را کجا می خواهیم. ما بین متمرکز کردن و توزیع آن به عقب و جلو می رویم. به عنوان مثال در قدیم معماری بر روی کامپیوترهای شخصی بود و سپس سعی شد مرکز گرا بشوند و الان تلاش بر این است که توزیع شده باشد آیا واقعا معماری باید وابسته به این باشد؟ به طور کلی کتاب می‌گوید که وب نوعی از GUI است و GUI خیلی به مرور زمان تغییر می‌کند و خود نیز جزوی از جزئیات است پس وب هم جزوی از جزئیات است و نباید به آن وابسته باشیم.

فریمورک یک جزئیات است (فصل ۳۲)

فریمورک‌ها بسیار محبوب شده‌اند و پر استفاده و بسیاری از آن‌ها رایگان است. نویسندگان این فریمورک‌ها بر اساس نیاز خود و دوستان خود آن را توسعه می دهند و دقیق با مشکلات و موضوع کاری شما آشنا نیستند لذا لزومی ندارد که این کدها برای کار شما بهینه باشد. ارتباط کد شما با یک فریمورک مانند یک ازدواج نامتقارن است شما بسیار تعهد دارید و خیلی از موارد را رعایت می‌کنید ولی نویسنده فریمورک هیچگونه تعهدی به کد شما ندارد! و به نوعی شما را نیز مجبور می‌کند که به توصیه‌های او توجه کنید و به نوعی کد او را به مرکز معماری خود منتقل کنید همان جایی که قوانین کسب‌وکار قرار گرفته‌اند.همچنین ممکن است که فریمورک در نسخه جدید خود برای شما مشکل ساز بشود و به ضرر شما باشد همچنین ممکن است که یک فریمورک دیگری بیاید و شما آرزو کنید که کاشکی می‌توانستم فریمورک خود را تغییر بدهم.راه‌حل کتاب این است که به هیچ عنوان با یک فریمورک ازدواج نکنید اگر فریمورک اهداف بیزینس شما رو تحت تاثیر قرار می‌دهد شما نباید از آن استفاده کنید در واقع نباید کد‌های لایه بالای شما متوجه این موضوع بشوند که شما از چه فریمورکی استفاده می‌کنید

مطالعه موردی: فروش ویدئو (فصل ۳۳)

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

در عکس بالا تمام بازیگران و ویژگی‌هایشان به نمایش گذاشته شده است.بخش view catalog یک بخش کلی است که ما می‌توانیم به صورت abstract از آن استفاده کنیم برای دو دسته از بازیگران. در عکس زیر نیز دیاگرام کلی برای کامپوننت‌ها طراحی شده است

همانطور که مشاهده می‌کنید برای هر بازیگر یک سری کامپوننت تعریف شده است همچنین در کتاب برای راحت‌تر شدن کد و توسعه آن پنج فایل jar-یکی برای نماها، ارائه‌کنندگان، تعامل‌کننده‌ها، کنترل‌کننده‌ها و برنامه‌های کاربردی تخصیص می‌دهد(البته مدل‌های دیگر نیز می‌شود دسته بندی کرد).

فصل گم شده (فصل ۳۴)

در ابتدا یک معماری لایه‌ای مثال می‌زند و می‌گوید این معماری برای پروژه‌های کوچیک که لازم است خیلی سریع راه‌اندازی شوند بسیار خوب است اما وقتی نرم‌افزار با پیچیدگی‌های جدید قرار است ترکیب شود شما خواهید فهمید که فقط سه سطح که در معماری لایه‌ای مطرح است کافی نیست و شما باید چند بخش دیگر نیز داشته باشید از طرف دیگر اصلی که در فصل‌های گذشته خواندید که کدهای سطح بالا باید نشان دهنده کسب‌وکار باشند و کمتر درگیر کدهای جزئی باشند رعایت نمی‌شود و بعد از مدتی نرم‌افزار شما در معماری لایه‌ای به مشکل خواهد خورد. مدل دیگر معماری عمودی است یعنی براساس ویژگی‌های نرم‌افزاری و کاربرد هر بخش از کد جداسازی انجام شود اما با این رویکرد کدهای سطح بالا که قرار بود ویژگی‌های کسب‌وکار را فریاد بزنند دیگر وجود ندارند البته این رویکرد برای اصلاح و تغییر ویژگی‌ها خوب است زیرا هر گروه یا بخش مسئولیتی مشخص را بر عهده دارد. اما معماری کتاب یک چیزی بینا بین این دو حالت است و سعی کرده خوبی‌های برش افقی و عمودی را با یکدیگر داشته باشد و هر چقدر کدها به مرکز نزدیک‌تر باشند یعنی کدهای مرتبط تری به کسب‌وکار هستند و هر چقدر دورتر باشند یعنی به محیط بیرونی اتصال پیدا می‌کند به عنوان مثال دیتابیس و UI ,....

در معماری لایه‌ای تمام فلش‌ها همیشه به سمت پایین است و اگر یک نیرو جدید و تازه نفس بیاید و بخواهد یک ویژگی جدید توسعه دهد شاید معماری لایه‌ای را خراب کند و معماری کتاب کمی در این باره بهتر عمل می‌کند زیرا هر چرخه یا ویژگی از لایه بیرونی به داخل و سپس به خارج میرود و می‌شود. سعی کنید تا جایی که میشه وابسته به جزئیات نباشید زیرا تمام خطرات و نگرانی‌ها در این بخش از کد هستند و به گفته کتاب شیطان در این بخش است.

توسعهٔ نرم‌افزارُمعماری نرم‌افزاررابط کاربریبرنامه نویسی
شاید از این پست‌ها خوشتان بیاید