کدنویسی تمیز: نام‌گذاری صحیح

Clean Coding: Correct Naming

17 فروردین 1400
درسنامه درس 2 از سری کدنویسی تمیز
کدنویسی تمیز: نام گذاری صحیح (قسمت 2)

فصل اول: نام گذاری

اگر یادتان باشد در جلسه اول توضیح دادم که کد تمیز ویژگی های خاصی را دارد. این ویژگی ها بدین شکل هستند:

  • نکته اول نام گذاری است. نام دهی به متغیرها، پارامترها، توابع، کلاس ها و امثال آن باید از قوانین خاصی پیروی کند تا خوانا باشد.
  • نکته دوم ساختار کلی کد و کامنت نویسی است. ما باید از code formatting (قالب دهی به کد) استفاده کنیم و با نوشتن کامنت های خوب و بد آشنا شویم.
  • نکته سوم توابع است. طول توابع (تعداد خطوط کد درون تابع) و تعداد پارامترهای دریافتی توابع از نکات بسیار مهم در این حوزه است.
  • نکته چهارم دستورات شرطی و مدیریت خطا است. از مباحث این قسمت می توان به تو در تو کردن دستورات شرطی و عدم مدیریت خطا صحبت کرد که کیفیت کد ما را پایین می آورند.
  • نکته پنجم کار با کلاس ها و داده ساختارها است. در این بخش با نوشتن کلاس های مینیمال و تفاوت آن ها با داده ساختارها آشنا خواهیم شد.

ساختار این دوره نیز به همین شکل است و هر فصل را به یکی از این موضوعات اختصاص داده ایم. امروز با نکته اول، یعنی نام گذاری، شروع خواهیم کرد. نام گذاری خود شامل سه بخش مهم است:

  • نام گذاری متغیرها، ثابت ها و خصوصیت ها
  • نام گذاری توابع و متدها
  • نام گذاری کلاس ها

ما هر سه حالت را بررسی کرده و از هر کدام مثال های مختلفی را بررسی خواهیم کرد.

چرا نام گذاری در کدنویسی اهمیت دارد؟

زمانی که بحث نام گذاری در برنامه نویسی مطرح می شود یک قانون کلی وجود دارد که بر روی تمام قوانین دیگر احاطه خواهد داشت و آن معنادار بودن نام های انتخاب شده توسط شما است. بسیاری از توسعه دهندگان (مخصوصا در ایران که آشنایی با زبان انگلیسی کمتر است) تصور می کنند که با انتخاب یک واژه انگلیسی معنادار، نامی عالی را انتخاب کرده اند. اگر این واژه انگلیسی معنادار از اصطلاحات برنامه نویسی و حوزه وب نیز باشد که فبها! از نظر این افراد بهترین نام را انتخاب کرده اند اما انتخاب نام معنادار به هیچ عنوان بدین معنی نیست. معنادار بودن نام انتخاب شده یعنی زمانی که فردی نام متغیر شما را می خواند باید بدون نگاه به کدهای دیگر تا حد زیادی متوجه بشود که کار آن متغیر چیست و چه مقداری را در خود نگه می دارد یا مثلا اگر کسی به نام تابع شما نگاه کند باید بدون نیاز به بررسی کدهای درون تابع، متوجه وظیفه اصلی آن تابع بشود. به طور مثال به کد زیر توجه کنید:

const us = new MainEntity();

us.process();




if (login) {

    // انجام فرآیندی خاص

}

این کد قسمت خاصی از یک پروژه بزرگ است. با اینکه کد بالا تنها چند خط است و نام های انتخاب شده کلمات انگلیسی صحیح هستند اما برای من و شما که تمام کدها را نداریم اصلا معلوم نیست که چه خبر است و وظیفه این کد چیست! هر کسی با دیدن کد بالا سوالاتی از خودش می پرسد: MainEntity چیست؟ متد process چه کار می کند؟ مقدار login چیست و چه نوع داده هایی را قبول می کند؟ آیا login یک تابع خاص است و ما در حال بررسی وجود یا عدم وجود این تابع هستیم یا اینکه یک مقدار boolean است یا اینکه یک رشته است؟ حالا نسخه خوانای کد بالا را برایتان قرار می دهم:

