اشتباه بزرگ توسعهدهندههای فرانت اند
ماهان زندی
توسعه دهنده نرم افزار

اشتباه بزرگ توسعهدهندههای فرانتاند
اگر چند سال با React، Next.js یا فریمورکهای مدرن کار کرده باشید، احتمالاً یک اشتباه را دیر یا زود تجربه میکنید:
اینکه فکر کنید هر پروژهای باید با همان تکنولوژیهایی ساخته شود که در آنها مهارت بیشتری دارید.
من هم این اشتباه را کردهام.
مدتی تصور میکردم اگر پروژهای را با React یا Next.js بسازم، حتماً انتخاب حرفهایتری داشتهام. تا اینکه برای یک لندینگ پیج ساده، متوجه شدم بخشی از پیچیدگیای که به پروژه اضافه کردهام، اصلاً مسئلهای را حل نمیکند.
وقتی ابزار تبدیل به عادت میشود
وقتی مدت زیادی با یک تکنولوژی کار میکنیم، طبیعی است که هنگام شروع یک پروژه جدید، همان تکنولوژی اولین چیزی باشد که به ذهنمان میرسد.
یک پروژه جدید؟
React.
چند صفحه بیشتر؟
Next.js.
یک فرم؟
React Hook Form.
یک state ساده؟
Zustand.
و به همین شکل، پروژهای که میتوانست با چند فایل HTML، CSS و JavaScript تمام شود، تبدیل به پروژهای با framework، dependency، build process و ساختار پیچیدهتر میشود.
مشکل React یا Next.js نیست.
مشکل زمانی شروع میشود که تکنولوژی را قبل از مسئله انتخاب کنیم.
یک لندینگ پیج واقعاً به React نیاز دارد؟
فرض کنید قرار است یک وبسایت برای معرفی یک محصول بسازیم.
چه چیزهایی داریم؟
چند سکشن، تصاویر، متن، چند انیمیشن، یک فرم تماس و شاید چند تعامل ساده.
آیا واقعاً به یک اپلیکیشن React نیاز داریم؟
احتمالاً نه.
میتوان این پروژه را با HTML و CSS و مقدار کمی JavaScript ساخت. نتیجه میتواند سادهتر، سبکتر و حتی سریعتر باشد.
البته این به معنی بد بودن React نیست.
اگر همین پروژه قرار باشد به یک اپلیکیشن تعاملی تبدیل شود، componentهای زیادی داشته باشد، state پیچیده داشته باشد یا بخشهای مختلف آن دائماً تغییر کنند، شرایط کاملاً متفاوت است.
پس سؤال درست این نیست:
«React بهتر است یا HTML؟»
سؤال درست این است:
«این پروژه دقیقاً چه مشکلی دارد که باید حل شود؟»
Over-Engineering؛ وقتی بیشتر از نیازمان میسازیم
یکی از چیزهایی که با تجربه بیشتر متوجه شدم، تفاوت بین حل مسئله و پیادهسازی تکنولوژی است.
گاهی آنقدر درگیر انتخاب framework، معماری، design pattern و ساختار پروژه میشویم که فراموش میکنیم محصول قرار است چه کاری انجام دهد.
Over-Engineering همیشه به معنی نوشتن کد بیشتر نیست.
گاهی یعنی:
استفاده از یک framework برای مسئلهای که به آن نیاز ندارد
اضافه کردن dependency بدون نیاز واقعی
ساخت abstraction قبل از اینکه تکراری بودن کد ثابت شده باشد
طراحی معماری پیچیده برای یک پروژه کوچک
استفاده از state management در جایی که یک state ساده کافی است
ساختن چیزی برای «آینده» که شاید هیچوقت اتفاق نیفتد
این پیچیدگیها در ابتدا شاید دیده نشوند، اما بعداً هزینه خودشان را نشان میدهند.
هزینهای که در ابتدا دیده نمیشود
هر تکنولوژی جدید فقط قابلیت اضافه نمیکند؛ یک هزینه هم همراه خودش میآورد.
Dependency بیشتر یعنی چیزهای بیشتری که باید مدیریت شوند.
Abstraction بیشتر یعنی چیزهای بیشتری که توسعهدهنده بعدی باید بفهمد.
Architecture پیچیدهتر یعنی تصمیمهای بیشتری که باید در آینده حفظ شوند.
و در نهایت، کد بیشتر یعنی سطح بیشتری برای نگهداری و تغییر.
این موضوع مخصوصاً در پروژههای کوچک مهم است.
چون ممکن است برای حل یک مسئله ساده، یک سیستم کامل بسازیم.
در حالی که خود مسئله فقط به چند خط کد نیاز داشته است.
اما از آن طرف، سادهسازی افراطی هم اشتباه است
این مقاله قرار نیست بگوید:
«React بد است.»
یا:
«همهچیز را با Vanilla JavaScript بنویسید.»
این هم خودش یک نوع تفکر افراطی است.
یک اپلیکیشن SaaS با داشبورد، احراز هویت، state پیچیده، تعاملات زیاد و چندین بخش مختلف، احتمالاً با HTML و JavaScript ساده انتخاب مناسبی نیست.
یک فروشگاه اینترنتی بزرگ هم ممکن است به قابلیتهایی نیاز داشته باشد که استفاده از یک meta-framework مثل Next.js را منطقی کند.
هدف این نیست که همیشه سادهترین تکنولوژی را انتخاب کنیم.
هدف این است که کمترین پیچیدگی لازم برای حل مسئله را انتخاب کنیم.
قبل از انتخاب تکنولوژی، مسئله را بشناس
من امروز قبل از شروع یک پروژه سعی میکنم چند سؤال ساده از خودم بپرسم.
۱. پروژه چقدر تعاملی است؟
آیا کاربر دائماً با رابط کاربری تعامل دارد؟
آیا state پیچیده داریم؟
آیا دادهها دائماً تغییر میکنند؟
اگر جواب این سؤالات «نه» باشد، شاید نیازی به یک SPA کامل نداشته باشیم.
۲. SEO چقدر اهمیت دارد؟
اگر پروژه یک وبسایت محتوایی یا landing page باشد، نحوه ارائه HTML و performance اهمیت زیادی پیدا میکند.
اما اگر با یک داشبورد داخلی طرف باشیم که فقط کاربران لاگینشده از آن استفاده میکنند، SEO احتمالاً مسئله اصلی نیست.
۳. پروژه قرار است چقدر رشد کند؟
یک پروژه شخصی کوچک با یک محصول SaaS که قرار است چند سال توسعه پیدا کند، شرایط یکسانی ندارند.
نباید معماری یک سیستم بزرگ را فقط به این دلیل که «شاید روزی لازم شود» روی یک پروژه کوچک پیاده کنیم.
۴. تیم چه چیزی را بلد است؟
تکنولوژی باید به تیم هم توجه کند.
گاهی استفاده از یک تکنولوژی که تیم به آن مسلط است، از نظر زمان توسعه و نگهداری منطقیتر است؛ حتی اگر روی کاغذ گزینه دیگری جذابتر به نظر برسد.
Right Tool, Right Job
به مرور به یک اصل ساده رسیدم:
برای هر پروژه یک تکنولوژی برنده وجود ندارد.
برای یک Landing Page:
HTML/CSS/JS یا یک Static Site Generator سبک ممکن است کاملاً کافی باشد.
برای یک Web Application:
React، Vue یا Svelte میتوانند انتخابهای منطقی باشند.
برای یک محصول بزرگتر که به SSR، routing، data fetching و ساختار یکپارچه نیاز دارد:
استفاده از یک Meta-framework مثل Next.js میتواند منطقی باشد.
و حتی در بعضی پروژهها، استفاده از یک CMS یا ابزار آماده ممکن است از نوشتن همهچیز از صفر بهتر باشد.
حرفهای بودن همیشه به معنی انتخاب تکنولوژی پیچیدهتر نیست.
گاهی حرفهایترین تصمیم این است که اصلاً چیزی را اضافه نکنیم.
Performance یک Feature است
کاربر اهمیتی نمیدهد که سایت شما با چه frameworkی ساخته شده است.
برای او مهم است که صفحه سریع باز شود، تعاملات روان باشند و چیزی که میخواهد بدون انتظار طولانی در دسترسش قرار بگیرد.
به همین دلیل performance نباید چیزی باشد که در آخر پروژه به آن فکر کنیم.
از همان ابتدا باید بپرسیم:
چه JavaScriptای واقعاً لازم است؟
چه assetهایی باید load شوند؟
چه چیزهایی میتوانند lazy load شوند؟
آیا تمام dependencyهای پروژه واقعاً لازم هستند؟
آیا این صفحه اصلاً به JavaScript زیادی نیاز دارد؟
گاهی سریعترین راه برای سریعتر کردن یک سایت، نوشتن کد بهتر نیست.
نوشتن کد کمتر است.
از پیچیدگی نترس؛ از پیچیدگی بیدلیل بترس
من هنوز از React و Next.js استفاده میکنم.
اتفاقاً در بسیاری از پروژههایی که کار میکنم، استفاده از آنها کاملاً منطقی است.
تفاوت امروز من با چند سال قبل این است که دیگر صرفاً به این دلیل که یک تکنولوژی را بلدم، آن را انتخاب نمیکنم.
اول مسئله را بررسی میکنم.
بعد محدودیتها را میبینم.
بعد درباره تکنولوژی تصمیم میگیرم.
این تغییر شاید ساده به نظر برسد، اما برای من یکی از مهمترین تغییرات فکری در مسیر توسعه نرمافزار بوده است.
کمتر ساختن، همیشه به معنی کمتر حرفهای بودن نیست
یکی از سختترین چیزها در توسعه نرمافزار این است که جلوی خودمان را بگیریم.
اینکه بتوانیم بگوییم:
«این پروژه به این abstraction نیاز ندارد.»
«این dependency لازم نیست.»
«فعلاً state management نمیخواهیم.»
«این صفحه اصلاً نیازی به React ندارد.»
و مهمتر از همه:
«لازم نیست همهچیز را از اول پیچیده کنیم.»
توسعهدهنده خوب کسی نیست که برای هر مسئلهای یک تکنولوژی داشته باشد.
توسعهدهنده خوب کسی است که بتواند تشخیص دهد چه زمانی به تکنولوژی نیاز دارد و چه زمانی ندارد.
به نظرم یکی از نشانههای رشد یک Frontend Developer این است که به جای پرسیدن:
«با چه تکنولوژیای بسازمش؟»
اول بپرسد:
«سادهترین راه حل درست برای این مسئله چیست؟»