يبدو التعاون في الوقت الفعلي سهلاً للغاية حتى ترفع الستار عنه. شخص يكتب، وآخر يحذف سطراً في الفقرة الثالثة، وثالث يلصق مقتطفاً من Stack Overflow. وبطريقة ما، يستقر المستند في حالة واحدة متماسكة. إن بناء هذه السلاسة من الصفر، دون خبرة سابقة في WebSockets أو الحالة الموزعة (distributed state)، قد يبدو أمراً متهوراً، ولكنه يبدو أيضاً الطريقة الصحيحة للتعلم الفعلي.

يبدأ هذا المشروع من الصفر. لا توجد أكواد جاهزة (boilerplate) مستعارة، ولا شروحات يوتيوب مصقولة يتم فيها تخطي الأجزاء الصعبة في مونتاج مدته ثلاثون ثانية. الهدف هو بناء محرر أكواد تعاوني حيث يمكن لعدة مستخدمين تحرير الملف نفسه في وقت واحد، ورؤية تغييرات بعضهم البعض — ومؤشرات الماوس (cursors) الخاصة بهم — فور حدوثها. الوصول إلى ذلك سيتطلب فهم طبقات النقل (transport layers)، ونماذج الاتساق (consistency models)، والمشكلة الشائ

تتم معايرة التوقعات بصدق. ستمر فترات لا يعمل فيها أي شيء. قد تستخدم في المحاولة الأولى JSON patches بسيطة لتمثيل التغييرات النصية، لتكتشف فقط أن JSON لا يملك مفهوم "المؤشر 5 في فقرة"، مما يؤدي إلى قيام عمليتي إدراج متزامنتين في نفس المؤشر بالكتابة فوق بعضهما البعض بدلاً من الدمج. وقد تحاول في المحاولة الثانية بناء سجل تاريخ خطي مخصص، لتدرك أن إعادة تشغيل ذلك السجل ستكون كابوسًا من حيث تعقيد الوقت (Big O) عندما يكبر المستند. أما المحاولة الثالثة فقد تنجح في تشغيل WebSockets محليًا، ثم تنهار عند العمل عبر شبكة حقيقية حيث يعيد فقدان الحزم وتأخر الاستجابة المتغير كتابة القواعد.

هذا الاحتكاك هو الجوهر. إن نسخ مستودع (repository) جاهز سيتجاوز عملية البحث في سبب تفريغ الطابور بهذا الترتيب المحدد، أو سبب احتفاظ الخادم بمتجه إصدار (version vector). إن إعادة بناء المكون نفسه ثلاث مرات أمر بطيء، لكنه يفرض فهمًا للحد الفاصل بين ما يفعله الإطار البرمجي وما يجب أن يتعامل معه منطقك الخاص.

لن تكون وثائق هذه العملية شريطًا من اللحظات البراقة، بل ستتضمن المنعطفات الخاطئة. على سبيل المثال، يبدو بناء الوعي بالحضور (presence awareness) —أي معرفة من هو متصل وأين يقع مؤشر الماوس الخاص به— ميزة تجميلية حتى تدرك أنها تعتمد على نفس نموذج الاتساق (consistency model) الذي يعتمد عليه النص نفسه. إذا رأى المستخدم A مؤشر المستخدم B عند العمود 10، ثم قام المستخدم B بإدراج أربعة أحرف، فأين ينتقل ذلك المؤشر؟ بدون فهم مشترك لطوبولوجيا المستند، ستنحرف بيانات الحضور عن الواقع. يتطلب حل ذلك ربط موضع المؤشر بهوية بنية البيانات الأساسية، وليس مجرد مؤشرها الرقمي. هذه هي أنواع التفاصيل التي تتجاوزها الشروحات التعليمية لأنها مملة، وليس لأنها غير مهمة.

ما الذي سيأتي بعد ذلك

خارطة الطريق الفورية شحيحة عن قصد. ستكون المعالم الأولى هي:

  • خادم WebSocket خام يقوم بصدى أحداث الأحرف، لتشعر بزمن التأخير ودورة حياة الاتصال بشكل مباشر
  • مخزن مؤقت بسيط للسلاسل النصية (string buffer) على جانب العميل لفهم سبب فشل ترتيب الإدراج الساذج في ظل التزامن
  • CRDT يتم بناؤه من الصفر للتسلسلات المرتبة، مهما كان غير فعال، لرؤية الخاصية التبديلية (commutative property) قيد التنفيذ
  • تكامل تدريجي مع واجهة محرر أكواد فعلي، مثل CodeMirror أو Monaco على الأرجح، للتعامل مع عدم التطابق بين واجهة برمجة التطبيقات الأمرية (imperative API) للمحرر والطبيعة الوظيفية لسجل العمليات

ستأتي كل خطوة مع مبرر مكتوب. لماذا هذا النهج وليس ذاك؟ ما هي الافتراضات التي ثبت خطؤها؟ ما هو التجريد الذي تسرب (abstraction leaked)؟

خلاصة حقيقية

إن البدء في مشروع كهذا دون خبرة في WebSockets أو CRDTs أمر مخيف، لكن الخبرة غالبًا ما تكون مجرد ارتباك متكرر بأسماء أفضل. الهدف ليس النهاية السريعة، بل بناء نظام يمكن التنبؤ بسلوكه لأن كل طبقة بُنيت بقصد بدلاً من استيرادها بالأمل.

إذا كنت قد بنيت برمجيات تعاونية من قبل —سواء كان محرر نصوص، أو أداة تصميم، أو محرك مزامنة حالة لعبة— شاركنا أنماط الفشل التي باغتتك. وإذا كنت تتعلم هذه الأنظمة أيضًا، فتابع معنا. سيصل الكود ببطء، وسيتم إعادة كتابته كثيرًا. اليوم صفر يبدأ الآن.