۱۰ اصل برنامه‌نویسی که هر توسعه‌دهنده نرم‌افزاری باید بداند

شکل ۱. اصول برنامه‌نویسی که توسعه‌دهندگلن نرم‌افزار می‌دانند
شکل ۱. اصول برنامه‌نویسی که توسعه‌دهندگلن نرم‌افزار می‌دانند
منتشر شده در blog.ossph به تاریخ ۲۱ ژوئن ۲۰۲۳
لینک منبع: 10 Programming Principles Every Software Developer Should Know

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

۱. اصل اول DRY (خودت را تکرار نکن)

اولین اصل برنامه‌نویسی در این لیست DRY است که مخفف عبارت Don't Repeat Yourself است. این بدان معناست که باید از تکرار کد در برنامه‌های خود اجتناب کنید و در عوض سعی کنید کدهای قابل استفاده مجدد و ماژولار بنویسید.

کپی کردن کد می‌تواند منجر به مشکلات متعددی شود، مانند افزایش تلاش‌های تعمیر و نگهداری، احتمال بیش‌تر معرفی باگ‌ها و مشکل در ایجاد تغییرات در مکان‌های مختلف.

تصور کنید در حال ساختن برنامه‌ای هستید که مساحت اشکال مختلف را محاسبه می‌کند. به جای نوشتن توابع جداگانه برای محاسبه مساحت هر شکل (به‌عنوان مثال، یک تابع جداگانه برای محاسبه مساحت مربع، دیگری برای یک مثلث، و غیره)، می‌توانید با ایجاد یک تابع منفرد به نامaccountArea از اصل DRY پیروی کنید. پارامترهای لازم را می‌گیرد و ناحیه را برمی‌گرداند.

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

به یاد داشته باشید، پیروی از اصل DRY نه‌تنها به شما کمک می‌کند کدهای تمیزتر و سازمان‌یافته‌تری بنویسید، بلکه در دراز مدت باعث صرفه‌جویی در زمان و تلاش می‌شود.

۲. دوم KISS (سخت نگیر، احمق)

عبارت KISS بر اهمیت سادگی در توسعه نرم‌افزار تاکید می‌کند. این نشان می‌دهد که ما باید تلاش کنیم تا کد و راه‌حل‌ها را تا حد امکان ساده نگه داریم. ساده‌سازی کد، درک، نگهداری و اشکال‌زدایی را آسان‌تر می‌کند و احتمال خطا یا مشکل را کاهش می‌دهد.

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

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

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

۳. سوم YAGNI (شما به آن نیاز ندارید)

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

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

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

۴. جداسازی نگرانی‌ها (SoC)

اصل تفکیک نگرانی‌ها (SoC) یک مفهوم اساسی در توسعه نرم‌افزار است که تقسیم یک برنامه به بخش‌های مجزا و مستقل را ترویج می‌کند که هر بخش به نگرانی یا مسئولیت خاصی می‌پردازد.

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

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

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

۵. ساده‌ترین کاری که ممکن است کارآمد باشد را انجام دهید

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

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

این رویکرد ساده بدون پیچیدگی بیش از حد یا محاسبات غیر ضروری به نتیجه مطلوب می رسد. تمرکز بر ساده ترین راه حل نه تنها باعث صرفه جویی در زمان و تلاش می شود، بلکه منجر به ایجاد کدهایی می شود که درک، اشکال زدایی و نگهداری در طولانی مدت آسان تر است.

۶. کد برای نگهدارنده

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

یکی از راه‌های دست‌یابی به قابلیت نگهداری کد، پیروی از کنوانسیون‌های کدنویسی و بهترین شیوه‌ها است. به‌عنوان‌مثال، استفاده از متغیرهای توصیفی و نام توابع می‌تواند خوانایی را تا حد زیادی افزایش دهد. به جای استفاده از نام‌های رمزآلود مانند a، b یا x، نام‌های معنی‌داری را انتخاب کنید که به وضوح هدف و عملکرد کد را توصیف می‌کنند.

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

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

۷. اجتناب از بهینه‌سازی زودرس

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

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

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

۸. قانون آمادگی دفاعی (Boy Scout)

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

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

اعمال قانون Boy Scout نه‌تنها مشکل فوری را حل می‌کند، بلکه پایگاه کد را برای توسعه‌دهندگان آینده که روی آن کار خواهند کرد نیز بهبود می‌بخشد.

۹. قانون دمتر

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

به زبان ساده، نشان می‌دهد که یک ماژول باید دانش محدودی در مورد ساختار داخلی ماژول‌های دیگر داشته باشد و فقط باید با همسایگان نزدیک خود تعامل داشته باشد.

