ahmad hasanzadeh branding logoahmad hasanzadeh branding logo
    خانهپروژه هامقالاتدرباره منتکنولوژی هاارتباط با من
ahmad hasanzadeh branding logoahmad hasanzadeh branding logo

ممنون که سر زدی ッ

© ۱۴۰۵

احمد حسن زاده. تمامی حقوق محفوظ است.

State Normalization در فرانت‌اند چیست؟ راهنمای کامل مدیریت داده‌های تودرتو

State Normalization در فرانت‌اند چیست؟ راهنمای کامل مدیریت داده‌های تودرتو

آموزش کامل مفهوم State Normalization در فرانت‌اند؛ چرا داده‌های تودرتو باعث افت کارایی و باگ می‌شوند و چگونه با نرمال‌سازی state، اپلیکیشن خود را مقیاس‌پذیرتر کنید.

در توسعه فرانت‌اند، خیلی زود به این نقطه می‌رسیم که داده‌هایی که از سرور می‌گیریم، ساختاری تودرتو (nested) دارند. یک پست وبلاگ چند کامنت دارد، هر کامنت یک نویسنده دارد، و همان نویسنده ممکن است در پست‌های دیگر هم حضور داشته باشد. وقتی این داده‌ها را همان‌طور که از API آمده‌اند مستقیم در state ذخیره می‌کنیم، خیلی زود با مشکلاتی مثل داده‌های تکراری، ری‌رندرهای غیرضروری و آپدیت‌های پیچیده مواجه می‌شویم.

ساختار تودرتو در مقابل ساختار نرمال‌شده داده‌ها

State Normalization دقیقاً همین مشکل را حل می‌کند: تبدیل داده‌های تودرتو به یک ساختار مسطح (flat) که شبیه جداول یک دیتابیس رفتار می‌کند.

نرمال‌سازی state یعنی چه؟

نرمال‌سازی مفهومی است که از طراحی دیتابیس‌های رابطه‌ای وام گرفته شده. در دیتابیس، به‌جای اینکه اطلاعات کاربر را داخل هر رکورد سفارش تکرار کنیم، یک جدول جداگانه برای کاربران می‌سازیم و در جدول سفارش‌ها فقط شناسه (ID) کاربر را نگه می‌داریم.

همین ایده در state فرانت‌اند هم قابل استفاده است. مستندات رسمی Redux این رویکرد را به‌عنوان روش پیشنهادی برای مدیریت داده‌های رابطه‌ای یا تودرتو معرفی کرده است؛ ایده اصلی این است که بخشی از store را طوری در نظر بگیریم که انگار یک دیتابیس است.

در عمل، نرمال‌سازی یعنی:

  • هر نوع داده (مثل پست، کاربر، کامنت) یک "جدول" مستقل در state دارد.
  • هر جدول، آیتم‌ها را به‌صورت یک آبجکت ذخیره می‌کند که کلیدهای آن، شناسه‌ی آیتم‌هاست.
  • برای اشاره به یک آیتم از جای دیگر state، فقط شناسه‌ی آن ذخیره می‌شود، نه کل آبجکت.
  • ترتیب آیتم‌ها (در صورت نیاز) در یک آرایه جداگانه از شناسه‌ها نگه‌داری می‌شود.

مثال: از حالت تودرتو به حالت نرمال‌شده

فرض کنید یک اپلیکیشن وبلاگ داریم که پاسخ API آن این‌طور است:

nested-response.jsonjson
{
  "posts": [
    {
      "id": "p1",
      "title": "شروع کار با React",
      "author": { "id": "u1", "name": "سارا احمدی" },
      "comments": [
        {
          "id": "c1",
          "text": "مقاله خوبی بود",
          "author": { "id": "u2", "name": "رضا کریمی" }
        }
      ]
    }
  ]
}

مشکل این ساختار این است که اگر کاربر «سارا احمدی» نامش را عوض کند، باید در تمام پست‌ها و کامنت‌هایی که او در آن‌ها حضور دارد، این تغییر را اعمال کنیم. همین‌طور اگر بخواهیم لیست پست‌ها را جدا از کامنت‌ها رندر کنیم، باید کل درخت را پیمایش کنیم.

نسخه نرمال‌شده همین داده به این شکل است:

normalized-state.jsonjson
{
  "posts": {
    "byId": {
      "p1": { "id": "p1", "title": "شروع کار با React", "author": "u1", "comments": ["c1"] }
    },
    "allIds": ["p1"]
  },
  "users": {
    "byId": {
      "u1": { "id": "u1", "name": "سارا احمدی" },
      "u2": { "id": "u2", "name": "رضا کریمی" }
    },
    "allIds": ["u1", "u2"]
  },
  "comments": {
    "byId": {
      "c1": { "id": "c1", "text": "مقاله خوبی بود", "author": "u2" }
    },
    "allIds": ["c1"]
  }
}

