Ali Fazeli
Ali Fazeli
خواندن ۴ دقیقه·۳ سال پیش

تحول برنامه نویسی با کد تمیز (بخش اول - نام گذاری ها)

اولین پست از سری مقاله های برداشت های شخصی من و خلاصه هایی از کتاب Clean Code مربوط به نام گذاری هاست. توی این بخش نکته ها و مسائلی که هنگام نام گذاری متغیر ها، توابع یا کلاس ها هنگام کد نویسی باید رعایت بشه رو مرور می‌کنیم. تاثیر عمل کردن به این نکته ها موقع کد نویسی احتمالا بیشتر ازچیزیه که در نگاه اول به نظرتون میاد.

به نظر من نوشتن کد تمیز از نام گذاری درست شروع می‌شه.
shining-and-clean-code
shining-and-clean-code



نام گذاری متغیر ها

از اسم های بی معنی استفاده نکن

اسم هایی که معنایی با خودشون ندارند موقع خوندن کد، فهمیدن رو سخت می‌کنن. پس برای انتخاب اسم وقت بذارید. متغیر هایی مثل a، b یا data تقریبا به شما هیچ اطلاعاتی در مورد ماهیت شون نمی‌دن.

meaningful-variable-name
meaningful-variable-name


از اسم های مخفف استفاده نکن

استفاده از اسم های مخفف باعث می‌شه که موقع خوندن کد نیاز به مراجعه دائم به ذهن و مپ کردن اطلاعات داشته باشید. IDE های مدرن انقدر امکانات برای autocomplete در اختیار ما قرار میدن که چند کاراکتر کوتاه تر یا بلند تر بودن اسم اهمیتی نداشته باشه. پس اگه جایی متغیری برای توضیحات داشتید اسمش رو description بذارید، نه dscr. یا اگر به جای category از cat استفاده کردین چقدر مطمئنید که نفر بعدی هم متوجه اون می‌شه و فک نمی‌کنه که با یه گربه طرفه؟

این مسئله در مورد مخفف هایی که به شکل کاملا عمومی یا توی فضای برنامه نویسی پذیرفته شدن صدق نمی‌کنه. اگه متغیری دارید که در باره fifa (فدراسیون جهانی فوتبال)‌ هست احتمالا منطقی نباشه که به جاش از federationInternationaleDeFootballAssociation استفاده کنین!


اسم متغیر باید نشان دهنده مقدار درونش باشه

با نگاه به اسم متغیر باید بفهمیم که شامل چه مقداری می‌شه. فرض کنیم متغیری داریم که روز های مانده تا تاریخ یک امتحان رو در بر میگیره. کدوم یک از این اسم ها برای این متغیر بهتره؟

var d; var days; var daysRemainingToExam;

اسم نباید اطلاعات غیرواقعی یا گمراه کننده منتقل کنه

بعضی وقت ها اسم هایی که برای متغیر انتخاب می‌کنیم ناخواسته اطلاعات غلطی به ذهن انتقال می‌دن. به طور مثال کلمه list توی برنامه نویسی گاها به نوع داده خاصی اشاره داره و اگر برای مجموعه ای از product ها به جای products از کلمه productList استفاده کنیم ممکنه که خواننده کد (که می‌تونیم خودمون تو آینده هم باشیم) موقع خوندن این ذهنیت رو پیدا کنه که ما با نوع list طرف هستیم. در حالی که یک مجموعه یا آرایه ساده داریم.


تا حد ممکن اسم های شبیه هم انتخاب نکن

اسم هایی که ابتدا و انتهای مشابه دارند و تفاوت کوچیکی وسطشون هست استفاده نکن. ذهن ما موقع خوندن متن ها (از جمله کد نرم افزار) برای تمایز دادن بین کلمه ها بیشتر به ابتدا و انتهای اون ها و شکل کلی شون توجه می‌کنه. پس این مثال (شاید کمی اغراق شده)‌ رو ببینید:

XYZControllerForEfficientHandlingOfStrings XYZControllerForEfficientStorageOfStrings

بهتره که اسم ها طوری انتخاب بشن که با نگاه تفاوت شون راحت مشخص بشه.


تفاوت معنایی ایجاد کن

