نگه‌داری ساده‌تر نرم‌افزار با معماری Vertical Slices - قسمت اول
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: سه دقیقه

معمولا معماری‌های ارائه شد،ه بر اساس جداسازی لایه‌های نرم‌افزار می‌باشد. برای مثال در معماری Hexagonal که آن‌را به Port & Adaptor هم میشناسیم، نرم‌افزار، با استفاده از لایه‌های Domain، Application، Infra و ... تفکیک می‌شوند. منطق تجاری در Domain پیاده سازی می‌شود و رابط‌های مربوط به کار با دیتا تعریف می‌شوند. در لایه‌ی Application، Portها و Adaptorهای مورد نیاز برای استفاده، پیاده‌سازی می‌شوند. در لایه‌ی Infra، رابط‍‌های تعریف شده در Domain پیاده‌سازی شده و در لایه‌ی Application، Adaptorهای پیاده‌سازی شده مورد استفاده قرار میگیرند.
تمام این اتفاقات در سطح لایه‌های برنامه اتفاق می‌افتند و بر همین اساس ما نیاز داریم برای جلوگیری از تغییرات بزرگ، از Abstraction استفاده کنیم و بسیار زیاد استفاده میکنیم. Abstraction یکی از راه‌های غیرمستقیم (InDirection) کردن دسترسی فراخوان به منبع یا تارگت مورد نظر می‌باشد که مزایای زیادی را مانند استفاده‌ی مجدد، جداسازی بخش‌هایی که باعث پیچیدگی می‌شوند و همچنین مخفی کردن وابستگی‌ها برای ما دارد.

 

Abstraction



می‌دانیم که غیرمستقیم کردن دسترسی به منابع در طراحی نرم‌افزار یک اصل است. اما Abstraction تنها راه جداسازی نیست. راه دیگر طراحی زیرساخت می‌باشد. مانند استفاده از Message Queue (مانند استفاده از MediatR) و یا Load Balancer. 



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

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

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

اما Vertical Slices چگونه به ما در این زمینه کمک میکند. در این معماری، ما به جای تمرکز بر روی لایه‌ها، تمرکز خود را روی فیچرها میگذاریم. در واقع نرم‌افزار را به قسمت‌های بسیار کوچکتری تقسیم میکنیم و از Abstraction اضافی جلوگیری میکنیم. در این صورت اگر تغییری لازم به اعمال شدن دارد، در سطح فیچر اعمال می‌شود و نه در سطح لایه‌ها. در ضمن دیگر Repository و یا Specification ی برای تست وجود ندارد؛ پس میزان تست‌های نوشته شده کاهش پیدا می‌کنند و طبیعتا برای تست Integration میتوانیم کل فیچر را تست کنیم.

در اینجا ما بجای تمرکز بر روی ساختار کل کدبیس، تمرکز خود را بر روی ساختار کدبیس یک فیچر خاص نگه میداریم. 

در Vertical Slices Arch ما مشکلی با اشتراک‌گذاری Domain بین فیچر‌ها نداریم. زیرا Domain ما به هیچ فریموورکی وابسته نیست و بصورت مستقیم مورد استفاده قرار میگیرد. لطفا به تصویر زیر توجه بفرمایید:

 

Vertical Slices Arch


زمانیکه این فیچرهای کوچک توسعه داده می‌شوند، دلیلی برای تعریف Repository و یا Specificationهای بی مورد نداریم. پس میتوانیم به راحتی آن‌ها را حذف کنیم و به صورت مستقیم از EF و یا هر ORM دیگری استفاده کنیم و یا میتوانیم به راحتی از Raw Query‌ها و مزیت آن‌ها بهره‌مند شویم. نگه‌داری یک فیچر کوچک که Command، Handler و Viewها و سایر نیازمندی‌هایش(به استثنای Domain) داخل خودش قرار گرفته و شامل یک ساختار ویژه‌ی خودش با توجه به نیازمندی‌های تعریف شده می‌باشد، بسیار کار ساده‌تری است تا نگه‌داری یک سری لایه که به صورت گسترده از Abstraction در آن‌ها استفاده شده‌است.