آرش منطقی،

طراح و توسعه‌دهنده رابط کاربری

توسعه کدهای CSS با قابلیت خوانایی و استفاده مجدد

css

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

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

ما معمولاً برای اینکه کدی تمیز، خوانا و قابل نگهداری تولید کنیم، به مشکلاتی بر می‌خوریم که باید اون‌ها رو حل کنیم. اما بهتره اول چندتا از این مشکلات رو بشناسیم:

۱- تکرار کردن کدهای روتین و معمول
۲- تکرار پیشوندهای مرورگرها
۳- عدم پایپندی به درج کامنت‌ها
۴- استفاده از سلکتورهای بیش از حد
۵- نام‌گذاری ضعیف کلاس‌ها
۶- و خیلی چیزهای دیگه…

اگر شما به ندرت برای کدهای خودتون کامنت می‌گذارید یا فقط تحت شرایطی، آن هم از روی ناچاری این کار رو می‌کنید، باید بگم این سیاست اشتباهی هست. شاید فکر کنید نام‌گذاری‌ای که برای کلاس‌ها دارید به حد کافی با معنی است و نیازی به کامنت نیست. اما اگر بعد از مدتی، برای بروزرسانی و تغییرات به کدهای خود سر بزنید قطعاً درک کدهایی که خودتون نوشتید براتون سخت میشه. از طرفی وقتی کار تیمی انجام میدین قطعاً نیاز هست که دیگران کدهای شما رو بخونند و شما هم کدهای اون‌ها رو. پروژه‌های تیمی معمولاً پروژه‌های بزرگی هستند که قائدتاً طول عمر بالاتری دارند، پس کدهای شما هم باید طول عمر بالاتری داشته باشه و در گذر زمان قابلیت نگهداشت و بروزرسانی داشته باشند. ترفندها و ترندهایی که الان در کدها استفاده می‌کنید قطعاً دو سه سال دیگه چیزهای پیش پا افتاده‌ای به حساب میاد که باید تغییرش بدید یا به روش‌های بهتر اون‌ها رو پیاده‌سازی کنید. استفاده از هک‌های CSS از این نمونه هست. اما راه حل چیست؟ در ادامه به ایده‌های کلی درباره راه حل‌های موجود می‌پردازیم.

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

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

کدهای CSS شئ‌گرا
حتماً با مفهوم شئ‌گرایی در برنامه نویسی آشنا هستید یا حداقل اسمش رو شنیدید. شئ‌گرایی یک الگوی برنامه‌نویسی هست و برای شکستن کارهای بزرگ به چند کار کوچک استفاده میشه. وقتی این مفهوم به دنیای استایل‌شیت‌ها میاد بهش میگیم OOCSS یا همون Object Oriented CSS. در اینجا ما کمتر با تکنیک‌های پیاده‌سازی سر به کار داریم بلکه مهم طرز فکر ما نسبت به روند توسعه هست. مفهوم اصلی در جداسازی ساختار عناصر، از استایل آن‌هاست. به این ترتیب نتیجه این کپسوله سازی این هست که میتونیم بدون پیاده‌سازی مجدد عناصر، از آن‌ها در قطعات مختلف کد استفاده‌ی مجدد کنیم که باعث میشه سرعت توسعه افزایش پیدا کنه و حجم کد تولیدی کاهش داشته باشه.

ساختار عناصر رو میتونید به عنوان اسکلت اون‌ها در نظر بگیرید. در اینجا ما بیشتر با مفاهیم باکس مدل و لیوت‌ها سر به کار داریم و به این ترتیب فریم‌هایی بوجود میاریم که ازشون می‌توانیم به عنوان آبجکت استفاده کنیم. این آبجکت‌ها خالی از هرگونه استایل‌های بصری هستند. در مرحله بعد می‌توانیم به صورت اختیاری هر پوسته‌ی ظاهری که خواستیم رو ایجاد و روی این آبجکت‌ها اعمال کنیم. به مثال زیر توجه کنید:

/* A simple, design-free button object. Extend this object with a `.btn--*` skin class. */
.btn {
    display: inline-block;
    padding: 1em 2em;
    vertical-align: middle;
}

/* Positive buttons' skin. Extends `.btn`. */
.btn--positive {
    background-color: green;
    color: white;
}

/* Negative buttons' skin. Extends `.btn`. */
.btn--negative {
    background-color: red;
    color: white;
}

در اینجا یک کلاس btn. می‌بینید که ساختار عنصر مورد نظر را طرح ریزی کرده است. اما هیچ رنگ و لعابی نداره. در قدم بعدی کلاس btn–positive. رو به عنصر مورد نظر اعمال می‌کنیم تا به اون دیزاینی که میخواستیم برسیم. ما میتونیم انبوهی از این استایل‌های بصری رو داشته باشیم و از هر کدوم، تو هر دکمه‌ای که نیاز بود استفاده کنیم. این درک و مفهومی هست که فریمورک‌های فرانت‌اند هم ازش استفاده می‌کنند. اما حالا که بحث به ایجاد کامپوننت‌ها رسید و دیدیم که آینده توسعه خوب بر مبنی مفهوم کامپوننت استواره، اجازه بدید کمی عمیق‌تر به جنبه‌های نام گذاری در این روش بپردازیم.

نام‌گذاری متغییرها
برای شروع شاید بد نباشه اگر نگاهی به نام‌گذاری متغییر‌ها در پیش پردازنده‌ها بندازیم. تو خیلی از سورس‌کدها، به این شیوه نام گذاری متغییرها انجام میشه:

/* Background Colors */ 
$background:
$header-background:
$content-background:

/* Colors */
$heading-color:
$link-color:

شاید این شیوه بد نباشه، اما عالی هم نیست. چون گروه بندی متغییر‌ها از هیچ استراتژی نام‌گذاری‌ای پیروی نمیکنه. بهتره کمی معنایی‌تر و قابل گروه‌بندی‌تر اسامی متغییر‌ها رو انتخاب کرد. من این روش رو پیشنهاد میکنم:

/* Background Colors */ 
$background:
$background-header:
$background-content:

/* Colors */
$color-heading:
$color-link:

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

BEM چیست؟
BEM یک متدولوژی برای توسعه فرانت‌اند هست و میشه ازش به عنوان یه متدولوژی کامل نام برد. چیزی که توجه ما رو میتونه جلب کنه استراتژی نام‌گذاری در این متد هست. با استفاده از این استراتژی میتونیم کلاس‌ها رو به ۳ گروه کلی تقسیم کنیم:

یک قیاس از ۳گروه بالا رو در این بخش میبینید که عناصر با دوتا زیر خط(__) و پیراینده‌ها با دوتا خط تیره(-‌-) از هم دیگه متمایز میشن.

.dog {}
.dog__tail {}
.dog--small {}

در قیاس فوق، ما dog. رو به عنوان به عنوان یه بلاک می‌بینیم که اساس کامپوننت ما هست. سپس dog__tail.(دُم سگ) یک عنصر هست و در واقع بخشی از کامپوننت اصلی ما(سگ) محسوب میشه، که البته خودش یه کامپوننت کوچک‌تر هست. و در نهایت dog-‌-small. یک پیراینده برای بلاکِ سگ هست. ما حتی میتونیم برای عناصر هم پیراینده داشته باشیم. به عنوان مثال dog__tail–short. یک تغییر ظاهری برای دم سگ ایجاد میکنه.

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

/* Block component */
.btn {}

/* Element that depends upon the block */ 
.btn__price {}

/* Modifier that changes the style of the block */
.btn--orange {} 
.btn--big {}

ساختار بندی ماژولار
ما تمام این حرف‌ها رو زدیم تا مدیریت خوبی روی کدهای نوشته شده داشته باشیم و اون‌ها رو بهتر سازماندهی کنیم. پس باید یادآور شم که همیشه کدنویسی ماژولار رو هم در نظر داشته باشید، و اگر از فریمورک خاصی استفاده نمی‌کنید، سعی کنید ساختاری شبیه به یک فریمورک ساده را برای پروژه‌ خودتون در نظر بگیرید و کدهای هر ماژول رو در جای درستش بنویسید. یه ساختار پیشنهادی ساده می‌تونه به صورت زیر باشه:

SMACSS چیست؟
مطالبی که تا اینجا گفتیم، میتونه برای توسعه بهتر برامون مفید باشه، اما میتونیم تمام چیزهای گفته شده رو کنار بزاریم و سعی در استفاده از SMACSS داشته باشیم. SMACSS یا سمکس(با تلفظ smacks) مجموعه‌ای از گاید‌لاین‌ها هست که به ما کمک می‌کنه تا کد بهتری در CSS تولید کنیم. سمکس نه ابزار توسعه هست و نه قوانین سختگیرانه‌ای که باعث هراس توسعه‌دهنده‌ها باشه؛ بلکه به نظر من راهنمای منعطفی هست که در نظر گرفتنش دید بهتری در زمینه توسعه کدهای فرانت‌اند بهمون میده. هدف سمکس همون چیزی هست که ما در این پست دنبالش می‌کنیم، یعنی تولید کدهایی که خوانایی بالاتری داشته باشند، قابل توسعه و نگهداشت باشند، و امکان استفاده مجدد از اون‌ها وجود داشته باشه.

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

اگر بخوایم نگاه کلی‌ای به اون چیزی که سمکس به ما پیشنهاد میده داشته باشیم، بهتره که با ساختاربندی پروژه شروع کنیم. سمکس هسته پروژه رو در ۵ دسته بندی کلی قرار داده و با تعاریف و مثال‌هایی از قطعه کدهای کاربردی، سعی داره تا مفاهیم لازم رو به مخاطبین انتقال بده. این ۵ دسته به قرار زیر هستند:

قوانین Base شامل تعریفات اولیه هستند، به عنوان مثال تعریف فونت و سایز متن برای پروژه، پیش‌فرض‌هایی که برای فرم‌ها در نظر گرفته میشه، رنگ لینک‌ها و هاور لینک‌ها و قوانین پایه‌ای دیگر. حتی فریمورک‌های CSS Reset رو هم میتونیم جزء این دسته‌بندی در نظر بگیریم.

قوانین Layout برای بخش‌بندی صفحه به اجزای کوچکتر در نظر گرفته میشه. تعریف مختصات و مکان نمایش هدر و فوتر از این دست از قوانین هستند. layoutها مکانی هستند که ماژول‌ها در اون‌ها قرار می‌گیرند. سیستم‌گرید‌هایی مثل 960 و Susy هم در این دسته از قوانین طبقه‌بندی می‌شوند.

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

قوانین Satet راهی هستند برای تشریح چگونگی نمایش ماژول‌ها و لی‌اوت‌ها در یک state خاص. به عنوان مثلاً فرض کنید یک دکمه رو به عنوان ماژول طراحی کرده‌اید. این دکمه می‌تواند در وضعیت فعال و یا غیر فعال نمایش داده شود؛ می‌تواند دکمه حذف کالا و یا اضافه کردن کالا به سبد خرید باشد.

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

در کنار تعریف ساختار فوق، میتوان از قوانین نام‌گذاری‌ای که سمکس پیشنهاد کرده نیز پیروی کرد. به عنوان مثال استفاده از پیشوند‌هایی مانند -l و یا -grid برای لی‌اوت‌ها از این دست از قوانین هستند. توسعه دهندگان بسته با قوانینی که در نظر می‌گیرند می‌توانند مستندسازی خاص خود را داشته باشند.

این توضیحات ترسیمی از اون چیزی هست که سمکس برای توسعه‌دهنده به ارمغان میاره. من پیشنهاد می‌کنم داکیومنت‌های مفصل‌تر رو از سایت سمکس مطالعه کنید.

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

Screen Shot 2016-03-13 at 12.17.16 PM

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

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

آرش.