بازگشت به کتاب‌ها
جلد کتاب معماری تمیز نوشتهٔ رابرت سی. مارتین

معماری تمیز

نوشتهٔ رابرت سی. مارتین · سال انتشار 2017

نظام‌مندترین بررسیِ جهت وابستگی و مرزها در طراحی نرم‌افزار — بازدهی‌اش واقعی است، اما فقط برای خواننده‌ای که نظم «کد تمیز» را از قبل دارد.

نقاط قوت

  • قانون وابستگی و دیاگرام‌های مرزی واژگانی برای تصمیم‌های معماری می‌دهند که در غیر این صورت ضمنی می‌ماندند
  • مستقل از فریم‌ورک است — ایده‌ها از هر استکِ خاصی عمر بیشتری دارند

نقاط ضعف

  • سطحی از نظم (و اندازهٔ تیم) را فرض می‌گیرد که بسیاری از پروژه‌های کوچک ندارند؛ اجرای بیش‌ازحدش هزینهٔ واقعی اضافه می‌کند
  • برخی ادعاهای جزم‌گرایانه‌تر مارتین (مثلاً دیتابیس را «جزئیات» دانستن) با مخالفت به‌جای اهل فن روبه‌رو شده

خلاصه کتاب

استدلال رابرت سی. مارتین در «معماری تمیز» از ادعایی شروع می‌شود که بدیهی به نظر می‌رسد اما بیشتر کدبیس‌ها نقضش می‌کنند: معماری یک سیستم نرم‌افزاری باید به تو بگوید سیستم چه کار می‌کند، نه اینکه با چه فریم‌ورکی ساخته شده. یک پروژهٔ معمولی را باز کن و پوشه‌های سطح بالا اعلام می‌کنند: ریلز، یا اسپرینگ، یا Next.js. موضع مارتین این است که این وارونه است — فریم‌ورک یک سازوکار تحویل است، یک جزئیات، و اجازه‌دادن به آن برای اشغال مرکز طراحی یعنی پرنوسان‌ترین بخش سیستم همان بخشی است که همه‌چیز به آن وابسته است.

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

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

ایده‌های کلیدی

۱. قانون وابستگی

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

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

همین یک قاعده است که بقیهٔ معماری را کارآمد می‌کند. بدون آن، «لایه‌ها» تزئینی‌اند — یک پروژه می‌تواند پوشه‌ای به نام domain داشته باشد که ORM را import می‌کند، و در آن نقطه دامنه یک لایه نیست، یک قرارداد نام‌گذاری است.

۲. فریم‌ورک‌ها، دیتابیس‌ها و وب جزئیات‌اند

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

همین منطق دربارهٔ وب هم صدق می‌کند: HTTP یک سازوکار تحویل است، از دید برنامه یک دستگاه ورودی/خروجی. اگر قواعد کسب‌وکار طوری نوشته شوند که یک درخواست وب فقط یکی از چند راه ممکن برای فراخوانی‌شان باشد، همان قواعد می‌توانند بدون تغییر با یک CLI، یک مصرف‌کنندهٔ صف، یا یک بستر تست اجرا شوند — که، نه به‌طور تصادفی، همان چیزی است که آن‌ها را بدون بالاآوردنِ یک سرور قابل‌تست می‌کند.

۳. معماری دربارهٔ به تعویق انداختن تصمیم‌هاست

یک مضمون تکرارشونده این است که یک معماری خوب تعداد تصمیم‌هایی که هنوز گرفته نشده‌اند را بیشینه می‌کند. مارتین استدلال می‌کند هدف کار معماریِ اولیه، انتخاب سریع دیتابیس یا فریم‌ورک درست نیست — ساختاردهی سیستم است طوری که آن انتخاب‌ها بتوانند دیر گرفته شوند، وقتی اطلاعات بیشتری هست، و اگر اشتباه از آب درآمدند بعداً عوض شوند.

این معنای «کار معماری» را بازتعریف می‌کند. کمتر دربارهٔ انتخاب فناوری از پیش است و بیشتر دربارهٔ برقرارکردن مرزهایی که یک انتخاب فناوری، وقتی گرفته شد، مهار شود نه فراگیر. تصمیمی که به یک آداپتور دست می‌زند برگشت‌پذیر است؛ همان تصمیم پخش‌شده در سیصد فایل نیست.

۴. اصول انسجام و جفت‌شدگیِ کامپوننت