سعی کنید اسم های انتخابی دارای معنی مشخص باشن و اطلاعات بیشتری نسبت به عملکرد اون ها بدن.

فرض کنین تابعی به اسم reverse داریم که مقدار معکوس آرایه ورودی اول رو در آرایه ورودی دوم کپی می‌کنه. حالا دو تعریف ورودی ها رو با هم مقایسه کنین:

// 1 reverse(char a1[], char a2[]) … // 2 reverse(char source[], char destination[])

توی خوندن کد دوم به راحتی از کلمه های source و destination متوجه کاربرد اون ها و عملکرد تابع می‌شیم. توی کد اول اسم ورودی ها هیچ اطلاعاتی در مورد نقش شون و عملکرد شون بهمون نمی‌ده.


کلمه های اضافی بی معنی استفاده نکن

از استفاده از حرف هایی که تفاوت معنایی ایجاد نمی کنند بپرهیزید. استفاده از کلماتی مثل the , info, data و … در حالت کلی تفاوت معنایی ایجاد نمی‌کنند و تنها باعث استفاده از متغیر های مختلف با اسم هایی با معنی یکسان می‌شن.

این اسم ها از نظر معنایی چه تفاوتی با هم دارن؟‌ product, theProduct, productInfo, productData

استفاده از اسم های این چنینی باعث میشه که متغیر هایی با اسم های متفاوت داشته باشیم که تفاوت واقعی شون مشخص نیست و این تاثیر منفی بر خوانایی کد میذاره.


از اسم های ناخوانا استفاده نکن

کد توی ذهن ما به شکل یه متن عادی خونده می‌شه (باید تلاش کنیم که اینطوری باشه!). پس اگر توی نوشتن کد از کلمه هایی استفاده کنیم که تلفظ کردن شون غیر ممکن یا سخته داریم این کارو سخت می‌کنیم. برای اینه که باید از کلمه های عادی و خوانا برای اسم گذاری ها استفاده کنیم. منظور از کلمه های ناخوانا چیه؟

tsmp -> timestamp

مخفف کردن های بی مورد از نکته هاییه که اینجا هم دیده می‌شه.


از اسم های قابل جستجو استفاده کن

از اسم های تک حرفی یا غیرقابل جستجو استفاده نکن. یکی از مهم ترین کاربرد های اسم، پیدا کردن تکرار های اون توی یه فایل یا کل کد بیس یه نرم افزاره. استفاده از اسم های تک حرفی یا اسم های بی معنی پیدا کردن متغیر ها با چشم موقع خوندن کد یا پیدا کردن اون ها توسط IDE رو سخت یا غیر ممکن می‌کنه. برای فهمیدن منظور این قسمت فقط کافیه که این دو تا کد رو با هم مقایسه کنین:

for (int j=0; j<34; j++) { s += (t[j]*4)/5; }
  • و
int realDaysPerIdealDay = 4; const int WORK_DAYS_PER_WEEK = 5; int sum = 0; for (int j=0; j < NUMBER_OF_TASKS; j++) { int realTaskDays = taskEstimate[j] * realDaysPerIdealDay; int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK); sum += realTaskWeeks; }

البته همونطور که توی مثال هم دیدین یه استثنا وجود داره برای این مورد و اونم counter های داخل حلقه ها هستن. استفاده از اسم های i،j یا k توی شمارنده ها پذیرفته شدست مخصوصا زمانی که scope اون ها خیلی کوچیک باشه و تداخلی با هیچ بخش دیگه ای از کد نداشته باشن.

به طور کلی سعی کنین طوری اسم رو انتخاب کنین که کسی که کد رو می‌خونه نیازی نداشته باشه که توی ذهنش اون رو تبدیل به کلمه معناداری کنه. درسته که برنامه نویس ها رو آدم های نسبتا باهوشی می‌دونیم ولی بذارید از این هوش برای کارهای مهم تری استفاده بشه! نه تبدیل کردن اسم های بد به کلمه های معنی دار.



اسم گذاری Class ها

برای کلاس ها از اسم استفاده کنین (و نه فعل)

سعی کنید اسم کلاس بیانگر کاری باشه که قراره اون کلاس انجام بده.

