حفظ الگوهای طراحی معماری در مبانی کد در دراز مدت می تواند کاملاً چالش برانگیز باشد. اگر شما به عنوان معمار نرم افزار، قوانین و محدودیت هایی را در طراحی معماری خود لحاظ کردید و به دنبال این هستید که برنامه نویس ها در توسعه نرم افزار مجبور به رعایت این قوانین شوند، می توانید این محدودیت ها و قوانین را در قالب تست به معماری خود اضافه کنید.
کتابخانه ArchUnit تلاش می کند تا با ارائه تست هایی که قراردادها را در زمینه هایی مانند طراحی کلاس، نام گذاری و وابستگی در بر می گیرند، این مشکلات را برای پایه های کد مبتنی بر جاوا برطرف کند.
کتابخانه NetArchTest، یک پیاده سازی الهام گرفته شده از ArchUnit می باشد که برای پروژه های دات نت قابل استفاده می باشد.
چالش اصلی برای اجرای این امر، تعیین وابستگی بین لایه های مختلف است. لایه ها شروع به دور زدن یکدیگر می کنند، interfaceها به صورت تصادفی پیاده سازی می شوند، قراردادهای نامگذاری رعایت نمی شوند و غیره.
برای نشان دادن قابلیتهای ArchUnit، می توانیم الگوی معماری Clean Architecture را مثال بزنیم.
یکی از مهم ترین مبانی که در این معماری به آن اشاره می شود بدون شک لایه بندی آن است.
اگر با نگاه کردن به تصویر متوجه نشدید که دایره ها چه چیزی را نشان می دهند، اشکالی ندارد. افرادی که با Clean Architecture آشنایی ندارند اغلب نمی دانند که کدها را کجا باید توسعه دهند.
قانون آن این است که دایره یا لایه درونی، نباید به دنیای بیرون وابستگی داشته باشد. زیرا برای آن مهم نیست که شما از چه نوع دیتابیسی استفاده می کنید و یا از نتایج در چه مواردی استفاده می کنید. به همین دلیل است که جهت فلش ها به سمت داخل است.
یک تیم معمولاً به بررسی دستی کد تکیه میکند تا مطمئن شود آن لایه ها به درستی توسعه یافته اند. اما ArchUnit می تواند بررسی را به طور کامل خودکار می کند و زمان صرفه جویی شده در بررسی کد را می توان صرف موضوعات ارزشمندتر شود.
کتابخانه NetArchTest به عنوان یک پکیج در NuGet در دسترس است.
ساختن یک fluent API برای NetArchTest ساده است و به کاربران اجازه می دهد جملات منسجمی از گزاره ها، حروف ربط و شرایط ایجاد کنند.
نقطه شروع برای هر قانون، کلاس Types static است. جایی که شما مجموعه ای از typeها را از یک مسیر، اسمبلی یا namespace بارگذاری می کنید.
var types = Types.InAssembly(typeof(MyClass).Assembly);
هنگامی که typeها را انتخاب کردید، می توانید آنها را فیلتر کنید و با استفاده از And یا Or به هم متصل کنید:
types.That().ResideInNamespace("MyProject.Data"); types.That().AreClasses().And().HaveNameStartingWith("Base"); types.That().Inherit(typeof(MyBase)).Or().ImplementInterface(typeof(IExample));
هنگامی که مجموعه کلاس ها فیلتر شدند، میتوانید مجموعه ای از شرایط را با استفاده از متدهای Should یا ShouldNot اعمال کنید، به عنوان مثال:
types.That().ArePublic().Should().BeSealed();
در نهایت، با استفاده از یک اجرا کننده، نتیجه ای به دست می آورید. از GetTypes برای برگرداندن typeهایی که با قانون مطابقت دارند یا GetResult برای تعیین اینکه آیا قانون رعایت شده است یا خیر، استفاده می کنید.
var isValid = types.That().ResideInNamespace("MyProject.Data").Should().BeSealed().GetResult().IsSuccessful;
یکی از جنبه های جالب ArchUnit API، توانایی تعریف لایه ها است که می تواند برای اعمال بررسی وابستگی بین بخش های مختلف یک معماری استفاده شود.
var result = Types.InCurrentDomain() .That() .ResideInNamespace("NetArchTest.SampleLibrary.Presentation") .ShouldNot() .HaveDependencyOn("NetArchTest.SampleLibrary.Data") .GetResult();