const user = new User();

user.save();




if (isLoggedIn) {

    // انجام فرآیندی خاص

}

درک این کد بسیار ساده تر است. ما در خط اول یک user یا کاربر جدید را ساخته ایم و در خط دوم این کار را ذخیره (save) کرده ایم (تمام کد را نداریم اما حدس می زنیم که این ذخیره سازی در پایگاه داده اتفاق می افتد). و در نهایت isLoggedIn (به معنی «آیا لاگین شده است؟») را داریم. از همین نام ساده (isLoggedIn) متوجه می شویم که مقدار آن حتما نتیجه بررسی لاگین بودن یا نبودن کاربر است و به احتمال بسیار زیاد با یک boolean سر و کار داریم.

زمانی که نام گذاری ما معنادار باشد، فرد دیگری که کدهای ما را می خواند به سادگی می تواند متوجه کلیت کار شود. ما برای درک کدهای بالا نیازی به داشتن سورس کد کل پروژه نداشتیم؛ مثلا نیازی به بررسی کلاس User نبود تا بدانیم دقیقا درون آن چه چیزی نوشته شده است. شاید بپرسید چرا باید برای من اهمیت داشته باشد که یک فرد دیگر بتواند کدهایم را بخواند؟ این سوال پاسخ های مختلفی دارد:

  • اگر در حال یادگیری کدنویسی هستید، معمولا نیاز است تا کدها را با دیگران به اشتراک بگذارید تا آن ها بتوانند خطاهایتان را برایتان تصحیح کنند.
  • اگر به دنبال شغل می گردید باید بدانید که اکثر برنامه نویسان با یکدیگر در شرکت های مختلف کار می کنند و زمانی برای هدر دادن و خواندن جزئیات کدهای یکدیگر نداریم.
  • اگر می خواهید به صورت فری لنسر (freelancer) کار کنید، باید بدانید که یک پروژه پس از اتمام تازه شروع می شود! در آینده صاحب پروژه که پروژه را از شما دریافت کرده است احتمالا بخواهد تغییراتی را در آن انجام بدهد (به روز رسانی و غیره) و با بد نوشتن کدها کار را بی جهت برای دیگران سخت می کند.
  • اگر می خواهید فقط برای پروژه های شخصیتان کدنویسی کنید، باید بدانید که پروژه ها دائما نیاز به ویرایش و به روز رسانی دارند. اگر یک پروژه را ۶ ماه رها کنید و دوباره به آن برگردید هیچ چیزی را به خاطر نخواهید داشت و آنجاست که نام گذاری بد باعث دردسر بسیار زیادی برایتان می شود. در این حالت خودتان «فرد دیگری» هستید که کدهایتان را می خوانید!

باید توجه داشته باشید که ما همیشه روی نام گذاری توافق نخواهیم داشت چرا که سلیقه هر فرد متفاوت است و تفاوت های فردی غیر قابل انکار است. نکته مهم اینجاست که کدهایتان معنادار و خوانا باشند. من سه نسخه از یک کد را برایتان آماده کرده ام:

const admin = new Admin();




const admin = new AdminUser();




const admin = createAdmin();

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

قوانین نام گذاری در برنامه نویسی

قبل از اینکه بخواهیم با مثال های خوب و بد نام گذاری آشنا شویم باید قوانین مربوط به آن ها را بررسی کنیم. من این قسمت به سه بخش مختلف تقسیم کرده ام:

  • متغیرها و ثابت ها و خصوصیت ها
  • توابع و متدها
  • کلاس ها

متغیرها و ثابت ها و خصوصیت ها همگی data container یا نگهدارنده داده هستند، یعنی از آن ها برای ذخیره داده استفاده می کنیم بنابراین من بعضا در این دوره با نام data container به آن ها اشاره می کنم. داده های ذخیره شده در این data container ها از منابع مختلفی می آیند؛ به طور مثال ممکن است داده های وارد شده توسط کاربر باشد یا نتیجه اعتبارسنجی باشد یا آرایه ای از محصولات از پایگاه داده باشد و الی آخر. با این حساب برای این دسته از نام گذاری ها باید از «اسم» یا «عبارات کوتاه به همراه صفت» استفاده نمایید تا آنچه درون data container های ما است را توصیف کند. به طور مثال User (به معنی «کاربر») یک اسم است یا isValid (به معنی «معتبر است») یک عبارت است (طبیعتا استفاده از صفت اجباری نیست). البته boolean ها مانند isValid کمی بیشتر شبیه به نام گذاری توابع هستند.

