وقتی درباره رشد Design System صحبت میکنیم، معمولاً تمرکزمون روی اضافه کردن چیزهای جدیده؛ Component جدید، Variant جدید، Token جدید یا Pattern جدید. اما یک Design System فقط با چیزهایی که بهش اضافه میکنیم رشد نمیکنه. بخشی از نگهداری سیستم، تصمیم گرفتن درباره چیزهاییه که دیگه نباید داخلش باقی بمونن.
فرض کنید Library ما طی چند سال به ۸۰ Component رسیده. بعضی از اونها تقریباً در تمام محصولات استفاده میشن، بعضی فقط چند Consumer دارن و تعدادی هم هنوز در Library هستن، اما مدتهاست هیچ تیمی برای Feature جدید سراغشون نرفته. در همین مدت، Patternهای جدیدتری ساخته شدن و بعضی Componentهای قدیمی فقط به این دلیل باقی موندن که هنوز چند صفحه Legacy به اونها وابستهان.
در چنین شرایطی، داشتن Componentهای بیشتر الزاماً نشانه کاملتر شدن Design System نیست. هر Componentی که داخل سیستم نگه میداریم، یک هزینه نگهداری هم با خودش میاره.
اگر یک Component داخل Library رسمی وجود داشته باشه، تیم باید مطمئن بشه با تغییر Tokenها خراب نمیشه، در Themeهای مختلف درست کار میکنه، Accessibility اون حفظ شده، Documentation اون معتبره، تغییرات جدید سیستم رو پشتیبانی میکنه و نسخه Code و Design اون از هم فاصله نگرفتن.
بنابراین سؤال فقط این نیست که «آیا هنوز کسی از این Component استفاده میکنه؟». سؤال مهمتر اینه:
آیا ارزشی که این Component ایجاد میکنه، هنوز بیشتر از هزینه نگهداری اونه؟
کم بودن Usage بهتنهایی دلیل حذف نیست
اولین چیزی که احتمالاً برای پیدا کردن Componentهای قدیمی بررسی میکنیم، میزان Usage اونهاست. اگر یک Component فقط در دو نقطه استفاده شده، در حالی که Component دیگهای در صدها صفحه وجود داره، طبیعیه که درباره آینده اون سؤال کنیم.
اما کم بودن Usage بهتنهایی معیار خوبی برای حذف نیست.
ممکنه یک FileUploader فقط در چند Flow استفاده بشه، اما همون Flowها برای محصول حیاتی باشن. از طرف دیگه، ممکنه Componentی Usage نسبتاً بالایی داشته باشه، اما فقط به این دلیل که در صفحات Legacy زیادی باقی مونده و تیمها برای Featureهای جدید دیگه ازش استفاده نمیکنن.
پس بهتره فقط نپرسیم «چند بار استفاده شده؟» بلکه بپرسیم «استفاده از اون در حال رشد، ثابت یا کاهش است؟»
این تفاوت مهمیه. تعداد Consumerها وضعیت امروز رو نشون میده، اما روند استفاده میتونه درباره آینده Component اطلاعات بیشتری بهمون بده.
یکی از نشانههای مهم، ظهور یک جایگزین بهتره
فرض کنید در Design System یک Dropdown قدیمی داریم که چند سال پیش ساخته شده. بعداً Component جدیدتری ایجاد کردیم که Keyboard Navigation بهتری داره، Accessibility اون کاملتره و API سادهتری هم ارائه میده.
حالا ممکنه هر دو Component همچنان داخل Library وجود داشته باشن.
تیمهای قدیمی از نسخه قبلی استفاده میکنن و تیمهای جدید گاهی نمیدونن باید کدوم رو انتخاب کنن. Documentation هر دو هم وجود داره و تیم Design System مجبور میشه هر تغییر مهم رو روی هر دو بررسی کنه.
در چنین شرایطی، مشکل فقط نگهداری Code اضافه نیست؛ وجود دو راهحل رسمی برای یک مسئله، خودش هزینه تصمیمگیری ایجاد میکنه.
یکی از کارکردهای Design System اینه که بخشی از تصمیمهای تکراری رو از دوش تیمهای محصول برداره. اگر برای یک مسئله چند راهحل رسمی و مشابه داشته باشیم، سیستم کمکم همون تصمیمهایی رو به مصرفکننده برمیگردونه که قرار بوده حذف کنه.
گاهی Component هنوز استفاده میشه، اما دیگه سالم نیست
یکی از اشتباهها اینه که بازنشسته کردن رو فقط برای Componentهایی در نظر بگیریم که کسی از اونها استفاده نمیکنه.
ممکنه یک Component همچنان Usage بالایی داشته باشه، اما هزینه نگهداری اون دائماً در حال افزایش باشه. برای هر Feature جدید باید Exception تازهای بهش اضافه کنیم، API اون پر از Propهای قدیمی شده، اصلاح Accessibility اون سخت شده یا معماری داخلیش اجازه نمیده با نیازهای جدید Design System هماهنگ بشه.
در چنین شرایطی، Usage بالا اتفاقاً حذف Component رو سختتر میکنه، نه اینکه ثابت کنه باید برای همیشه نگهش داریم.
اینجا باید بین Popularity و Health تفاوت قائل بشیم. یک Component میتونه پرکاربرد باشه و در عین حال از نظر معماری ناسالم باشه.
بازنشسته کردن با حذف کردن فرق داره
اگر تشخیص دادیم Componentی دیگه نباید بخشی از آینده Design System باشه، نباید فردای همون روز اون رو از Library حذف کنیم.
برای هر Component میتونیم یک Lifecycle مشخص در نظر بگیریم و وضعیت اون رو هم به بخشی از اطلاعات رسمی سیستم تبدیل کنیم. برای مثال، یک مسیر ساده میتونه این باشه:
Experimental → Stable → Deprecated → Retired
در مرحله Experimental هنوز در حال یادگیری هستیم و API ممکنه تغییر کنه. وقتی Pattern تثبیت شد، Component وارد وضعیت Stable میشه و تیمها میتونن با اطمینان بیشتری از اون استفاده کنن.
اگر بعداً جایگزین بهتری ساخته بشه یا Component دیگه با جهت سیستم هماهنگ نباشه، میتونه وارد وضعیت Deprecated بشه.
وقتی یک Component در وضعیت Deprecated قرار میگیره، همچنان کار میکنه، اما نباید در Featureهای جدید استفاده بشه.
این فاصله خیلی مهمه، چون به تیمها فرصت Migration میده. در این مرحله میتونیم جایگزین مناسب رو در Documentation معرفی کنیم، در Code هشدار نمایش بدیم، Migration Guide آماده کنیم و تیمها رو بهتدریج از نسخه قدیمی به راهحل جدید منتقل کنیم.
تنها زمانی که وابستگیها به سطح قابل قبولی رسیدن، Component میتونه وارد وضعیت Retired بشه و واقعاً از سیستم حذف بشه.
تصمیم بازنشستگی باید براساس چند نشانه گرفته بشه
بهتره تصمیم درباره آینده Component به نظر یک نفر یا یک Review مقطعی وابسته نباشه. میتونیم چند نشانه رو کنار هم بررسی کنیم.
کاهش Usage در Featureهای جدید، وجود جایگزین بهتر، افزایش تعداد Bugها، زیاد شدن Exceptionها، هزینه بالای هماهنگی با Tokenها و Themeهای جدید، مشکلات Accessibility، اختلاف Design و Code و هزینه بالای تغییر API همگی میتونن نشونههایی باشن که Component نیاز به بازبینی داره.
نکته مهم اینه که هیچکدوم از این نشانهها بهتنهایی حکم حذف نیستن.
برای مثال، Usage پایین ممکنه کاملاً منطقی باشه. تعداد زیاد Bug هم شاید به دلیل اهمیت و Usage بسیار بالای Component باشه. اما وقتی چند نشانه همزمان دیده میشن، احتمالاً وقتشه درباره ادامه عمر Component تصمیم بگیریم.
در واقع بهتره بهجای داشتن یک Component Inventory ساده، کمکم وضعیت Component Health رو هم بررسی کنیم.
اضافه کردن هر Component باید یک تعهد نگهداری ایجاد کنه
این نگاه یک نتیجه مهم دیگه هم داره.
وقتی Component جدیدی وارد Core Design System میکنیم، فقط یک Asset جدید اضافه نکردیم؛ یک تعهد بلندمدت هم پذیرفتیم.
از اون لحظه باید Component رو Test کنیم، Documentation اون رو نگه داریم، Bugهاش رو رفع کنیم، Accessibility اون رو بررسی کنیم، با تغییر Foundationها سازگار نگهش داریم و مراقب Breaking Changeها برای Consumerهای فعلی باشیم.
به همین دلیل، تصمیم ورود Component به Core باید کمی شبیه تصمیم اضافه کردن یک Dependency بلندمدت دیده بشه.
اگر ورود آسون باشه ولی برای خروج فرآیندی نداشته باشیم، Library فقط در یک جهت حرکت میکنه: بزرگتر شدن.
بعد از چند سال هم با سیستمی روبهرو میشیم که تعداد Componentهاش زیاد شده، اما کسی دقیقاً نمیدونه کدومها هنوز بخشی از مسیر آینده سیستم هستن.
شاید توانایی حذف کردن یکی از معیارهای بلوغ Design System باشه
یک Design System بالغ فقط نباید بدونه چه چیزی رو استاندارد کنه؛ باید بتونه تشخیص بده چه زمانی یک استاندارد دیگه مفید نیست.
نیازهای محصول تغییر میکنن، تکنولوژی تغییر میکنه، استانداردهای Accessibility جلو میرن و Patternهایی که زمانی بهترین تصمیم بودن ممکنه چند سال بعد جای خودشون رو به راهحل بهتری بدن.
اگر سیستم نتونه همراه این تغییرها بعضی تصمیمهای قدیمی خودش رو کنار بذاره، بهمرور تبدیل به آرشیوی از تمام تصمیمهایی میشه که تیم در طول سالها گرفته.
در حالی که هدف Design System نگهداری تاریخچه تصمیمها نیست؛ هدفش فراهم کردن بهترین مجموعه فعلی از تصمیمهای مشترک برای تیمهاست.
جمعبندی
هر Componentی که وارد Design System میشه، نباید برای همیشه در اون باقی بمونه.
بعضی Componentها ممکنه Usage خودشون رو از دست بدن، بعضی جایگزین بهتری پیدا کنن، بعضی از نظر معماری به بنبست برسن و بعضی هم با وجود Usage بالا، هزینه نگهداری زیادی به سیستم تحمیل کنن.
به همین دلیل، بهتره Componentها رو Assetهای دائمی نبینیم. اونها بخشی از یک Lifecycle هستن و باید بتونن از Experimental به Stable برسن، در صورت نیاز Deprecated بشن و در نهایت با یک Migration کنترلشده از سیستم خارج بشن.
شاید سؤال مهم برای ارزیابی یک Design System فقط این نباشه که:
امسال چند Component جدید اضافه کردیم؟
سؤال مهمتر اینه:
آخرین بار چه زمانی تشخیص دادیم یک Component دیگه نباید بخشی از سیستم باشه؟
اگر جواب «هیچوقت» باشه، شاید Design System ما در حال رشد نباشه؛ فقط در حال بزرگتر شدنه.
کامنتها
…