حالا هر نوع داده در جدول خودش قرار دارد و هیچ اطلاعاتی تکرار نشده. این الگو معمولاً به‌نام ساختار byId و allIds شناخته می‌شود؛ byId برای دسترسی سریع به هر آیتم با شناسه‌اش، و allIds برای حفظ ترتیب آیتم‌ها.

چرا نرمال‌سازی state اهمیت دارد؟

۱. جلوگیری از داده‌های تکراری و ناهماهنگ

وقتی یک آبجکت (مثلاً یک کاربر) در چند جای مختلف state کپی شده باشد، به‌محض تغییر یکی از آن‌ها، بقیه‌ی کپی‌ها قدیمی می‌مانند. نرمال‌سازی تضمین می‌کند هر موجودیت (entity) فقط یک "منبع حقیقت" (single source of truth) دارد.

۲. کارایی بهتر و ری‌رندر کمتر

در کتابخانه‌هایی مثل React که آپدیت‌های تغییرناپذیر (immutable) دارند، تغییر یک آیتم تودرتو معمولاً باعث می‌شود کل مسیر تا ریشه‌ی state کپی شود. این یعنی حتی کامپوننت‌هایی که داده‌شان تغییر نکرده هم ممکن است دوباره رندر شوند. با ساختار مسطح، فقط همان بخش کوچکی از state که واقعاً تغییر کرده به‌روزرسانی می‌شود.

۳. آپدیت‌ها ساده‌تر می‌شوند

آپدیت، حذف یا افزودن یک آیتم در یک آبجکت با کلید شناسه، بسیار ساده‌تر از پیدا کردن و ویرایش آن در دل چند سطح آرایه‌ی تودرتو است. کافی است با شناسه‌ی آیتم به آن دسترسی پیدا کنید.

۴. مقیاس‌پذیری در اپلیکیشن‌های بزرگ

هرچه اپلیکیشن بزرگ‌تر و روابط بین داده‌ها پیچیده‌تر شود، نگه‌داری ساختار تودرتو سخت‌تر می‌شود. state نرمال‌شده رفتار قابل‌پیش‌بینی‌تری دارد و تیم‌های بزرگ‌تر راحت‌تر می‌توانند روی آن کار کنند.

چه زمانی سراغ نرمال‌سازی برویم؟

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

  • داده‌هایی که در چند بخش مختلف UI به‌طور هم‌زمان استفاده می‌شوند (مثلاً یک کاربر هم در لیست پست‌ها و هم در پروفایل).
  • روابط چندبه‌چند یا یک‌به‌چند بین موجودیت‌ها (پست‌ها، کاربران، کامنت‌ها، تگ‌ها).
  • عملیات CRUD مکرر روی آیتم‌های مجزا (افزودن، ویرایش، حذف تکی).
  • لیست‌های بزرگ که باید مرتب‌سازی، فیلتر یا صفحه‌بندی شوند.

ابزارها و کتابخانه‌ها

برای پیاده‌سازی دستی، می‌توانید ساختار byId/allIds را خودتان بسازید. اما برای داده‌های واقعاً تودرتو، کتابخانه‌ی normalizr استاندارد صنعتی است. با این کتابخانه، یک schema برای موجودیت‌ها و روابطشان تعریف می‌کنید و تابع normalize() داده‌ی خام را به همان ساختار مسطح تبدیل می‌کند.

اگر از Redux Toolkit استفاده می‌کنید، ابزار createEntityAdapter دقیقاً برای همین منظور طراحی شده و بخش زیادی از این کار تکراری را خودکار می‌کند. در کتابخانه‌های دیگر مدیریت state مثل Zustand یا حتی در کش کوئری‌های TanStack Query هم می‌توانید همین اصول را به‌صورت دستی پیاده کنید، چون این یک الگوی معماری است، نه یک ویژگی مخصوص Redux.

جمع‌بندی

State Normalization یعنی رفتار کردن با بخشی از state اپلیکیشن مثل یک دیتابیس کوچک: هر نوع داده در جدول خودش، دسترسی از طریق شناسه، و بدون تکرار اطلاعات. این الگو مشکلات رایج داده‌های تودرتو -- ناهماهنگی، ری‌رندرهای غیرضروری و آپدیت‌های پیچیده -- را حل می‌کند و برای اپلیکیشن‌هایی با داده‌های رابطه‌ای، یک سرمایه‌گذاری کم‌هزینه با بازدهی بالا در بلندمدت است.

هوش مصنوعی

نویسنده:

هوش مصنوعی
دقیقه:8
انتشار :۱۴۰۵/۵/۱۱
آپدیت :۱۴۰۵/۵/۱۱

دسته بندی ها

فرانت‌اند

تگ ها

#State Management#Redux#React#Frontend Architecture#Performance