نرمافزار Local-first برگشته است و موتورهای همگامسازی کار سنگین را انجام میدهند

بیشتر نرمافزارهایی که امروز استفاده میکنیم هنوز سرور را تنها نسخه واقعی دادههایمان میدانند. گوشی و لپتاپ ما فقط پنجرههای نازکی به پایگاه دادهای در جای دیگر هستند و وقتی اتصال قطع میشود، این پنجرهها خالی میشوند. جنبش Local-first میگوید این رویکرد وارونه است. دستگاه باید نسخه کاری را نگه دارد، شبکه باید وسیله همگامسازی باشد و اپ باید وقتی شبکه نیست هم کار کند.
این ایده تازه نیست، اما حالا عملی شده است. آنچه تغییر کرده تغییر فلسفی در میان توسعهدهندگان نیست. موتورهای همگامسازی و نوع دادههای تکرارشونده بدون تعارض (CRDT) به اندازه کافی بالغ شدهاند تا سختترین بخش کار را انجام دهند: ادغام دو ویرایش انجامشده روی دو دستگاه بدون از دست رفتن هیچکدام. اگر امروز نرمافزار مشارکتی میسازید، همگامسازی دیگر یک جزئیات زیرساختی نیست که به تیم بکاند بسپارید. این یک تصمیم محصول است که روی مدل داده، دسترسیها و هزینه پشتیبانی شما اثر میگذارد.
بیانیه ۲۰۱۹ و چرایی طول کشیدن هفت سال
در سال ۲۰۱۹ گروه پژوهشی Ink & Switch مقالهای با عنوان «نرمافزار Local-first: دادههایتان را، با وجود ابر، مال خودتان کنید» منتشر کرد. این مقاله هفت ایدهآل را فهرست کرد: پاسخ سریع بدون چرخش لودر، کار کردن حتی با قطع شبکه، همکاری میان دستگاهها و افراد، دادهای که از عمر شرکت سازنده فراتر میرود، امنیت و حریم خصوصی بهصورت پیشفرض، و کاربرانی که فایلهای خودشان را کنترل میکنند. تقریباً کسی با این فهرست مخالف نبود. مشکل هزینه پیادهسازی بود.
ساختن یک اپ Local-first تا همین اواخر یعنی نوشتن منطق ادغام، لایه ذخیرهسازی و پروتکل تکثیر داده از صفر. بیشتر تیمها مسیر صرفاً ابری را انتخاب کردند چون سادهتر بود و کاربران لودر را تحمل میکردند. این محاسبه تغییر کرده، چون کتابخانههایی مثل Automerge و Yjs CRDTها را در JavaScript قابل استفاده کردهاند و موتورهای همگامسازی بخش لولهکشی اطراف آنها را برداشتهاند.
موتور همگامسازی دقیقاً چه میکند
CRDT ساختار دادهای است که طوری طراحی شده که نسخههای مختلف داده را با هر ترتیبی بتوان ادغام کرد و باز هم به نتیجه یکسان رسید، بدون داور مرکزی. متن، فهرستها و نگاشتها همگی با این روش قابل مدلسازیاند. موتور همگامسازی روی آن قرار میگیرد و کارهای پرزرقوبرق نیست اما حیاتی را انجام میدهد: جابهجایی تغییرات میان کلاینت و سرور، تکثیر فقط زیرمجموعه دادهای که هر کاربر اجازه دیدنش را دارد، ماندگاری وضعیت پس از راهاندازی مجدد، و تطبیق با پایگاه داده معتبر.
چند محصول در عمل روی این الگو اجرا میشوند. Linear درباره ذخیرهسازی سمت کلاینت خود بهصورت عمومی نوشته است که به ردیاب موضوعاتش اجازه میدهد فوری پاسخ دهد در حالی که تغییرات در پسزمینه همگام میشوند. ویرایش همزمان در Figma نمونه شناختهشده دیگری از ویرایش همزمان یک سند توسط کلاینتهای متعدد است. درس این محصولات این است که نسخه محلی همان چیزی است که کاربر با آن کار میکند و سرور به هماهنگکننده تبدیل میشود، نه گلوگاه.
جایی که این مدل میشکند
CRDTها برای ادغام ویرایش متن و مجموعهای از آیتمها عالیاند. اما وقتی قوانین کسبوکار شما به محدودیتهای سراسری وابسته است، کمک چندانی نمیکنند. اگر دو نفر آخرین صندلی یک پرواز را در حالت آفلاین رزرو کنند، تابع ادغام بدون اطلاعاتی که فقط سرور دارد نمیتواند تصمیم بگیرد چه کسی آن را میگیرد. همین موضوع برای پرداختها، موجودی انبار که نباید منفی شود، و هر چیزی که به پول یا تعهد حقوقی مربوط است صدق میکند.
مهاجرت اسکیمای داده مشکل دوم است که تیمها کمتر جدی میگیرند. وقتی کلاینتی که سه ماه از نسخه روز عقب است دوباره وصل میشود، باید دادهای را بفهمد که نسخه جدیدتر نوشته، و نسخه جدیدتر هم باید داده نسخه قدیمی را تحمل کند. این به گیتهای نسخه در کلاینت، حذف دقیق فیلدها و برنامهای برای کلاینتهایی که هرگز بهروز نمیشوند نیاز دارد. ذخیرهسازی سومین مشکل است. گوشی فضا و باتری محدود دارد، پس به سیاست حذف داده، تکثیر جزئی و پاسخ روشن برای زمانی که پایگاه داده محلی از ظرفیت دستگاه بزرگتر شود نیاز دارید.
یک چارچوب تصمیم ساده
پیش از انتخاب معماری Local-first، برای هر نوع داده محصول خود سه پرسش بپرسید. اول، آیا این داده باید آفلاین کار کند یا در کمتر از حدود ۱۰۰ میلیثانیه پاسخ دهد؟ دوم، آیا چند نفر بهطور همزمان روی یک شیء ویرایش میکنند؟ سوم، اگر دسترسی به ارائهدهنده را از دست بدهید، آیا داده برای کاربر بیاستفاده میشود؟
اگر پاسخ هر سه بله است، برای یادداشتها، مدیریت وظایف و ابزارهای طراحی دلیل قوی برای Local-first دارید. اگر دو پاسخ اول خیر است، مدل معمول با سرور معمولاً ارزانتر و قابل فهمتر است. بیشتر محصولات در نهایت ترکیبی هستند. پیشنویسها و محتوای مشارکتی بهصورت محلی همگام میشوند، در حالی که پرداختها، نقشها و صورتحسابها تحت کنترل سرور میمانند.
نکات عملی
- هر موجودیت در مدل داده را پیش از نوشتن کد بهصورت ادغامشونده با CRDT، معتبر در سرور یا فقطخواندنی طبقهبندی و مستند کنید.
- از روز اول اسکیمای داده را نسخهبندی کنید و بررسی نسخه کلاینت اضافه کنید تا کلاینتهای قدیمی با خطای قابلمدیریت متوقف شوند، نه اینکه داده را خراب کنند.
- روی دستگاههای اندروید ارزان با فضای محدود تست کنید، نه فقط آخرین آیفون.
- یک آزمایش یکهفتهای آفلاین داخلی اجرا کنید. کارهای عادی را در حالت پرواز انجام دهید و هر جایی که اپ شما را مسدود میکند یادداشت کنید. اینها نیازمندیهای واقعی شما هستند.
Local-first جایگزین ابر نیست. بازتوزیع کار است: دستگاه بخش بیشتری از کاری را انجام میدهد که کاربر به آن اهمیت میدهد و سرور هماهنگی را انجام میدهد که در آن خوب است. تیمهایی که این را درست انجام دهند اپهایی میسازند که سریعتر حس میشوند و شبکههای بد را تحمل میکنند.