پرش به مطلب اصلی

Clean Code

مقدمه

اگر اصول Clean Code را در توسعه فرانت‌اند رعایت نکنیم، با چالش‌های جدی و متعددی روبرو خواهیم شد. این چالش‌ها می‌توانند شامل کد پیچیده و غیرقابل خواندن، دشواری در نگهداری و به‌روزرسانی، افزایش زمان و هزینه‌ی رفع اشکال، و مشکلات در همکاری تیمی باشند. در نتیجه، پروژه‌ها با تأخیر مواجه شده، کیفیت محصول نهایی کاهش یافته و هزینه‌های توسعه به طور قابل توجهی افزایش می‌یابد. همچنین، عدم رعایت این اصول می‌تواند منجر به ایجاد بدهی فنی شود که در طول زمان انباشته شده و مدیریت پروژه را دشوارتر می‌کند.

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

  • نوشتن کد تمیز چه مزایایی دارد؟
  • از چه اصول و از چه تکنیک‌هایی برای دست‌یابی به کد تمیز می‌توان استفاده کرد؟
  • کد تمیز به طور خاص در فرانت‌اند دارای چه ویژگی‌هایی است؟

یادگیری

Clean Code

شاید برای شما هم پیش آمده باشد که بعد از چند ماه به پروژه‌ای که خودتان آن را توسعه داده‌اید سر بزنید و احساس کنید تقریباً هیچ‌چیز از آن متوجه نمی‌شوید. زمانی که بر روی پروژه‌ای کوچک، به صورت انفرادی کار می‌کنید شاید هیچ‌وقت به اهمیت کد تمیز پی نبرید؛ اما اگر همین پروژه، در آینده احتیاج به توسعه داشته باشید یا اگر به همراه یک تیم بر روی آن کار کنید، بدونِ داشتنِ کد تمیز، محکوم به شکست خواهید بود.

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


Code Smells

یکی از راه‌های افزایش کیفیت کد، پیدا کردن نشانه‌های کد کثیف و بازنویسی آن‌هاست. به این نشانه‌ها Code Smell می‌گوییم.

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


S.O.L.I.D

یکی از مهم‌ترین مجموعه اصول در برنامه‌نویسی، اصول پنج‌گانهٔ SOLID می‌باشد که عبارت است از:

  1. Single Responsibility
  2. Open for Extension/Closed for Modification
  3. Liskov Substitution
  4. Interface Segregation
  5. Dependency Inversion

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


Refactoring Techniques

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

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


Open-Source

README.md

فایل README.md معرفی‌نامۀ پروژۀ شماست. تمام مواردی که یک کاربر بیرونی احتیاج دارد در مورد پروژه بداند باید در این فایل آورده شوند یا حداقل به جایی که در مورد آن‌ها توضیح داده شده است، اشاره شود.

پیشنهاد می‌کنیم موارد زیر را حتماً در این فایل بیاورید:

  • نام پروژه
  • لوگو شخص، تیم یا شرکت
  • لینک به سایت اصلی پروژه
  • وضعیت CI/CD، بالا بودن سرورها، پاس‌شدن تست‌ها و موارد مشابه
  • توضیحی چند خطی و کوتاه در مورد کاربرد پروژه
  • اهداف پروژه و نیازهایی که می‌تواند برطرف کند
  • پیش‌نیازهای استفاده از پروژه
  • لینک دانلود فایل نهایی/اجرایی پروژه
  • باگ‌های احتمالی و مواردی که کاربر باید به آن‌ها توجه کند
  • قابلیت‌های فعلی و نحوۀ استفاده از آن‌ها
  • مستندات کامل یا لینک به جایی که آن‌ها را قرار داده‌اید
  • برنامه‌های آینده و قابلیت‌هایی که می‌خواهید به پروژه اضافه کنید
  • شرایط پشتیبانی و نحوۀ ثبت درخواست
  • توضیح اجمالی، دعوت به مشارکت و لینک به CONTRIBUTING.md
  • لینک به صفحات پروژه در شبکه‌های اجتماعی
  • معرفی اجمالی توسعه‌دهندگان پروژه و لینک به صفحات مرتبط آن‌ها در شبکه‌های اجتماعی

CONTRIBUTING.md

در دنیای Open-Source ، آدم‌های زیادی پیدا می‌شوند که به طور رایگان بخواهند به شما کمک کنند؛ بنابراین شما باید با فراهم‌کردن فایل CONTRIBUTING.md مناسب، آن‌ها را در این راه یاری کنید.

