جلوگیری از وابستگیهای چرخشی با استفاده از SDP
وابستگیهای چرخشی (Circular dependencies) قاتلان خاموش هستند. آنها باعث خطای بیلد نمیشوند و در زمان وارد کردن (import) نیز باعث استثناهای زمان اجرا نمیگردند. در عوض، آنها باعث ایجاد مقادیر تعریفنشده (undefined) بسیار ظریفی میشوند که هفتهها بعد در محیط تولید (production) خود را نشان میدهند.
یک چرخه زمانی رخ میدهد که ماژول A از B وارد (import) کند و B نیز از A وارد کند.
جاوااسکریپت این وارد کردنها را بهصورت خاموش حل میکند. اگر ماژول A هنوز در حال بارگذاری باشد و ماژول B آن را درخواست کند، جاوااسکریپت یک شیء خالی (empty object) برمیگرداند. کد شما بعداً با خطا مواجه میشود و ردپای خطا (stack trace) نقطه اشتباهی را نشان میدهد.
شما میتوانید این مشکل را با dependency-cruiser حل کنید. این ابزار فایلهای شما را اسکن کرده و گراف وابستگی شما را ترسیم میکند. این ابزار با TypeScript و monorepoها سازگار است.
نحوه راهاندازی:
- آن را به وابستگیهای توسعه (dev dependencies) خود اضافه کنید:
yarn add -D dependency-cruiser - یک اسکریپت به
package.jsonخود اضافه کنید:"depcruise": "depcruise packages --config .dependency-cruiser.js" - یک فایل
.dependency-cruiser.jsبرای شناسایی چرخهها ایجاد کنید.
اما پیدا کردن چرخه تنها نیمی از مسیر است. شما باید از شکلگیری آنها جلوگیری کنید.
از اصل وابستگیهای پایدار (Stable Dependencies Principle یا SDP) استفاده کنید. این قانون میگوید که شما باید در جهت پایداری وابستگی ایجاد کنید.
پایداری یک ویژگی ساختاری است. یک ماژول زمانی پایدار است که ماژولهای زیادی به آن وابسته باشند. اگر یک ماژول پایدار را تغییر دهید، بر افراد زیادی تأثیر میگذارید. همین هزینه است که آن را پایدار میکند.
از فرمول ناپایداری استفاده کنید:
I = Fan-Out / (Fan-In + Fan-Out)
• I = 0 یعنی ماژول در بالاترین سطح پایداری قرار دارد. همه چیز به آن وابسته است و آن به هیچ چیز وابسته نیست.
• I = 1 یعنی ماژول در بالاترین سطح ناپایداری قرار دارد. آن به چیزهای زیادی وابسته است و هیچ چیز به آن وابسته نیست.
قانون: امتیاز ناپایداری یک ماژول باید بیشتر از امتیاز هر ماژولی باشد که از آن وارد (import) میکند. فلشهای شما باید به سمت ناپایداری کمتر اشاره کنند.
ابزارهای کمکی (utils) سطح پایین شما (I ≈ 0) هرگز نباید از صفحات (pages) سطح بالا (I ≈ 1) وارد کنند.
شما میتوانید این اصل را با dependency-cruiser به یک قانون خودکار تبدیل کنید. به جای اینکه فقط چرخهها را بررسی کنید، جهت وابستگی را بررسی کنید:
- جلوگیری از وارد کردن (import) از ویژگیها (features) توسط ابزارهای کمکی (utils).
- جلوگیری از وارد کردن (import) از صفحات (pages) توسط ویژگیها (features).
این کار شرایط ساختاری که باعث ایجاد چرخهها میشوند را متوقف میکند. شما از حالت واکنش نشان دادن به باگها خارج شده و شروع به پیشگیری از آنها میکنید.
