اصول طراحی SOLID در #C (قسمت اول)

اصول طراحی SOLID در #C اصول اولیه طراحی هستند.
کلمه SOLID مخفف اصول زیر می باشد :
- Single Responsibility Principle (SRP)
- Open closed Principle (OSP)
- Liskov substitution Principle (LSP)
- Interface Segregation Principle (ISP)
- Dependency Inversion Principle (DIP)
در این مطلب اصول SOLID را با مثال هایی در #C خواهیم آموخت.
دلیل اکثر برنامه های ناموفق
توسعه دهندگان با استفاده از دانش و تجربه خود شروع به ساخت نرم افزار با طراحی های خوب و مرتب می کنند. اما با گذشت زمان، برنامه ها ممکن است باگ هایی ایجاد کنند که طراحی برنامه باید برای هر “درخواست تغییر” یا “درخواست ویژگی جدید” تغییر یابد. به همین دلیل پس از مدتی ممکن است برای این تغییرات با مشکلات زیادی روبرو شویم، اما این به این معنا نیست که درخواستهای تغییر یا ویژگیهای جدید مقصر هستند بلکه آنها بخشی از توسعه نرم افزار هستند. ما نمی توانیم آنها را متوقف کنیم یا آنها را رد کنیم. پس مقصر اینجا کیست؟ بدیهی است که مقصر نوع طراحی برنامه است.
موارد زیر ایرادات طراحی هستند که بیشتر در نرم افزار باعث آسیب می شوند.
- سپردن مسئولیت های بیشتر به کلاس ها : با سپردن مسئولیت های بیشتر به کلاس ها، استرس بیشتری به کلاس ها وارد کنید. (بسیاری از عملکردها مربوط به یک کلاس نیست.)
- وادار کردن کلاس ها به وابستگی به یکدیگر: اگر کلاسها به یکدیگر وابسته باشند (به عبارت دیگر بهطور محکمی با هم پیوند خوردهاند)، تغییر در یکی بر دیگری تأثیر میگذارد.
- نوشتن کد تکراری در نرم افزار
راه حل
- انتخاب معماری صحیح : ( MVC, MVP, MVVPمعماری سه لایه و غیره)
- پیروی از اصول طراحی :انتخاب الگوهای طراحی صحیح برای ساخت نرم افزار.
اکنون ابتدا اصول طراحی را مرور می کنیم.
مقدمه ای بر اصول SOLID
اصول SOLID اصول طراحی هستند که ما را قادر می سازند تا اکثر مشکلات طراحی نرم افزار را مدیریت کنیم. رابرت سی مارتین این اصول را در دهه 1990 گردآوری کرد. اصول طراحی به شما کمک می کند تا کدی را پیاده سازی کنید که بتوانید با در نظر گرفتن انعطاف پذیری، گسترش پذیری، خوانایی و نگهداری، طرحی را ایجاد کنید. با دانش و استفاده مناسب از اصول طراحی، توسعه دهندگان می توانند راهنمایی هایی را در زمینه نوشتن کدهایی دریافت کنند که دارای اتصالات سست، قابل آزمایش و همچنین قابل نگهداری هستند.
هنگامی که این اصول را یاد گرفتید وسوسه خواهید شد که آنها را در همه جای کد خود اعمال کنید، اما مراقب باشید که این اصول در همه شرایط مناسب نیستند. گاهی اوقات با به کار بردن اصول، قطعه کد خود را بیش از حد مهندسی می کنید و پیچیدگی های غیر ضروری را اضافه می کنید.
S: Single Responsibility Principle (SRP)
شعار : هر ماژول نرم افزاری باید تنها یک دلیل برای تغییر داشته باشد.
این بدان معناست که هر کلاس یا ساختار مشابه در کد شما باید فقط یک کار برای انجام داشته باشد، همه چیز در آن کلاس باید به یک هدف واحد مرتبط باشد، کلاس ما نباید مانند یک چاقوی سوئیسی باشد که اگر یکی از آنها نیاز به تغییر داشته باشد، کل ابزار باید تغییر کند. این بدان معنا نیست که کلاس های شما فقط باید دارای یک متد یا ویژگی باشند،بلکه ممکن است کلاس دارای اعضای زیادی باشد به شرطی که به مسئولیت واحد مربوط باشند.
اصل مسئولیت واحد راه خوبی برای شناسایی کلاسها در مرحله طراحی یک برنامه کاربردی به ما میدهد و باعث میشود به تمام راههایی که یک کلاس میتواند تغییر کند فکر کنید. تفکیک مناسب مسئولیت ها تنها زمانی انجام می شود که تصویر کاملی از نحوه عملکرد برنامه داشته باشیم. اجازه دهید این را با یک مثال بررسی کنیم.
public class UserService
{
public void Register(string email, string password)
{
if (!ValidateEmail(email))
throw new ValidationException("Email is not an email");
var user = new User(email, password);
SendEmail(new MailMessage("mysite@nowhere.com", email) { Subject="HEllo foo" });
}
public virtual bool ValidateEmail(string email)
{
return email.Contains("@");
}
public bool SendEmail(MailMessage message)
{
_smtpClient.Send(message);
}
}
کد بالا از SRP پیروی نمی کند. متدهای SendEmail و ValidateEmail هیچ ربطی به کلاس UserService ندارند پس کد بالا را به صورت زیر باز سازی می کنیم.
public class UserService
{
EmailService _emailService;
DbContext _dbContext;
public UserService(EmailService aEmailService, DbContext aDbContext)
{
_emailService = aEmailService;
_dbContext = aDbContext;
}
public void Register(string email, string password)
{
if (!_emailService.ValidateEmail(email))
throw new ValidationException("Email is not an email");
var user = new User(email, password);
_dbContext.Save(user);
emailService.SendEmail(new MailMessage("myname@mydomain.com", email) { Subject = "Hi. How are you!" });
}
}
public class EmailService
{
SmtpClient _smtpClient;
public EmailService(SmtpClient aSmtpClient)
{
_smtpClient = aSmtpClient;
}
public bool virtual ValidateEmail(string email)
{
return email.Contains("@");
}
public bool SendEmail(MailMessage message)
{
_smtpClient.Send(message);
}
}
فواید استفاده از SRP
- طراحی و اجرای کلاس های با مسئولیت واحد آسان تر است.
- خوانایی را بهبود می بخشد زیرا یک کلاس برای یک عمل است و توضیح و درک آن بسیار آسان تر است.
- قابلیت نگهداری کد بهتر ،زیرا تغییر در یک عملکرد بر عملکرد دیگر تأثیر نمی گذارد.
- تست پذیری را بهبود می بخشد زیرا به دلیل عملکرد واحد در یک کلاس، پیچیدگی را در هنگام نوشتن موارد تست واحد برای یک کلاس کاهش می دهد.
- جداسازی هر عملکرد در کلاسهای مختلف به محدود کردن تغییرات فقط در آن کلاس کمک میکند که در نهایت به کاهش تعداد باگها به دلیل تغییرات برای نیازمندیهای جدید کمک میکند.
- اشکال زدایی خطاها نیز آسان تر است، یعنی اگر خطایی در عملکرد ایمیل وجود داشته باشد، می دانید کدام کلاس را باید جستجو کنید.
- امکان استفاده مجدد از همان کد را در مکانهای دیگر فراهم میکند، یعنی اگر یک کلاس عملکرد ایمیل بسازید، میتوان از آن برای ثبت نام کاربر، فراموشی رمز عبور و غیره استفاده کنید.
نتیجه گیری : اصل SRP یکی از رایج ترین اصول طراحی برای دستیابی به اهداف شی گرا است. با استفاده از اصل مسئولیت واحد میتوانیم وابستگی بین عملکردها را کاهش دهیم و از این رو میتوانیم کد خود را برای پیادهسازی ویژگیهای جدید در طولانی مدت بهتر مدیریت کنیم. گاهی اوقات بر اساس موقعیت میتوانید تصمیم بگیرید. بر اساس عملکردهایی که اجرا می شوند، تصمیم بگیرید که چه چیزهایی می توانند با هم باشند و چه چیزهایی نمی تواند.
دیدگاهتان را بنویسید