پیشنهاد می‌کنیم موارد زیر را حتماً در این فایل بیاورید:

  • پیشنهاد برای چک‌کردن لیست Issue های فعلی و جلوگیری از ثبت Issue تکراری
  • لیست قابلیت‌هایی که دوست دارید توسط دیگران به پروژه اضافه شوند
  • لیست قابلیت‌هایی که دوست ندارید به پروژه اضافه شوند
  • لیست باگ‌هایی که دوست دارید توسط دیگران حل شوند
  • لیست باگ‌هایی که از وجود آن‌ها باخبرید اما قصد برطرف‌کردن آن‌ها را ندارید
  • مراحل ثبت باگ، درخواست امکانات جدید، ارتباط با توسعه‌دهندگان و موارد مشابه
  • پیش‌نیازهای راه‌اندازی پروژه بر روی سیستم شخص
  • نحوۀ Clone کردن و راه‌اندازی پروژه به صورت خط به خط با بیشترین جزئیات ممکن
  • قوانین کدنویسی که در پروژه رعایت می‌کنید
  • قواعد نوشتن Commit Message

IDE

استفاده از Text Editor هایی مانند VS Code فقط برای پروژه‌های کوچک مناسب است. برای پروژه‌های بزرگ، مخصوصاً پروژه‌هایی که به صورت تیمی آن‌ها را توسعه می‌دهید، حتماً از WebStorm استفاده کنید.

ESLint

برای فعال‌کردن تنظیمات ESLint از لینک زیر استفاده کنید:

Prettier

برای فعال‌کردن تنظیمات Prettier از لینک زیر استفاده کنید:

Stylelint

معمولاً هر شخص زمانی که کد CSS می‌نویسد، برای آن قواعدی در نظر می‌گیرد؛ به‌عنوان مثال ترتیب و اولویت Property های مختلف یا استفاده از یک فرمت رنگ خاص. اما زمانی که به صورت تیمی بر روی پروژه‌ای کار می‌کنید، بهتر است این قواعد به صورت عمومی اعمال شوند تا کدی که در نهایت نوشته می‌شود برای همه قابل‌فهم و در یک چارچوب باشد. Stylelint ابزاری است که به ما امکان تعریف چنین قواعدی را می‌دهد.

برای آشنایی بیشتر با StyleLint از لینک‌های زیر استفاده کنید:


General

Download Size

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

پیشنهاد می‌کنیم برای کاهش حجم عکس‌ها از سایت Squoosh استفاده کنید. همچنین به طور کلی حجم فایل‌های svg از فرمت‌های دیگر کمتر است، بنابراین سعی کنید تا جای ممکن از این فرمت استفاده کنید. در صورتی که عکس شما به صورت Raster بود و امکان استفاده از svg را نداشتید، پیشنهاد ما فرمت webp می‌باشد.

به طور کلی توصیه می‌کنیم تا جای ممکن از ویدئو استفاده نکنید.

Comment

زمانی که در حال توسعۀ پروژه هستید، ممکن است بخواهید به‌طور موقت قسمتی از کد را کامنت کنید؛ این مورد به تنهایی مشکلی ندارد اما زمانی که خواستید کد را بر روی نسخۀ master یا main ببرید، حتماً کامنت‌های اضافی را پاک کنید. همچنین به طور کلی زمانی که مجبور شدید برای توضیح قسمتی از کد، از کامنت استفاده کنید، احتمالاً کدی که نوشتید تمیز نیست؛ سعی کنید همیشه کدی بنویسید که بدونِ نیاز به توضیحات، قابل‌فهم باشد.

Unicode Characters

بعضاً مشاهده می‌شود که توسعه‌دهندگان برای نمایش اعداد فارسی از کاراکترهای ۰۱۲۳۴۵۶۷۸۹ استفاده می‌کنند؛ ما پیشنهاد می‌کنیم به‌هیچ‌وجه چنین کاری نکنید؛ در عوض از فونتی استفاده کنید که کاراکترهای 0123456789 را به شکل درست نمایش دهد.


CSS

Reset

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

برای حل این مشکل Reset های متعددی وجود دارد اما ما در اینجا از ساده‌ترین آن‌ها استفاده می‌کنیم:

*,
*::before,
*::after {
box-sizing: border-box;

margin: 0;
padding: 0;
}

BEM

