کتاب Clean Code فصل 2 : نام های معنی دار

کتاب Clean Code

کتاب CLEAN CODE

فصل 2 : نام های معنی دار

مقدمه

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

از نام های آگاهانه استفاده کنید

آسان است که بگوییم نام ها باید بیانگر نیت شما باشند. چیزی که ما می خواهیم این است که شما این موضوع را به خاطر بسپارید که ما در این موضوع جدی هستیم.

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

انتخاب نام مناسب متغییر

 

 

نام متغیر d منظور و یا چیزی از زمان را برای ما نشان نمی‌دهد. ما باید نامی را انتخاب کنیم که نشان دهد بر اساس چه معیاری انتخاب شده است و این کار تحت عنوان چه واحدی بوده است.

نام مناسب برای متغییر

 

 

 

انتخاب نام هایی که هدف را نشان می‌دهد باعث درک بهتر کد و تغییرات آن نیز می‌شود. به عنوان مثال هدف کد زیر چیست؟

کد پیچیده

 

 

 

 

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

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

  1. چه نوع هایی در theList وجود دارد؟
  2. اهمیت یک زیرمجموعه یک نمونه در theList چیست؟
  3. ارزش وجودی 4 چیست؟
  4. چگونه می‌توان از یک لیست بازگشتی استفاده کرد؟

پاسخ به این سوال ها در کد نمونه وجود ندارد در صورتی که می‌توانست وجود داشته باشد. ما در حال بازی کردن در یک بازی mine sweeper هستیم. ما board ای را پیدا کرده ایم که در آن لیستی از سلول ها وجود دارد و theList نامیده می‌شود. بیایید آن را به gameBoard تغییر نام دهیم. هر سلول در آن با یک آرایه ساده نشان داده می‌شود. علاوه بر این متوجه شدیم که زیرمجموعه نشانگر مکان مقادیر وضعیت[4] است که مثلا مقدار 4 نشان دهنده flag می‌باشد. فقط با نامگذاریِ این مفاهیم به این شکل می‌توانیم کد را به طور قابل توجه ای بهبود دهیم.

تابع خوب

 

 

 

 

 

البته توجه داشته باشید که سادگی کد، تغییری نکرده است. این کد هنوز دقیقا همان تعداد متغیر و ثابت را دارد. ولی کد خیلی واضح تر شده است.

ما می‌توانیم جلوتر برویم و کلاسی ساده برای سلول ها به جای استفاده از آرایه های int بنویسیم و یا می توان یک تابع واضح با نام isFlagged نیز نوشت که اعداد جادویی را پنهان کند. خروجی زیر نتیجه یک نسخه جدید از تابع است:

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

 

 

 

 

 

با این تغییر نام ساده، درک آنچه که در حال انجام است، سخت نیست. این قدرت انتخاب نام های خوب است.

اجتناب از اطلاعات غلط

برنامه نویسان باید از دادن سرنخ های غلطی که مفهوم کد را پنهان می کند، اجتناب کنند. ما باید از نوشتن کلماتی که معنای معتبر آنها، به جای معنای مورد نظر ما درک می شود اجتناب کنیم. به عنوان مثال hp و aix و sco نام های نامناسبی برای متغیرها هستند زیرا اینها نام ها برگفته شده از دنیای
یونیکس و نسخه های آن هستند. حتی اگر شما از نام hypotenuse برای نامگذاری استفاده کنید و برای اختصار نام آن را hp قرار دهید می تواند دلسردکننده باشد.

برای ارجاع دادن به گروه حساب ها 1 از accountList استفاده نکنید، مگر آنکه واقعاً یک List باشد. کلمه لیست برای برنامه نویسان دارای معنا و مفهوم خاصی است. اگر کانتینری 2 که حاوی account ها است، یک List نباشد در نهایت باعث ایجاد نتایج غلط می شود؛ بنابراین accountGroup یا bunchOfAccounts یا accounts گزینه های مناسب تری هستند.

مراقب استفاده از نام هایی باشید که تفاوت خیلی کمی با یکدیگر دارند. چه مدتی طول می کشد که به تفاوت XYZControllerForEfficientHandlingOfStrings و XYZControllerForEfficientStorageOfStrings در یک ماژول برسیم؟ این دو کلمه شباهت شگفت انگیزی دارند.

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

یک مثال بد از نام های غیرمنتظره این است که از حروف کوچک یا بزرگ به تنهایی یا در ترکیب برای نام متغیرها استفاده شود و مشکل این است که مانند ثابت صفر و یک هستند. به کد زیر توجه کنید:

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

 

 

 

 

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

ایجاد تمایز با معنی دار کردن

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

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

نامگذاری سری مانند ( a1, a2,. . aN ) مخالف قاعده نامگذاری است. چنین اسامی اطلاعات غلط میدهند (غیرمستقیم هستند). همچنین مقصود نویسنده را نیز بیان نمی کنند. برای مثال کد زیر را در نظر بگیرید:

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

 

 

 

 

این تابع زمانی بهتر خوانده می شود که از source و destination به عنوان نام آرگومان ها استفاده شود. کلمات نویز 1 (کلماتی an, a, the, of , …) مورد دیگری از نام های بی معنی هستند. تصور کنید که شما یک کلاس product دارید. اگر ProductInfo یا ProductData را فراخوانی کنید، نام های مختلفی ایجاد کرده اید اما تفاوتی در این نام ها وجود ندارد. زیرا که Info و Data مانند a و an و the کلمات نویز هستند. توجه داشته باشید که قرار دادن پیشوندها و پسوندها تا زمانی که یک تمایز معنادار ایجاد کند، هیچ مشکلی ندارد. برای مثال ممکن است برای همه متغیرهای محلی a و برای تمام آرگومان های توابع از the استفاده کنید. مشکل زمانی به وجود می آید که شما تصمیم به فراخوانی متغیری با نام theZork می کنید ولی شما از قبل متغیری با نام zork دارید.

