برنامه نویس
چند نکته خودمانی در مورد برنامه نویسی JS و ReactJS
خیلی وقته در مورد چیزی ننوشتم و بعد از یه مدت طولانی تصمیم گرفتم در مورد کد تمیز وتجربیاتی که تو این چند سال کد نویسی و توسعه با JavaScript داشتم بنویسم.
تو این مقاله تمرکزم رو بردم رو Clean Code و استاندارد های تعریف شده؛ البته با چاشنی تجربه شخصیم. مقاله برای React هستش ولی نکات اشاره شده جامع هستن و اکثرا محدود به React نیست.
منظور از کد تمیز چیه؟
Martin Fowler توی کتاب Clean Code خودش یه توصیف جالب داره، میگه که:
هر احمقی میتونه کدی بنویسه که یه کامپیوتر بفهمه، برنامه نویس های خوب کسایی هستن که کدهایی مینویسن که توسط آدما قابل فهم باشه!
به نظر من این توصیف آخر توصیف کد تمیزه!
چند وقت پیش هم در یک مقاله ای یه عبارت جالب رو دیدم، با این مضمون که:
یه کدی بنویس که آخر هر روز با افتخار ببری و به مامانت نشون بدی!
که البته این آخر روز برای اکثر ماها اول صبحه! :دی
در نظر گرفتن این دو توصیف به خودی خود باعث میشه کدتون تمیز باشه. اینو بهتون قول میدم!
کد نویسی تمیز زمانتون رو تلف نمیکنه!
خیلی از دوستان برنامه نویسی که دیدم، میدونن که کد تمیز چیه و اهمیتش رو هم خوب میدونن فقط به اشتباه فکر می کنن که کد نویسی تمیز اتلاف وقته و روی چیزی که بهش عادت کردن تاکید می کنن!
متاسفانه ترک عادت های قبلی در هر زمینه ای سخته و این کاملا قابل درکه. ولی نکته ای که باید بهش توجه کنید اینه که شما با ترک عادت کدنویسی کثیف یه عادت باحال تر رو صاحب میشید.
کدنویسی تمیز ممکنه توی اوایل زمانتون رو بگیره ولی این زمان مثل سرمایه گذاری میمونه. تجربه ثابت کرده که این زمان با چیزایی که یاد میگیرید و موقع استفاده از عادت های جدید جبران میشه. در واقع عادت های جدید باعث افزایش سرعت کد نویسی و کاهش هزینه های نگهداری کدتون میشه.
به مثال بالا توجه دقت کنید. مطمئنا شما به عنوان یک برنامه نویس JS با حالت اول یا همون Dirty Code مثال آشنا هستید و به احتمال زیاد قسمت های زیادی رو دارید همینجوری جلو میرید. و شاید براتون سخت باشه که به تمیز نوشتن عادت کنید و یا شاید بگید یادگیری اینا زمانبره (ایشالله تو پروژه بعدی حتما از اینا استفاده میکنم، یا به قولی ایشالله از شنبه...). ولی باور کنید و مطمئن باشید که مثلا داشتن یه فایل جدا واسه ثابت ها تو یه پروژه یا استفاده از توابع ES6/5 و یا نوشتن کامنت فقط اول ممکنه برای بعضی هاتون سخت باشه. به عبارتی فقط کافیه initialize بشید و تمام.
کامنت ها صدای کد شما هستن!
اگر میخواید پایه های کدتون قوی باشه حتما از کامنت استفاده کنید و برای هر قسمتی که لازمه توضیحات اضافه کنید. این کار از هدر رفت زمانتون در بلند مدت جلوگیری میکنه و باعث میشه هزینه های نگهداری هم پایین بیاد.
در واقع باید اینو در نظر بگیرید که در آینده ای نه چندان دور، در بهترین حالت خودتون و در بدترین حالت یک نفر به جای شما، با کدتون درگیر خواهید بود. پس کاری نکنید که حتی خودتون هم نتونید از پس کدتون بربیاد. (حالا وای به حال نفر بعد شما!)
نکته ای که باید بهش توجه کنید اینه که نوشتن کامنت برای همه قسمت های کدتون هم کار درستی نیست! لازم نیست برای قسمت های بدیهی کدتون توضیحی بنویسید. البته ممکنه قسمتی که برای شما بدیهی هست، به نظر یک نفر دیگه پیچیده بیاد و یا بر عکس این. هر چی تجربه توی کد نویسی بیشتر باشه کامنت گذاری ها هم استاندارد تر و به دردبخور تر میشن.
به نحوه کامنت گذاری در کد زیر توجه کنید و دو تارو باهم مقایسه کنید لطفا.
DRY کد بزنید ولی خطا نزنید!
قراره کدهایی که مینویسیم ماژولار باشه تا راحت بتونیم در پروژه ها و ماژول های دیگه ازشون استفاده کنیم و از تکرار کد ها جلوگیری کنیم. این یعنی DRY.
DRY مخفف Don’t Repeat Yourself هستش و چیزیه که هر برنامه نویسی باید رعایت کنه. DRY بودن باعث کاهش هزینه های نگهداری و البته کمتر شدن حجم کد میشه.
به نظر من وسواس بیش از حد بر مفهوم DRY هم خوب نیست و پیچیدگی کد رو واقعا بالا میبره و خواناییش رو کمتر میکنه.
کار با Component توی React در واقع کد نویسی DRY هستش. برای مثال وقتی شما تو یکی پروژه ای نیاز دارید که 10 خط کد بنویسید تا یک Custom Button داشته باشید، به جای اینکه این 10 خط رو توی چند جا بنویسید، کامپوننت CustomButton رو با همون 10 خط درست میکنید و هر جایی که لازم دارید ازش استفاده میکنید.
به کامپوننت هاتون رحم کنید!
هر کامپوننتی که درست میکنید باید یه وظیفه داشته باشه و اگه غیر از این باشه، واقعا دارید در حق خودتون و کامپوننتتون ظلم میکنید!
تا جایی که می تونید کامپوننت هاتون رو بشکنید و به کامپوننت های کوچک تر تبدیل کنید. با این کار بهتر میتونید پروژتون رو تست کنید و نگهداری کد هم راحت تر میشه.
به توابعتون هم رحم کنید!
تک مسئولیتی بودن در مورد توابع و متدها هم صادق هستش و تمام نکات بالا برای توابع هم تاکید میشه.
- میتونستم این دو بخش رو یکی در نظر بگیرم چون در React کامپوننت های Functional داریم که در اصل یک متد هستن ولی چون متدها محدود به React و Component ها نمیشه برای همین خواستم جدا روشون تاکید کرده باشم.
Functional Components رو جایگزین Class Components کنید!
توی React دو نوع کامپوننت میتونیم داشته باشیم:
1- Class Components (CC): ساختار یک کلاس رو دارن که از یک کلاس دیگه ی React مثل Component یا PureComponent یا ... Extend میشن.
2- Functional Components (FC): این نوع کامپوننت های در واقع توابع ساده JS هستن که یه پارامتر هایی رو می گیرن و یه چیزی رو برمیگردونن.
به این نوع کامپوننت ها Stateless Components هم می گفتن (میگن). این به خاطر این بود که نمی شد در این نوع کامپوننت ها state تعریف کرد. ولی به لطف ویژگی Hooks که در نسخه 16.3 به صورت رسمی معرفی شد، استفاده از state در FC هم ممکن شد. نه تنها state بلکه Lifecycle, Ref, Context و چند مورد دیگه رو هم دیگه میتونید به همراه FC داشته باشید.
استفاده از FC به جای CC به شدت توصیه میشه. چون که این مورد هم باعث تمیزی کدتون میشه. همون چیزی که از اول این مطلب روش تمرکز کردیم. بهتره این دو کد زیر رو یه مقایسه ای بکنید.
از توابع کمکی React Immutability Helpers استفاده کنید
این توابع کمکی زمانی به کارتون میاد که بخواید مقدار/مقادیر کپی یک Object رو در یک Scopeتغییر بدین.
برای مثال اگر بخواید Obj1 را در Obj2 قرار بدید و مقدار Obj2.value رو تغییر بدین، مقدار Obj1.value هم تغییر با Obj2 تغییر میکنه و این مشکلیه که داریم. در مواردی مثل این شما باید یک Deep Copy (کپی واقعی - نتونستم ترجمهی خوبی براش پیدا کنم!) از Object اصلیتون بگیرید و در متغیر هدف بزارید.
یکی از راه های انجام این کار استفاده از Object.assign() به صورت زیر هستش:
یک راه دیگه هم استفاده از تابع update از توابع Immutability هستش که کار رو واقعا راحت کردن. مثال های زیر رو لطفا با دقت مقایسه کنید:
روش مقداردهی تخریبی (ES6 Destructuring Assignment)رو درک و استفاده کنید
در ES6 یک روش جدید برای دریافت مقادیر از Object ها و Array ها معرفی شد که به خاطر کوتاهی و راحتی در خوانایی کار رو برای برنامه نویس های JS راحت تر کرده. مثال زیر مقایسه دو حالت مقداردهی را بادقت بررسی کنید
با (bind(this. خداحافظی کنید
در صورتی که متد داخل کلاس رو به صورت Arrow Function تعریف کنید، دیگه نیازی به bind کردن همه متدها در constructor نخواهید داشت. در واقع با این کار وطیفه bind رو به ES5/6 میسپارید.
اسامی فایل هاتون رو kebab-case بزارید
درسته که هر کسی/تیمی میتونه استاندارد خودش رو در نامگذاری فایل های پروژش داشته باشه ولی بهتره اینه که استاندارد های عمومی و شناخته شده رو رعایت کند. یکی از اون استانداردها ساختار kebab-case در اسامی فایل هاست.
- یه توضیح جالب در مورد اسم ساختار kebab-case، برخلاف دیگر اصطلاحات نام گذاری، میشه گفت هیچ اتفاق نظری روی اسم این ساختار وجود نداره و همه به سلیقه حودشون یه چیزی رو به عنوان اسمش به کار میبرن. از اسامی شناخته شده می تونم به dash-case, hyphen-case, kebab-case و دو سه مورد دیگه(که الان یادم نمیاد) اشاره کنم. که از بین اینا kebab-case از همشون مشهور تره.
از اسم هایی استفاده کنید که لایق خودتون باشه!
همه متغیرها، متدها، کلاس ها و فایلها یه شخصیتی برای خودشون دارن که اولش با تعیین اسمشون توسط شما شکل میگیره. خودتون رو بزارید جای این عزیزان؛ راضی میشید یکی یه اسم عجیب غریب بزاره روی شما؟
برای این عزیزان اسامی خوب و با معنی انتخاب کنید و هیچ وقت هیچ اسمی رو به اختصار ننویسید مگر اون چیزهایی که دیگه واقعا شناخته شده هستن. برای مثال msg یک اختصار شناخته شده از message هستش و استفاده از اون هیچ مانعی نداره ولی اگر بجای Customer مثلا cstmr رو به کار ببرید خیلی اشکال داره و حتما نیازه که یه اصول اولیه ای رو دوباره مطالعه کنید.
این مورد رو حتی توی تست ها و حتی توی Hello World هاتون هم رعایت کنید. چرا که رعایت نکردنشون فقط باعث ریشه کردن عادت های بد کدینگ میشه.
از اینکه همه جا try-catch میزارید خجالت نکشید!
به هر نحوی که میتونید توی کدتون خطاهای احتمالی رو شکار کنید. ممکنه بعضی هارو بشناسید که اینو عیب بدونن! ولی مطمئن باشید که try-catch ها و Error Handling اعتبار یک کد هستش.
به کدتون اعتبار بدین و برچسب های درست روی هر بخش از کدتون بزارید. هیچ وقت خطاهای بی معنی رو throw نکنید و سعی کنید یک Sheet از خطاها و توضیحاتشون برای هر پروژه داشته باشید.
حرف آخر
رعایت کردن موارد بالا تاثیر بسیار زیادی در کیفیت کد شما خواهد داشت و مطمئنا در کوتاه مدت خودتون هم متوجه این تغییر خواهید شد.
همونطور که اول مقاله نوشتم، درسته که توی بعضی قسمت ها روی React تاکید کردیم ولی خودتون هم دیدید و خوندید سعی کردم موارد خیلی جامع باشن.
نظری/سوالی داشتید من در خدمتم یا اگر مشکلی یا موردی بود بفرمایید. امیدوارم مفید واقع بشه! :)
مطلبی دیگر از این انتشارات
react-helmet | دسترسی به head در ری اکت
مطلبی دیگر از این انتشارات
در سال 2020 از کدوم تکنولوژی کراس پلت فرم استفاده کنیم؟
مطلبی دیگر از این انتشارات
ویژگیهای جدید ریاکت 16.8 (React Hooks)