یکی از معروف‌ترین و محبوب‌ترین متدولوژی‌های موجود که در نام‌گذاری المان‌ها استفاده می‌شود، BEM است. با استفاده از این متدولوژی می‌توانید صرفاً با نگاه‌کردن به اسم یک المان، ساختاری که در آن قرار دارد را متوجه شوید. همچنین از آن‌جایی که برای هر المان از یک کلاس مشخص استفاده می‌کنید، به مشکلات مربوط به Specificity برنخواهید خورد.

استفاده از BEM در SCSS بسیار راحت است:

.card {
&__header {
&__icon {
// ...
}

&__title {
// ...
}
}

&--primay {
// ...
}
}

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

Color Syntax

در CSS به طور کلی از 4 روش مختلف می‌توان رنگ یک المان را تعیین کرد که در ادامه به مقایسۀ آن‌ها می‌پردازیم.

Names

شاید به نظر برسد بهترین راه برای مشخص‌کردن یک رنگ، استفاده از اسم آن است. برای رنگ‌هایی که به طور معمول با آن‌ها سروکار داریم و اسم آن‌ها را می‌دانیم، این قضیه صادق است؛ اما CSS دارای بیش از 100 رنگ است که تعداد زیادی از آن‌ها برای توسعه‌دهندگان، به خصوص کسانی که زبان مادری آن‌ها انگلیسی نیست، ناآشنا هستند. از طرفی حتی در مورد رنگ‌هایی که اسم آن‌ها را می‌دانیم، نمی‌توانیم به طور دقیق میزان پُررنگ یا کم‌رنگ‌بودن آن‌ها را تشخیص دهیم. به‌عنوان مثال تفاوت رنگ‌های pink و lightpink در چیست؟ یا کدام‌یک از رنگ‌های hotpink و deeppink پُررنگ‌تر است؟

البته این نوع رنگ‌ها کاملاً هم بلااستفاده نیستند، بلکه بعضاً برای زمانی که صرفاً به‌دنبال تست‌کردن پروژه یا شناسایی باگ هستید، بهترین گزینه‌اند.

HEX

این فرمت از سه عدد در مبنای 16 تشکیل شده است؛ آیا برای اثبات نابهینه‌بودن این فرمت احتیاج به توضیح بیشتری هست؟ جدای از آنکه تشخیص یک عدد مبنای 16 و محاسبه ذهنی برای تبدیل آن به مبنای 10 کاری دشوار است، این فرمت دارای مشکل بزرگ دیگری است که در قسمت RGB به آن اشاره می‌کنیم.

RGB

این فرمت از سه عدد در مبنای 10 تشکیل شده است که به ترتیب نشان‌دهندۀ رنگ‌های قرمز، سبز و آبی هستند. این اعداد از 0 تا 255 می‌توانند متغیر باشند و هر چه عدد متناظر یک رنگ بزرگ‌تر باشد، مقدار بیشتری از آن در رنگ نهایی استفاده خواهد شد.

مشکل این فرمت آن است که نمی‌توان رنگ فعلی را به راحتی تشخیص داد. به‌عنوان مثال rgb(48, 15, 16) مربوط به چه رنگی است؟ درست است که می‌توان متوجه شد رنگ قرمز تقریباً 3 برابر رنگ‌های سبز و آبی استفاده شده است، اما اینکه رنگ نهایی چه چیزی است، بسیار دشوار است. همچنین ساخت نسخه‌های روشن‌تر یا تیره‌تر با استفاده از این فرمت به هیچ عنوان ساده نیست.

HSL

این فرمت از سه قسمت تشکیل شده است که به ترتیب یک زاویه در Color Wheel ، درصد استفاده از رنگ پایه و درصد روشنایی رنگ نهایی را مشخص می‌کنند. اگر Color Wheel و زاویۀ رنگ‌های اصلی را حفظ کنید، به راحتی می‌توانید رنگی که با این فرمت ساخته می‌شود را تشخیص دهید. حفظ‌کردن Color Wheel بسیار ساده‌تر از چیزی است که فکر می‌کنید؛ صرفاً کافی است رنگ‌های رنگین‌کمان را بلد باشد:

  • قرمز: 0
  • نارنجی: 30
  • زرد: 60
  • سبز: 120
  • آبی: 180
  • نیلی: 240
  • بنفش: 270

