این مقاله خلاصه ای از کتاب Clean Code است که به طور اختصاصی بر فصل دوم با عنوان Meaningful Names (نام های بامعنی) تمرکز دارد.
اسم ها در تمام کد شما وجود دارند: متغیر ها، کلاس ها، متد ها و... از آنجایی که این مقاله یک خلاصه است و از دید شخصی من باید مستقیم و بی پرده باشد، از هر گونه اطلاعات اضافی عبور کرده و مستقیما به سمت محتوا می رویم...
نام باید نقش خود را فریاد بزند. وقتی که نام ها به طور معنی دار تعریف می شوند، دیگر نیازی به نوشتن کامنت در بالای آن یا توضیح مستقیم به یک همکار نیست. به جای تعریف نام های بی معنی مانند int myNumber، String s یا هر نام دیگری که معنی مشخصی ندارد، می توان آن ها را با نام هایی که نقششان را فریاد می زنند جایگزین کرد.
به این کد دقت کنید:
//This returns car full name of Company + Model //For example: Nissan + GTR String car(String a, String b) { return "$a $b" }
با کد زیر مقایسه کنید:
String carName(String company, String model) { return "$company $model" }
کد دوم به راحتی و بدون هیچ تعریف اضافه یا کامنت به خواننده می گوید که دقیقا چه اهدافی دارد.
خواننده باید همیشه به وضوح متوجه شود که در ذهن توسعه دهنده چه اتفاقی در حال رخ دادن است. نامگذاری یک متغیر به عنوان String shoppingList فقط به این علت که شامل "فلفل، گوجهفرنگی، پاستا" می شود، صحیح نیست؛ این نام به راحتی می تواند خوانندگان را گمراه کند چرا که آن ها فکر کنند این یک List<String> shoppingList است. در واقع، مشکل اصلی زمانی ایجاد می شود که یک همکار بخواهد از shoppingList در جای دیگر استفاده کند و بر اساس نام آن فرض کند که این یک List است.
مثال دیگر، int isFull است که می تواند به دلیل استفاده از is، یک bool تشخیص داده شود.
دو قانون ساده:
1- از اضافه کردن Type به نام ها خودداری کنید: از String name به جای String nameString یا از var user به جای var userVariable استفاده نمایید!
2- از متفاوت سازی متغیر ها با کلمات عمومی مانند a, an, another, the و... کنید. به جای rowText و anotherRowText، به سادگی از rowTitle و rowSubtitle استفاده نمایید.
موقع نام گذاری یک متغیر، تصور کنید که دارید آن را بلند بلند به همکار خود می گویید. آیا آن ها بلافاصله متوجه منظور شما می شوند؟ ممکن است فقط شما بدانید که Desc مخفف "Description" در متغیر studyDesc است. آیا آن ها فکر نمی کنند که منظور شما "Study Desk" (میز مطالعه) باشد؟ بهتر است آن را studyDescription نام گذاری کنید تا همه آن را تشخیص دهند.
نام هایی را انتخاب کنید که جستجوی آن ها راحت باشد. فرض کنید به یک متغیر بولین نیاز دارید که بررسی کند یک مقدار درست است یا نه؛ احتمالاً اولین نامی که به ذهنتان میرسد isCorrect خواهد بود. در حالی که نامهایی مانند isRighteous از نظر فنی ممکن است کار کند، اما برای همه قابل درک و واضح نیست، به ویژه برای توسعه دهندگانی که در سطوح زبانی مختلف قرار دارند.
در استفاده از اصطلاحاتی که باید توسط همکاران و خوانندگان حفظ شوند خودداری کنید. به عنوان مثال، بهتر است که از حروف سنتی مانند i، j و k در حلقههای for استفاده نمایید و آنها را با حروفی مانند a، b و c جایگزین نکنید.
برای نام گذاری کلاس ها از اسم (دستور زبان) استفاده کنید. به عنوان مثال، نامهایی مثل Currenct، Tool و Shape برای کلاس ها مناسب هستند، در حالی که نام هایی مانند GetCurrency، CalculateShape و ChooseTool به دلیل فعل بودن مناسب نیستند.
برای نام گذاری متد ها از فعل استفاده کنید. به عنوان مثال، نام هایی مانند getCurrency، calculateShape و chooseTool برای متد ها مناسب هستند، در حالی که نام هایی مانند currency، shape و tool به دلیل اسمی بودن مناسب نیستند.
استفاده از نام های بامزه مثل hastaLaVista() به جای exit() ممکن است از نظر نویسنده کد بامزه باشد، اما از دید همکاران چندش به نظر می رسد.
به سادگی یک کلید واژه را انتخاب کرده و در تمام جاهایی که آن مفهوم به کار رفته استفاده کنید. مثلا استفاده از fetch هم در متد های DataSource و هم Repository معقولانه است. اما اگر در DataSource از fetch و در Repository از get استفاده کنید، باعث سردرگمی و سوءتفاهم می شود.
هر هدف باید نام خاص و متمایز خود را داشته باشد. برای مثال، نباید از نام user هم برای اشاره به فردی که از برنامه استفاده میکند و هم برای رکورد کاربر در پایگاه داده استفاده کنید. به جای آن، از نامهای توصیفی تر مانند appUser و userRecord استفاده کنید تا مشخص باشد که به چه چیزی اشاره دارید.
اضافه کردن پیشوند ها یا پسوند های مناسب می تواند هدف متغیر را روشن تر کند. برای مثال، به جای استفاده از balance به تنهایی، از accountBalance استفاده کنید تا مشخص باشد که این موجودی مربوط به حساب است. البته توجه داشته باشید که این روش برای متغیر های درون کلاس (مثل نمونه ی زیر) صدق نمی کند:
class Account{ int id; String name; int balance; const Account({required this.id, required this.name, required this.balance}); }
ولی خارج از کلاس Account این مورد کار می کند:
void Main(){ int accountBalance = Account().balance; }
با این وجود که لازم است کلمات معنی دار اضافه کنید، باید از افزودن پیشوند ها و پسوند های بی فایده به نام ها خودداری کنید. به عنوان مثال، به جای استفاده از userAccountBalanceInTheBank از userBalance استفاده کنید یا به جای carMakeInEnglish از carMake بهره بگیرید تا نام ها کوتاه و خوانا باشند.
این کار باعث می شود کد شما شفاف تر و آسان تر و قابل فهم تر باشد.
بر اساس تجربه ی شخصی، نام گذاری متغیر های بولی همیشه باید با کلید واژه های is یا has شروع شود. این قانون، هم "بولین بودن" را به وضوح مشخص می کند و هم خوانایی کد را به خصوص در مواردی مثل if می دهد.
یک مثال خوب:
bool isUserRegistered; bool hasError; if (isUserRegistered) { if (hasError) { } }
یک مثال بد:
bool register; bool error; if (register) { if (error) { } }
مثال دوم، بیشتر از bool بودن، شبیه به یک method جلوه می کند.
با رعایت تمام این اصول، نه تنها کد شما قابل فهم تر خواهد بود، بلکه توسعه ی آن در آینده نیز آسان تر می شود! یک متغیر، متد یا کلاس با نام گذاری مناسب می تواند ساعت ها زمان را در دیباگ و ریفکتور کد ذخیره کند. نام های تمیز و معنا دار نشانه ای از کد حرفه ای و با کیفیت هستند.
نسخه ی انگلیسی مقاله را می توانید از طریق این لینک بخوانید.