بیایید سناریویی را تصور کنیم که در آن یک شی به نام Person داریم که دارای خواص و رفتارهای مختلفی است. طبق قانون Demeter، اگر بخواهیم به یک ویژگی از آدرس شخص دسترسی داشته باشیم، به جای دسترسی مستقیم به آن مانند person.address.street، باید از متدی ارائه شده توسط خود شی شخص، مانند person.getStreet() استفاده کنیم. به این ترتیب، شی Person جزئیات آدرس خود را کپسوله می‌کند و یک رابط سطح بالاتر را برای سایر اجزا برای تعامل با آن در معرض دید قرار می‌دهد.

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

۱۰. اصول جامد

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

اصل مسئولیت واحد (SRP)

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

اصل باز/بسته (OCP)

اصل OCP تاکید می‌کند که موجودیت‌های نرم‌افزار (کلاس‌ها، ماژول‌ها، توابع) باید برای توسعه باز باشند اما برای اصلاح بسته باشند. این بدان معنی است که ما باید بتوانیم ویژگی‌ها یا رفتارهای جدیدی را بدون تغییر کد موجود اضافه کنیم. یکی از راه‌های رسیدن به این هدف استفاده از وراثت یا رابط‌ها است. به‌عنوان مثال، یک کلاس Shape با زیر کلاس‌های مختلف مانند Rectangle و Circle را تصور کنید. اگر بخواهیم یک شکل جدید اضافه کنیم، می‌توانیم یک زیر کلاس جدید بدون تغییر کلاس Shape موجود ایجاد کنیم. این اصل قابلیت استفاده مجدد کد را ارتقا می‌دهد و خطر ایجاد اشکال در کدهایی که قبلا کار می‌کردند را کاهش می‌دهد.

اصل جایگزینی لیسکوف (LSP)

اصل LSP بیان می‌کند که اشیاء یک سوپرکلاس باید با اشیاء زیرکلاس‌های آن بدون تأثیر بر صحت برنامه قابل تعویض باشند. به عبارت ساده‌تر، هر نمونه از یک کلاس باید بتواند به جای کلاس والد خود بدون ایجاد رفتار غیرمنتظره استفاده شود. برای مثال، فرض کنید یک کلاس پایه به نام Animal با متد makeSound() داریم. زیرکلاس‌هایی مانند Cat and Dog باید بتوانند کلاس Animal را جایگزین کنند و هم‌چنان رفتار مورد انتظار را بدون ایجاد خطا یا ناسازگاری ایجاد کنند.

اصل جداسازی رابط (ISP)

اصل ISP توصیه می‌کند که کلاینت‌ها نباید مجبور شوند به واسط‌هایی که استفاده نمی‌کنند وابسته شوند. به جای داشتن رابط‌های بزرگ و یک‌پارچه، ایجاد واسط‌های خاص متناسب با نیازهای مشتریان را تشویق می‌کند. این امر باعث می‌شود کلاس‌ها مجبور نباشند متدهایی را که به آن‌ها مرتبط نیستند، پیاده‌سازی کنند. برای مثال، رابطی به نام Printer با متدهایی مانند print()،scan() وfax() تصور کنید. به جای داشتن یک رابط واحد، بهتر است آن را به رابط‌های کوچک‌تری مانند قابل چاپ، قابل اسکن و فکس تقسیم کنید. به این ترتیب، کلاس‌ها می‌توانند تنها رابط‌های مورد نیاز خود را پیاده‌سازی کنند و پایگاه کد را تمیزتر و متمرکزتر نگه دارند.

اصل وارونگی وابستگی (DIP)

اصل DIP پیشنهاد می‌کند که ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند. هر دو باید به انتزاعات بستگی داشته باشند. اتصال سست را ترویج می‌کند و امکان تغییرات و آزمایش آسان‌تر را فراهم می‌کند. در عمل، این بدان معناست که کلاس‌ها باید به رابط‌ها یا کلاس‌های انتزاعی وابسته باشند تا پیاده‌سازی مشخص. به‌عنوان مثال، کلاسی به نام Logger را در نظر بگیرید که نیاز به نوشتن گزارش در یک فایل دارد. به جای اینکه مستقیما به یک پیاده‌سازی سیستم فایل خاص وابسته باشد، باید به رابطی مانند FileSystem بستگی داشته باشد که می‌تواند چندین پیاده‌سازی داشته باشد (به‌عنوان مثال، LocalFileSystem، CloudFileSystem). به این ترتیب، می‌توانیم بین پیاده‌سازی‌ها بدون تغییر کلاس Logger سوئیچ کنیم.

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

بسته‌بندی

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

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