ایجاد قالب‌های رنگی با استفاده از این فرمت بسیار ساده است؛ از قسمت اول برای تغییر رنگ پایه می‌توانید استفاده کنید و صرفاً با افزودن 180 درجه، به رنگ مکمل می‌رسید؛ قسمت دوم برای تعیین میزان روشنایی در قالب‌های Light و Dark کاربرد دارد؛ قسمت سوم مربوط به روشنایی رنگ نهایی است و می‌توانید از آن برای ایجاد رنگ State هایی مانند Hover استفاده کنید.

:root {
--primary-hue: 220;
--secondary-hue: 260;
--success-hue: 120;
--warning-hue: 20;
--danger-hue: 0;

--color-gray-98: hsl(0, 0%, 98%);
--color-gray-90: hsl(0, 0%, 90%);
--color-gray-80: hsl(0, 0%, 80%);
--color-gray-70: hsl(0, 0%, 70%);
--color-gray-40: hsl(0, 0%, 40%);
--color-gray-30: hsl(0, 0%, 30%);
--color-gray-20: hsl(0, 0%, 20%);
--color-gray-10: hsl(0, 0%, 10%);

--color--default-background: var(--color-gray-98);
--color--default-foreground: var(--color-gray-10);

--color--primary: hsl(var(--primary-hue), 100%, 56%);
--color--primary-fade: hsl(var(--primary-hue), 100%, 96%);
--color--primary-lighter: hsl(var(--primary-hue), 100%, 60%);
--color--primary-darker: hsl(var(--primary-hue), 100%, 52%);
--color--primary-opposite: var(--color-gray-98);

--color--secondary: hsl(var(--secondary-hue), 50%, 50%);
--color--secondary-fade: hsl(var(--secondary-hue), 100%, 90%);
--color--secondary-lighter: hsl(var(--secondary-hue), 50%, 56%);
--color--secondary-darker: hsl(var(--secondary-hue), 50%, 44%);
--color--secondary-opposite: var(--color-gray-98);

--color--warning: hsl(var(--warning-hue), 100%, 44%);
--color--warning-fade: hsl(var(--warning-hue), 100%, 90%);
--color--warning-lighter: hsl(var(--warning-hue), 100%, 50%);
--color--warning-darker: hsl(var(--warning-hue), 100%, 40%);
--color--warning-opposite: var(--color-gray-98);

--color--success: hsl(var(--success-hue), 100%, 40%);
--color--success-fade: hsl(var(--success-hue), 100%, 92%);
--color--success-lighter: hsl(var(--success-hue), 100%, 44%);
--color--success-darker: hsl(var(--success-hue), 100%, 36%);
--color--success-opposite: var(--color-gray-98);

--color--danger: hsl(var(--danger-hue), 100%, 36%);
--color--danger-fade: hsl(var(--danger-hue), 100%, 90%);
--color--danger-lighter: hsl(var(--danger-hue), 100%, 42%);
--color--danger-darker: hsl(var(--danger-hue), 100%, 30%);
--color--danger-opposite: var(--color-gray-98);
}

Font Management

Multiple Fonts

در کل پروژه فقط از یک فونت استفاده کنید. کمتر پیش می‌آید استفاده از دو فونت مجزا، نتیجۀ مطلوبی داشته باشد؛ مخصوصاً برای سایت‌های فارسی. اگر قسمتی از سایت شما فارسی و قسمت دیگر انگلیسی است، از دو فونت برای آن‌ها استفاده نکنید؛ بلکه به‌دنبال فونتی بگردید که هر دو را به خوبی نشان دهد.

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

font-family

استایل‌های مربوط به font-family را به * ندهید چراکه باعث بالا رفتن Specificity می‌شود و در کار بعضی از کتابخانه‌ها مانند Fontawesome یا Monaco Editor خلل ایجاد می‌کند. در عوض می‌توانید این استایل را به html بدهید. از آنجایی که font از المان پدر به ارث می‌رسد، تمام المان‌های شما فونت مورد نظر را خواهند داشت. اما بعضی از المان‌ها مانند input و button احتیاج دارند که به طور دقیق فونت آن‌ها را مشخص کنید.

برای راحتی کار می‌توانید از کد زیر استفاده کنید:

html {
font-family: Poppins, sans-serif;
}

input,
label,
select,
textarea,
button,
fieldset,
legend,
datalist,
output,
option,
optgroup {
font-family: inherit;
}
Generic Default Fonts

همیشه یک فونت پیش‌فرض مانند sans-serif را به آخر font-family اضافه کنید تا در صورتی که به هر دلیلی فونت اصلی از کار افتاد، مرورگر بتواند از فونت پیش‌فرض استفاده کند. دقت کنید که فقط فونت‌های Generic می‌توانند به‌عنوان Fallback استفاده شوند؛ یعنی:

  • serif
  • sans-serif
  • cursive
  • fantasy
  • monospace