کلمات نویز بسیار زیاد هستند، کلمه variable هیچ گاه نباید در نام یک متغیر ظاهر شود. کلمه table هیچ گاه نباید در نام جدول قرار بگیرد. چگونه NameString بهتر از Name است؟ آیا نام همیشه یک عدد شناور است؟ اگر چنین باشد که قانون قبل نقض می شود. تصور کنید که کلاسی با نام Customer و کلاس دیگری با نام CustomerObject نامگذاری شده اند. چه چیزی را باید به عنوان تمایز در این دو نامگذاری درک کنیم؟ کدام یک بهترین مسیر برای تاریخچه پرداخت یک مشتری را نشان می دهد؟ یک برنامه کاربردی وجود دارد که ما می دانیم در کجا نشان داده شده است.

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

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

 

 

 

چگونه برنامه نویسان در این پروژه بدانند که کدام یک از این توابع را فراخوانی کنند؟ در نبود قراردادهای خاص متغیر moneyAmount از money و یا customerInfo از customer قابل تشخیص نیست. همچنین accountData از account و theMessage از message قابل تشخیص نیست. نام ها را به گونه ای مشخص کنید که خواننده قادر به تشخیص تفاوت ها باشد.

استفاده از نام های قابل تلفظ

انسان ها در تلفظ کلمات خوب هستند. بخش مهمی از مغز ما به مفهوم کلمات اختصاص داده شده است و کلمات به وسیله تعریفشان قابل تلفظ هستند. این خجال تآور است که از بخش بزرگی از مغزمان که در زبان گفتاری پیشرفت کرده است استفاده نکنیم. پس نام های خود را قابل تلفظ کنید.
اگر نمی توانید آن را تلفظ کنید پس نمی توانید حتی با یک آدم احمق در مورد آن بحث کنید. این مهم است که درست بنویسیم و درست تلفظ کنیم. (به عنوان مثال از عبارت هایی مانند ازتسمشس1، آمخته 2، ببه 3، که فقط برای افراد محدودی قابل فهم است استفاده نکنید. «مترجم )»

شرکتی وجود دارد که من می دانم genymdhms را دارند که این نشانگر (, generation date, year month, day , hour, minute , و second ) می باشد. پس افراد شرکت در حالی که راه می روند، می گویند “gen why emm dee aich emm ess“ . من یک عادت آزاردهنده ای دارم، عادت من این است که    می خواهم هر چیزی که نوشته شده است را تلفظ کنم. بنابراین مورد بالا را حرف به حرف تلفظ می کنم و می خوانم. بعدها این مورد توسط گروهی از تحلیلگران و طراحان نامگذاری شد ولی ما همچنان تلفظ احمقانه ای داشتیم. اما ما در موردش شوخی می کردیم و این سرگرم کننده بود. البته سرگرمی که نمی توان گفت، می توان گفت که ما یک نامگذاری ضعیف را تحمل می کردیم. توسعه دهندگان جدیدی که وارد می شدند باید برای آنها این مورد توضیح داده می شد و سپس به جای استفاده از اصطلاحات انگلیسی مناسب، باید در مورد کلمات احمقانه صحبت می کردند. در مثال زیر می توانید این دو کد را با هم مقایسه کنید:

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

 

 

 

با

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

 

 

 

 

مکالمه هوشمند در حال حاضر امکان پذیر است. “هی مایکی نگاهی به این رکورد بنداز، تولیدکننده برچسب زمان 1 برای تاریخ فردا تنظیم شده”. چطور ممکنه؟

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

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

به همین ترتیب برای برنامه نویسی که ممکن است نیاز به جست و جو داشته باشد انتخاب نام e برای یک متغیر یک انتخاب ضعیف است. این رایج ترین نشانه در زبان انگلیسی است و احتمالاً در هر قسمت برنامه و متن، ممکن است وجود داشته باشد. در این راستا نام های طولانی تر، نام های کوتاه را پوشش می دهند و هر اسمِ قابل جست و جو یک نتیجه ثابت را بر می گرداند. ترجیح شخصی من این است که از نام های تک حرفی فقط و فقط به عنوان متغیرهای محلیِ درون یک تابع کوتاه استفاده شود. طول نام باید با طول دامنه هماهنگی داشته باشد 2[N5] . یک متغیر یا یک ثابت ممکن است در چندین مکان از بدنه یک کد دیده شود. ضروری است از نامی که برای جست و جو مناسب است استفاده شود. یک بار دیگر دو کد زیر را با هم مقایسه کنید:

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

 

با

 

 

;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
{

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

 

شما میتوانید برای مطالعه یک فصل دیگر از کتاب Clean Code یعنی  فصل 4 : کامنت ها از کتاب Clean Code بر روی متن لینک کلیک کنید. ( لینک ) 

 

3 پاسخ

تعقیب

  1. […] 2 : نام های معنی دار . برای مطالعه قسمتی از فصل دوم کلیک کنید. […]

  2. […] قسمتی از فصل 2 : نام های معنی دار بر روی لینک کلیک کنید. ( لینک […]

دیدگاه خود را ثبت کنید

تمایل دارید در گفتگوها شرکت کنید؟
در گفتگو ها شرکت کنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.