سادگی (Simplicity)
سادگی یکی از بنیادیترین اصول فلسفهی توسعه در این پروژه است. هدف از این اصل، کاهش پیچیدگیهای غیرضروری و ایجاد راهحلهایی است که قابلدرک، قابلنگهداری و پایدار باشند.
سادگی به معنای «ابتدایی بودن» نیست؛ بلکه به معنای انتخاب مؤثرترین و کمهزینهترین راهحل ممکن است که نیاز واقعی را برطرف کند، بدون افزودن ساختار یا abstractionهای غیرضروری.
چرا سادگی اهمیت دارد؟
سادگی در توسعه نرمافزار مزایای مهمی به همراه دارد:
- کاهش هزینههای نگهداری
- افزایش خوانایی و درک سریع کد
- کاهش احتمال خطاهای غیرمنتظره
- افزایش تستپذیری
- ایجاد ساختار پایدار و توسعهپذیر
- جلوگیری از انباشت پیچیدگی (Complexity Debt)
سیستمی که ساده طراحی شود، بهتر مقیاس میگیرد و کمتر نیازمند بازنویسی خواهد بود.
اصول کلیدی برای رسیدن به سادگی
در ادامه، مجموعهای از اصول عملی ارائه شده است که رعایت آنها به سادگی واقعی در کد و معماری کمک میکند.
از انتزاعهای زودهنگام پرهیز کنید
export const BaseInteractiveElement = ({ as: Component, ...props }) => {
return <Component {...props} />
}
export const Button = (props) => {
return <BaseInteractiveElement as='button' {...props} />
}
این الگو باعث پیچیدگی و کاهش خوانایی میشود.
export const Button = (props) => {
return <button className='primary' {...props} />
}
یک تابع تنها یک مسئولیت داشته باشد
توابع چندمنظوره خوانایی و تستپذیری را کاهش میدهند.
const submitForm = (form) => {
const validateForm = (form) => {}
const buildPayload = (form) => {}
const isValid = validateForm(form)
if (!isValid) {
toast.error('Invalid data')
return
}
const payload = buildPayload(form)
return api.post('/submit', payload)
}
const validateForm = (form) => {}
const buildPayload = (form) => {}
const sendSubmitRequest = (payload) => {}
const submitForm = (form) => {
if (!validateForm(form)) return
return sendSubmitRequest(buildPayload(form))
}
کد هوشمندانه لزوماً ساده نیست
Object.fromEntries(items.map((i) => [i.id, i]))
const map = {}
for (const item of items) {
map[item.id] = item
}
از تو در تویی زیاد اجتناب کنید
if (user && user.profile && user.profile.age > 18) {
/* Logic Block */
}
if (!user?.profile) return
if (user.profile.age <= 18) return
/* Logic Block */
رفتار تابع باید قابلپیشبینی باشد
توابعی که داده ورودی را تغییر میدهند یا اثرات ضمنی ایجاد میکنند، ساده نیستند.
const addItem = (item, list) => {
list.push(item)
return list
}
const addItem = (item, list) => {
return [...list, item]
}
معماری باید حداقلی و در حد نیاز باشد
سادگی در معماری یعنی:
- اضافه نکردن لایههای زائد
- انتخاب ابزار مناسب
- جلوگیری از over-engineering
نمونهٔ واقعی از ابزار نامناسب:
- استفاده از Redux برای دو مقدار ساده
- استفاده از React Query برای یک fetch ساده
- استفاده از Zustand برای حالتی که useState کفایت میکند
چکلیست سادگی
پیش از نهاییکردن هر PR این موارد را بررسی کنید:
- آیا این سادهترین راهحل مؤثر است؟
- آیا abstraction واقعاً لازم است؟
- آیا میتوان تابع را کوچکتر و شفافتر کرد؟
- آیا رفتار تابع کاملاً قابلپیشبینی است؟
- آیا نامگذاری واضح و دقیق است؟
- آیا یک توسعهدهنده جدید بدون توضیح کد را درک میکند؟
اگر حتی به یکی از سؤالات پاسخ «نه» باشد، کد هنوز ساده نیست.
جمعبندی
سادگی یک اصل بنیادین و یک ارزش بلندمدت است.
سادگی باعث:
- افزایش کیفیت
- کاهش هزینه
- افزایش سرعت توسعه
- ایجاد معماری پایدار میشود.
تمام اجزای سیستم باید تا حد امکان ساده، شفاف و قابلدرک باشند.