برای نام گذاری توابع و متدها باید روش دیگری را اتخاذ کنیم. ما درون توابع و متدها هیچ داده ای را به صورت خاص ذخیره نمی کنیم بلکه کدهایی را داریم که باید اجرا شوند. حتی اگر درون تابع متغیری تعریف کرده باشید، آن متغیر پس از اجرای تابع از بین می رود و موقتی است. برای نام گذاری این دسته باید از «فعل» یا «عبارات کوتاه با صفت» استفاده کنیم. نام هایی مانند sendData (داده را ارسال کن) یا InputIsValid (ورودی معتبر است) نام های مناسبی هستند. نکته مهم وجود «فعل» در این دو نام است.

برای نام گذاری کلاس ها باید با طبیعت کلاس ها آشنا باشید. کلاس ها نقشه ای برای ساخت یک شیء خاص هستند. به طور مثال اگر کلاسی برای ساخت کاربرها داشته باشیم، می توانیم با استفاده از نمونه سازی از آن یک شیء کاربر دریافت کنیم. با این حساب برای نام گذاری آن ها باید از «اسم» یا «عبارات ساده با اسم» استفاده می کنیم. نام هایی مانند User یا RequestBody نمونه هایی از نام خوب هستند.

طبیعتا شما نیازی به حفظ کردن این دستور العمل ها ندارید بلکه به مرور زمان به این ساختارها عادت خواهید کرد و بدون اینکه نیازی به فکر کردن داشته باشید چنین نام هایی را انتخاب می کنید.

قوانین Casing در نام گذاری

Casing به استفاده از حروف بزرگ و کوچک و علامت های آندراسکور و امثال آن اشاره می کند. ما در برنامه نویسی معمولا چهار Casing یا روش نوشتار مشهور را برای نام گذاری داریم:

  • snake_case: در این روش تمام حروف به صورت کوچک نوشته می شوند و کلمات با استفاده از آندراسکور (علامت _) از هم جدا می شوند. توسعه دهندگان زبان پایتون معمولا از این روش استفاده می کنند (مثال: user_data و first_user_name)
  • camelCase: در این روش تمام کلمات به هم می چسبند و حرف اول تمام کلمات به غیر از حرف اول از کلمه اول، بزرگ است. توسعه دهندگان زبان هایی مانند جاوا و جاوا اسکریپت از این روش استفاده می کنند (مثال: userData و firstUserName).
  • PascalCase: در این روش تمام کلمات به هم می چسبند بنابراین دقیقا مانند camelCase است اما تفاوت اینجاست که حرف اول همیشه بزرگ است (مثال: UserData و FirstUserName). زبان هایی مانند پایتون و جاوا و جاوا اسکریپت فقط برای نام کلاس ها از این روش استفاده می کنند. زبانی مانند PHP نیز برای نام کلاس هایش از این روش و برای نام متدهایش از camelCase استفاده می کند.
  • kebab-case: در این روش تمام حروف به صورت حروف کوچک نوشته می شوند بنابراین دقیقا مانند snake_case است با این تفاوت که به جای آندراسکور (علامت _) از خط فاصله (علامت -) استفاده می کنیم. زبان HTML از این روش استفاده می کند (مثال: <side-drawer>).

طبیعتا این زبان برنامه نویسی است که مشخص می کند شما از کدام روش Casing استفاده می کنید. شاید بپرسید من توسعه دهنده جاوا اسکرپیت هستم، آیا نمی توانم از kebab-case استفاده کنم؟ از نظر فنی می توانید کدهایتان را با هر Casing ای که خواستید بنویسید اما پیروی از قرارداد های هر زبان برنامه نویسی، بخشی از روش نوشتن کد تمیز و خوانا می باشد بنابراین پیشنهاد می کنم همیشه از قرارداد های مشهور زبان یا فریم ورک مورد استفاده خود پیروی کنید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری کدنویسی تمیز توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.