پیش از فصل‌های معماری، مارتین اصول سطح-کامپوننت را پوشش می‌دهد که کمتر از SOLID به آن‌ها توجه می‌شود اما احتمالاً در مقیاس بزرگ‌تر تحمل‌کنندهٔ بار بیشتری‌اند. اصول انسجام تعیین می‌کنند کدام کلاس‌ها به یک کامپوننت قابل‌استقرار تعلق دارند — «اصل بستار مشترک» کلاس‌هایی را گروه می‌کند که به دلایل یکسان تغییر می‌کنند، درحالی‌که «اصل هم‌ارزی بازاستفاده/انتشار» می‌گوید واحد بازاستفاده همان واحد انتشار است.

اصول جفت‌شدگی سپس وابستگی‌های میان کامپوننت‌ها را تعیین می‌کنند: «اصل وابستگی‌های بدون دور» (هیچ دوری در گراف وابستگی کامپوننت‌ها) آن یکی است که نقضش فوری‌ترین درد را دارد، چون یک دور وابستگی یعنی دو کامپوننت دیگر هرگز نمی‌توانند مستقل ساخته، تست یا منتشر شوند.

برای چه کسی مفید است

  • توسعه‌دهندگانی که دیده‌اند یک کدبیس غیرقابل‌تغییر می‌شود — کتاب علت‌های ساختاریِ مشخص را نام می‌برد، به‌جای مقصر دانستن انضباط.
  • هرکسی که سیستمی طراحی می‌کند که انتظار می‌رود از فریم‌ورک فعلی‌اش عمر بیشتری کند — قانون وابستگی دقیقاً ابزار همین کار است.
  • مهندسانی که از نوشتن فیچر به گرفتن تصمیم‌های معماری منتقل می‌شوند — اصول کامپوننت شکافی را پر می‌کنند که بیشتر آموزش‌ها کاملاً از آن رد می‌شوند.
  • تیم‌هایی که برای تست منطق کسب‌وکار مشکل دارند — بیشتر تست‌ناپذیری‌ای که کتاب تشخیص می‌دهد از وابستگیِ سیاست به ورودی/خروجی می‌آید، که معماری مستقیماً به آن می‌پردازد.
اگر داری چیزی کوچک، کوتاه‌عمر یا واقعاً به‌شکل CRUD می‌سازی، اجرای کامل این احتمالاً بیشتر از آنچه برمی‌گرداند هزینه دارد. لایه‌ها، اینترفیس‌ها و لایه‌های واسط قیمت واقعی دارند، و مارتین نسبتاً کم دربارهٔ اینکه چه زمانی این معامله ارزشش را ندارد می‌گوید — آن قضاوت به عهدهٔ توست.
مارتین چند موضع را با قطعیتی بیشتر از آنچه حرفه واقعاً بر سرش توافق دارد بیان می‌کند — به‌ویژه «دیتابیس یک جزئیات است» با مخالفت جدی اهل فن روبه‌رو می‌شود که اشاره می‌کنند تصمیم‌های مدل داده اغلب کم‌برگشت‌پذیرترین تصمیم‌های یک سیستم‌اند، نه بیشترین. استدلال را بخوان، نه فقط نتیجه‌گیری‌ها را، و انتظار داشته باش جاهایی مخالف باشی.

سؤالات پرتکرار

باید اول «کد تمیز» را بخوانم؟

نه، این دو در مقیاس‌های متفاوتی عمل می‌کنند و می‌شود مستقل خواندشان. «کد تمیز» دربارهٔ توابع و کلاس‌هاست؛ این کتاب دربارهٔ کامپوننت‌ها و مرزهاست. با این حال، نظمی که «کد تمیز» یاد می‌دهد اینجا فرض گرفته شده — کدبیسی با معماری تمیز و توابع ناخوانا هنوز سخت است که در آن کار کنی.

این همان معماری شش‌ضلعی یا «پورت‌ها و آداپتورها» است؟

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

این برای کار فرانت‌اند هم صدق می‌کند یا فقط بک‌اند؟

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

آیا این همه لایهٔ واسط، مهندسیِ بیش‌ازحد نیست؟

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

ضعف اصلیِ کتاب چیست؟

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

این مطلب برایتان مفید بود؟

شمارش آرا پس از ۵ رأی نمایش داده می‌شود.

بیشتر در همین دسته