افراد زیادی در حوزههای مختلف مشغول برنامه نویسی هستند، اما چیزی که یک برنامه نویس حرفه ای را از یک برنامه نویس متوسط یا بد متمایز میکند، یادگیری طراحی کد خوب (Good Design) است. طراحی خوب و استاندارد در برنامه نویسی بخاطر ویژگی هایی که در برنامه ایجاد میکند باعث راحت شدن فرآیند تغییر در کدها میشود. با این کار، هزینههای مالی و زمانی تغییر کدها و نگهداری از برنامه به شدت کاهش پیدا میکند.
دنیایی که درآن زندگی میکنیم دنیای پیچیدگیها است و نیاز به تغییرات و همگام و سازگار شدن با آن تغییرات امری ضروری است. این دنیا، برای برنامه نویس هایی که از ایجاد تغییر در کدهای خود وحشت زده میشوند و یا زمان زیادی را برای آن به هدر میدهند مکان بی رحمی است! بنابراین بهتر است هر چه زودتر با یادگیری اساس طراحی کد خوب، برنامههای خود را برای ایجاد تغییرات و featureها یا امکانات جدید، ساده و استاندارد و تمیز کنیم.
طراحی کد خوب به ما کمک میکند با تغییرات برنامهها به راحتی کنار بیاییم و از پیچیدگی برنامههای خود کم کرده و خوانایی کد را افزایش دهیم. شاید تصور بعضیها این باشد که کدهای پیچیده که هیچکسی از آن سر در نیاورد نشانه یک برنامه نویس باهوش و خوب است. خیر! باید بدانید برنامه نویس خوب کسی نیست که کدهایش توسط کامپیوتر قابل فهم باشد بلکه برنامه نویسی است که کدهایش به راحتی توسط انسان قابل خواندن و تفسیر کردن باشد.
چندین بار از عبارت طراحی کد استفاده کردیم! شاید برایتان سوال باشد که طراحی چه ارتباطی با برنامه نویسی دارد! پس برای شروع آشنایی با اصطلاح Single Responsibility، بهتر است در ابتدا با دیزاین یا طراحی و چیستی آن آشنا شویم. منظور از طراحی در برنامه نویسی، در واقع فرآیند کدنویسی، تست کردن و بازتولید یا ریفکتور (Refactoring) آن است. بنابراین با این دیدگاه، برنامه نویس یک طراح نرم افزار محسوب میشود.
به طور خلاصه برای رسیدن به یک طراحی خوب، به تک منظوره بودن و انسجام درونی ماژول ها (که در برنامه نویسی شی گرا همان کلاسها هستند) و همینطور پرهیز از در هم تنیدگی آنها احتیاج داریم. باید بدانید که Single Responsibility راه حل رسیدن به شرط اول است. Single Responsibility از اصول پنجگانه SOLID (بخوانید سالید) و اولین آنها است. در SOLID به این اصل Single Responsibility Principle یا به اختصار SRP میگویند.
در این اصل، گفته میشود که برای رسیدن به یک طراحی خوب، نیاز داریم که هر کلاس تنها و تنها یک هدف و وظیفه را در برنامه ایفا کند. کار تمام متدهای کلاس باید در راستای رسیدن به آن هدف باشد و استفاده از هر متدی با وظایف منحرف از هدف اصلی اشتباه است و باعث در هم تنیدگی وظایف در برنامه و بنابراین پیچیدگی کد و در نتیجه کم کردن Reusability یا قابلیت استفاده مجدد از کدها میشود. همینطور هر متد کلاس باید تنها و تنها یک وظیفه را ایفا کند.
به عنوان مثال گوشیهای تلفن همراه هوشمند را در نظر بگیرید. این گوشیها معمولا امکانات زیادی مانند دوربین عکاسی و فیلم برداری، رادیو، ضبط کننده صدا و... در خود دارند. اما چه کسی میتواند ادعا کند که یک تلفن همراه میتواند از یک دوربین حرفه ای عکاسی و فیلم برداری بهتر عمل کند؟ چه کسی برای ضبط تخصصی پادکست و یا قطعات موسیقی از تلفن همراه خود استفاده کرده و دستگاههای تخصصی ضبط را نادیده میگیرد؟
در اصل Single Responsibility به عنوان مثال اگر یک کلاس Authentication یا احراز هویت داشته باشیم، لازم است که تمام متدهای کلاس در راستای احراز هویت کاربر باشند. مثلا میتوانیم متدهای Login() و یا Logout() داشته باشیم ولی داشتن متدهایی مانند showPosts() برای نمایش پستهای کاربر در این اصل، عملی اشتباه است.
به مثال زیر دقت کنید:
interface Modem {
public function dial($number);
public function hangUp();
public function send($character);
public function recieve();
}
در این مثال یک Interface مودم تعریف کرده ایم. در کلاس Modem، دو متد با نام dial() و hangUp() برای اتصال و قطع اتصال مودم و دو متد send() و Receive() برای ارسال و دریافت داده داریم. بنابراین در این کلاس در حال انجام دو وظیفه هستیم:
مدیریت اتصال مودم
انتقال دادهها از طریق مودم
اما همانطور که گفتیم این کار اصل Single Responsibility را نقض میکند. بنابراین به جای داشتن یک Interface بزرگ با دو مسئولیت، آن را به دو Interface کوچکتر تک منظوره میشکنیم. با این کار کدمان به این شکل در میآید:
interface DataChannel {
public function send($character);
public function recieve();
}
interface Connection {
public function dial($number);
public function hangUp();
}
همانطور که مشاهده میکنید Interface بزرگ Modem، به دو Interface با نامهای DataChannel و Connection شکسته شده است. با این عمل حالا دو ماژول داریم که یکی وظیفه مدیریت اتصال مودم و دیگری وظیفه انتقال دادهها را پشتیبانی و مدیریت میکنند.
در این مطلب با اولین اصل از اصول مهم SOLID در طراحی نرم افزار آشنا شدیم. اصل Single Responsibility یا تک وظیفگی میگوید که هر ماژول یا کلاس برنامه فقط باید در راستای یک هدف فعالیت کند و داشتن متدهایی که وظایف حاشیه ای یا نامربوط دارند اشتباه است. این قانون در مورد متدها نیز برقرار است. یعنی هر متد کلاس باید تنها یک وظیفه را به عهده داشته باشد. با رعایت کردن این اصل میتوانیم به اولین نشانه طراحی خوب که همان انسجام در ماژولهای برنامه است برسیم. آیا شما تجربه ای از اشتباه در رعایت نکردن این اصل داشته اید؟ این اشتباه چه مشکلاتی برای شما ایجاد کرد؟ از خواندن نظرات شما خوشحال میشویم!
۹ دیدگاه
محمدمهدی فرخی۲۱ آبان ۱۴۰۱، ۱۲:۱۹
سلام ممنون بابت مقاله عالی تون
فقط یه تعداد سوال برای من پیش اومد.
اول اینکه ظاهرا با رعایت کردن این اصل تعداد کلاسها بیشتر از حالتی میشه که این اصل رعایت نمیشه
این میتونه نکته ی بدی باشه؟
و بعد بعنوان مثال اگر قرار باشه توی برنامه م از دیتابیس MS Access دیتا بخونم و داخلش بنویسم و به این منظور میخوام کلاسی رو بنویسم که select و insert رو توی متدهایی پیاده سازی کنم
ایا برای رعایت این اصل باید توی یک کلاس متد selectهای مختلف رو بنویسم و توی کلاس دیگه ای متدهای مربوط به insert رو بنویسم؟
نازنین کریمی مقدم۲۱ آبان ۱۴۰۱، ۱۸:۴۸
درود
ببینید یکم سلیقه ای هم هست، منتها به شخصه پیشنهاد میکنم که اگر تعداد select کم هست همگی در یک کلاس باشه (مشابه send و recieve که در یک کلاس تعریف شد) و اگر زیاد هست، بله به دو بخش select و insert تقسیم بشه.
این تعداد کلاس میتونه زیاد بشه اما دیگه به مدیریت و چگونگی تعریف کردن خودتون برمیگرده، باید سعی کنید حد وسط رو بگیرید چون تعداد کلاس خیلی زیاد از اون سمت باعث گیج شدن برنامه نویس و پایین اومدن پرفورمنس هم میشه.
حمیدرضا کریمی۱۵ شهریور ۱۳۹۹، ۰۸:۰۴
خیلی عالی بود ممنون از مقاله خوبتون
نازنین کریمی مقدم۱۹ شهریور ۱۳۹۹، ۱۳:۵۹
سلام. ممنون از همراهی و توجه شما.
عرفان نعمتی۰۷ دی ۱۳۹۸، ۰۷:۰۴
سلام
وقت بخیر
یه نکته مهم به ذهنم میرسه در مورد این مطلب:
عبارت Single Responsibility Principle باید ترجمه بشه: "اصل مسئولیت واحد" یا "اصل تک مسئولیتی" نه "اصل چند وظیفگی"
چون کلمه Single به تک بودن و واحد بودن اشاره میکنه نه چندگانگی
مشایخی۲۳ فروردین ۱۳۹۸، ۱۵:۵۷
احسنت این مطالب را زیاد کنید کل solid و design patternها را ذکر کنید عالیه
لقمان آوند۲۴ فروردین ۱۳۹۸، ۰۵:۳۷
ممنون از دیدگاهتون
حتما در ادامه این مقالات رو بیشتر خواهیم داشت