rem & px

همان‌طور که می‌دانید به طور پیش‌فرض هر rem برابر با 16px است. این موضوع باعث می‌شود زمانی که می‌خواهید از rem استفاده کنید، مجبور به انجام محاسبات نسبتاً سختی باشید که سرعت توسعه و از همه مهم‌تر خوانایی کد را کاهش می‌دهد. برای حل این مشکل پیشنهاد می‌کنیم سایز فونت html را به %62.5 تغییر دهید؛ با این کار هر rem برابر با 10px خواهد شد.

Variables

ما پیشنهاد می‌کنیم همیشه به طور پیش‌فرض از متغیرهای CSS استفاده کنید و تنها در صورتِ نیاز به متغیرهای SCSS رجوع کنید.

همچنین پیشنهاد می‌کنیم متغیرها را قبل از بقیۀ Rule ها تعریف کنید تا خوانایی کد بالا رود و از اشتباهات احتمالی جلوگیری شود:

.item {
--size: 10rem;
--gap: 1rem;

/* ... */
}

Transition/Animation Performance

در صورتی که فقط از transform و opacity برای انجام Animation های خود استفاده کنید، فقط مرحله Composite اجرا می‌شود و مرورگر می‌تواند تمام کارها را بر عهدۀ GPU بگذارد. بنابراین همیشه سعی کنید فقط از این دو Property استفاده کنید.

دقت کنید که در اینجا منظور تنها کلیدواژۀ animation یا keyframe نیست، بلکه transition و به طور کلی هر راهی که بتوان با آن ظاهر یک المان را به تدریج عوض کرد، مد نظر است.

Zero Unit

در CSS زمانی که از عدد 0 استفاده می‌کنید، بهتر است واحدی برای آن در نظر نگیرید.

/* Bad */
.item {
margin: 0rem auto;
}

/* Good */
.item {
margin: 0 auto;
}

Logical Properties

اگر قبلاً بر روی پروژه‌ای کار کرده باشید که هم‌زمان باید از دو زبان انگلیسی و فارسی پشتیبانی می‌کرد، قطعاً متوجه شده‌اید که نیاز است خیلی از استایل‌هایی که به راست یا چپ ربط دارند را عوض کنید. به‌عنوان مثال اگر از margin-left در نسخۀ انگلیسی استفاده کردید، باید در نسخۀ فارسی آن را به margin-right تغییر می‌دادید. خوشبختانه در CSS برای حل این مشکل می‌توان از Logical Properties استفاده کنیم؛ در این صورت، مرورگر بر اساس Direction سایت، استایل‌ها را اعمال می‌کند.

در ادامه برای سایتی که LTR است، معادل چند Property پُر استفاده را می‌آوریم:

Normal PropertyLogical Property
topinset-block-start
bottominset-block-end
leftinset-inline-start
rightinset-inline-end
margin-topmargin-block-start
margin-bottommargin-block-end
margin-leftmargin-inline-start
margin-rightmargin-inline-end
padding-toppadding-block-start
padding-bottompadding-block-end
padding-leftpadding-inline-start
padding-rightpadding-inline-end
heightblock-size
min-heightmin-block-size
max-heightmax-block-size
widthinline-size
min-widthmin-inline-size
max-widthmax-inline-size

هم‌چنین می‌توانید دو Logical Property را که هر دو Inline یا Block هستند، همزمان مقداردهی کنید. برای روشن‌تر شدن موضوع، سه کد معادل زیر را در نظر بگیرید:

.item {
padding-top: 1rem;
padding-bottom: 1rem;
}

/* or */

.item {
padding-block-start: 1rem;
padding-block-end: 1rem;
}

/* or */

.item {
padding-block: 1rem;
}

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


پروژه

هدف

بررسی کد پروژه فاز Angular با استفاده از قواعد Clean Code

مراحل

  1. کد پروژه خود در فاز Angular را بررسی کنید و اگر جایی قواعدی که توضیح داده شده است را رعایت نکردید آن را اصلاح کنید
  2. پس از بررسی کد خود شما باید حداقل Pull Request یکی از تیم‌هارا بررسی کنید

نکات

  • کد پروژه شما حداقل باید توسط یکی از تیم‌ها بررسی شود و Approve داده شود