همین نگاه ساده تا حدی در مورد بهتر نوشتن کد های شی گرا (Object Oriented) هم می‌تونه کمک کننده باشه. و اگر مسئولیت های زیادی (بیشتر از یکی) برای یک کلاس در نظر گرفته باشین احتمالا موقع انتخاب اسمش هم متوجه اون بشید.

همینطور از کلمه های عمومی که معنی مشخصی ندارن توی ترکیب اسم ها دوری کنین.

این مثال ها رو ببینین:

  • ProductDataProcessor → ProductAPIOutputTransformer
  • CustomerManager → Customer
  • ProductData → Product
به دلایل واضح، بیشتر نکته هایی که برای اسم متغیر گفته شده برای اسم کلاس ها هم صادقه و باید رعایتشون کرد.

نام گذاری متد ها (توابع)

نام گذاری متدها هم از اکثر قوانینی که تا اینجا گفته شده پیروی می‌کنه. یکی از نکته های متفاوت برای function ها اینه که از فعل برای اسم اونا استفاده می‌کنیم. فعل بیانگر کاریه که اون متد قراره انجام بده.

نمونه های ساده ای از اسم مناسب:

  • save
  • create
  • deleteCustomer

برای متد هایی که اطلاعاتی از یک Object رو تغییر می‌دن یا اونا رو می‌خونن حتما از set و get استفاده کنین.

  • setName
  • getName

یه مورد استثنایی که میشه راجع بهش حرف زد متد هاییه که خصوصا برای خوندن مقادیر boolean استفاده می‌شن که توی اون ها میشه به جای get از is استفاده کرد که خوانا تره.

این مثال رو ببینین:

Class Order { private sent = true; }

برای خوندن مقدار sent استفاده از متد isSent به نظرم خوانا تر از getSent هست.

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



توی انتخاب اسم ها از شوخی یا کلماتی که فقط برای شما معنا داره استفاده نکنین و سعی کنین شفاف اسم رو انتخاب کنین. ممکنه بامزه یا سرگرم کننده به نظر بیاد که اسم متدی که قراره یه سفارش رو کنسل کنه sendToDowntown بذارین ولی حواستون باشه که این شوخی ممکنه کسی متوجه این کار (حداقل در نگاه اول)‌ نشه. پس پیشنهاد می‌کنم شوخی رو برای جای دیگه ای نگه دارید و توی این شرایط اسم متد رو cancelOrder بذارید. همین موضوع در مورد شوخی ها یا تکیه کلام های داخلی تیم هم صدق می‌کنه. شوخی های داخلی تون رو وارد کد هایی که قراره برای ماه ها یا سال ها باقی بمونه و کارکنه نکنید.

هر مفهوم = یک کلمه

سرتاسر یه کد بیس برای هر عملکرد یا مفهوم از یک کلمه ثابت استفاده کنین و توی تله استفاده از اسم های مشابه نیفتید.

مثلا برای گرفتن اطلاعات از دیتابیس می‌تونید جایی از get و جای دیگه از fetch یا retrieve استفاده کنید. این ها از نظر معنایی و عملکردی درستن. ولی کار شما رو موقع نوشتن و خوندن کد به طور مسخره ای سخت می‌کنن. پس اگر برای گرفتن اطلاعات از get استفاده کردید پاش بایستید و همه جا از همون استفاده کنین.

همینطور از استفاده از یک کلمه برای مفاهیم متفاوت هم استفاده نکنین! به طور مثال فرض کنید که شما برای ایجاد اطلاعات جدید همیشه از متد با اسم add استفاده کردید. حالا جایی برای اضافه کردن یک رکورد به یک لیست هم اگر از همین اسم استفاده کنید احتمالا کمی سردرگمی به کد اضافه کردید. پس بهتره اینجا از کلمه هایی مثل insert یا append استفاده کنین.

توجه کنید که توی این مثال:

  • add = اضافه کردن رکورد جدید در دیتابیس
  • append = اضافه کردن یک رکورد به لیستی از داده ها

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

جمع بندی

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

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

این متن خلاصه و برداشت های من از بخش هایی از کتاب Clean Code بود.

این سری ادامه داره.

برنامه نویسیکد تمیز
مهندس نرم افزار
شاید از این پست‌ها خوشتان بیاید