چه تکنولوژی می‌خواهید یاد بگیرید؟

نظرات و انتقادات خود را با ما در میان بگذارید.

آپدیت روزانه

بیش از 1000 پست آموزشی

نیازهای روز

5 اصل پایه طراحی شی‌گرا - بخش 2

اولین اصل پایه در مدیریت وابستگی(Dependency Managemet) در توسعه‌ی برنامه‌های شی‌گرا، Single Responsibility Principle یا به اختصار S.R.P خوانده می‌شود که تعریف آن به صورت زیر نگاشته‌اند:

A class should have one and only one reason to change, meaning that a class should have only one job.

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

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

روبرو شدن با متدهای N خط کد که حتی اصول پایه در آن پروژه به خوبی رعایت نشده باشد دلیل نخواهد شد آن سامانه کنار گذاشته شود در واقع شما استخدام شده‌اید سامانه را نظم و توسعه دهید. برای مثال می‌توان از کلاس‌های که دو مسئولیت همراه هستند استفاده نمود و به دو کلاس با مسئولیت واحد تقسیم کرد.

هر گاه یک کلاس بیش از چند مسئولیت را شامل شود با اعمال تغییر در آن کلاس، کلاس‌های دیگر دستخوش تغییرات خواهند بود در واقع fragility نامیده می‌شود البته مرور زمان با رعایت اصل پایه این کلاس‌ها هم قابل اصلاح هستند.

اصل SRP توسط آقای رابرت سسیل مارتین در کتاب "Agile Software Development Principles, Patterns and Practices" تعریف گردید و بعدها نسخه‌های دیگر تحت عنوان "Agile Software Development Principles, Patterns and Practices in C#" تأليف شدند.

مزایای بکارگیری SRP شامل:

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

کلاس‌ها و اینترفیس‌ها زمانی پیچیدگی را شامل خواهند شد که آنها را مستلزم پیاده سازی‌ مسئولیت‌های مختلفی کنیم. ایده پایه SRP، جداسازی مسئولیت‌ها در کلاس‌ها و ماژول‌های مجزا است البته این رویکرد یک طراحی بد است که چند مسئولیت در یک کلاس بکار گرفته شود اگر چه مسئولیت‌ها ممکن است در طول زمان تغییر کنند با این حال اصل اول پایه در SOLD، سخت‌ترین اصل در پیاده سازی به حساب می‌آید و در صورت یک کلاس بیش ازیک مسئولیت را شامل شود کلاس تعریف شده اولین اصل پایه SOLD را نقض می‌کند.

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

مثال:

اینترفیس زیرا در نظر بگیرید که به عنوان اینترفیس پایه به منظور پیاده سازی مخزن جنریک بکار خواهیم برد:

public interface IRepository<T> where T : class
{
    void Create(T entity);
    void Save();
}

کلاس جدید ایجاد و اینترفیس فوق را به ارث خواهیم برد و نهایتا دو متد آن را پیاده سازی خواهیم کرد:

public  class Repository<D, T> : IRepository<T> where T : class where D : DbContext, new()
{
    D entities = new D();

    public  void Create(T entity)
    {
        entities.Set<T>().Add(entity);
    }

    public  void Save()
    {
        entities.SaveChanges();
    }
}

اکنون قصد داریم استثناهای که ممکن است در زمان اجرا برنامه رخ دهند را مدیریت کنیم، کد فوق به صورت زیر تغییر می‎دهیم:

public class Repository<D, T> : IRepository<T> where T : class where D : DbContext, new()
{
    D entities = new D();

    public void Create(T entity)
    {
        try
        {
          entities.Set<T>().Add(entity);
        }
        catch(Exception ex)
        {
          File.WriteAllText(@"D:\Error.log", ex.ToString());
        }
    }

    public void Save()
    {      
        try
        {
           entities.SaveChanges();
        }
        catch(Exception ex)
        {
           File.WriteAllText(@"D:\Error.log", ex.ToString());
        }
    }
}

کلاس Repository در واقع اصل پایه SOLD را نقض نموده است، این کلاس از تک مسئولیت بودن خارج شده و همین دلیل موجب نقض SRP خواهد شد. اصل SRP برای رفع این مشکل می‌گوید هر ماژول نرم افزاری می‌بایست تنها یک دلیل برای تغییر داشته باشد(منظور از ماژول نرم افزاری همان کلاس‌ها ، توابع و ... است و عبارت "دلیل برای تغییر" همان مسئولیت است).

public class FileLogger
{
	public string Path
	{
		get; set;
	}
	public void Log(string message)
	{
		File.WriteAllText(Path, message);
	}
}

بازنگری مجدد، کلاس جدید ایجاد که مسئولیت ثبت خطا فایل بر عهده دارد اکنون از این کلاس به منظور ثبت خطا استفاده می‌کنیم همچنین با ایجاد کلاس FileLogger در واقع مسئولیت ثبت خطا از کلاس Repository برداشته شده و اصل Single Responsibility Principle رعایت شده است.


...

امید نصری

0 نظر:

تعداد دیدگاه‌های کاربران : 0 دیدگاه
مهمان گرامی! برای ارسال نظر نیاز است وارد سایت شوید.


You must ورود to comment.