از شخصی پرسیدن که دنیا رو چی استاده, گفت: «روی یه لاک پشت» دوباره ازش پرسیدن: «خب اون لاک پشت روی چی ایستاده؟» جواب داد: «روی یه لاک پشت دیگه!»
—Rev. Joseph Frederick Berg (1854)
این داستان کوتاه به یک استدلال فلسفی/منطقی به نام تسلسل بی پایان (Infinite Regress) اشاره دارد. تسلسل بی پایان زمانی رخ می دهد که برای توضیح یک مسئله به پاسخ دیگری نیاز می باشد و این فرایند به شکل بی پایان ادامه دارد بدون آنکه به یک نقطه پایان و نتیجه نهایی برسیم! این داستان نه تنها در فلسفه بلکه در دنیای طراحی نرم افزار نیز وجود دارد و با این موقعیت ها روبرو می شویم. تسلسل بی پایان در طراحی و پیاده سازی نرم افزار به وابستگی های زنجیره ای و بی پایان اشاره دارد که بسیاری از ما با آنها روبرو هستیم.
در دنیای نرم افزار تسلسل بی پایان می تواند به شکل هایی مانند Circular Dependencies و نبود مرزبندی های مشخص بین ماژول ها و سرویس ها رخ دهد. برای مثال اگر ماژول های مختلف یک سیستم بدون مرزهای مشخص به هم وابسته باشند احتمال ایجاد وابستگی ها و مشکلات ناشی از آن زیاد می باشد که می تواند باعث ایجاد مشکلاتی مانند پیچیدگی در نگهداری, توسعه و تست سیستم شود. به دلیل اینکه هر تغییر در یک بخش به دلیل وجود وابستگی ها می تواند به صورت زنجیره ای بخش های دیگر را ایمپکت کند و باعث بروز خطاهای ناخواسته شود.
برای جلوگیری از این وضعیت و حفظ یکپارچگی سیستم باید اصول طراحی سیستم را رعایت کنیم. برای مثال در طراحی میکروسرویس ها با استفاده از اصولی مانند Loose Coupling و High Cohesion میتوانیم تا حدود زیادی از این وابستگی ها جلوگیری کنیم. به زبان ساده تر هر سرویس باید تنها بر وظایف خود تمرکز کند و اطلاعات داخلی خودش را از سرویس های دیگر مخفی/پنهان نگه دارد تا به جای وابستگی های دوطرفه یک ساختار مستقل تر و پایدارتر ایجاد شود. پیشنهاد میکنم برای اطلاعات بیشتر در رابطه با مرزبندی میکروسرویس ها فصل دوم کتاب Building Microservices رو مطالعه کنید.
بیایید یک مثال عملی را بررسی کنیم. فرض کنید که می خواهیم یک سیستم احراز هویت را طراحی کنیم, این سیستم به شکل کلی و ساده شامل ماژول های زیر می باشد:
کاربر: برای مدیریت کاربران.
احراز هویت: برای تایید هویت کاربران.
ایمیل: برای ارسال ایمیل های تایید و اطلاع رسانی.
اگر در اینجا ماژول ایمیل برای دسترسی به اطلاعات کاربر به ماژول احراز هویت و ماژول احراز هویت برای ارسال کد تایید به ماژول ایمیل وابسته باشد, یک circular dependency ایجاد کرده ایم که مشکلاتی مانند تست و نگهداری را برای ما ایجاد میکند. حال برای اینکه درگیر این مشکل نشویم می توانیم از اینترفیس های مشترک و جدا کردن وظیفه آنها استفاده کنیم. یعنی ماژول ایمیل فقط به اینترفیس مربوط به User دسترسی داشته باشد که توسط ماژول کاربر پیاده سازی شده است تا به این شکل وابستگی یک طرفه باشد.