سجل التطوير: فواصل المشغلات (Driver Seams)، أخطاء الروابط (URL Bugs)، وإعدادات قاعدة البيانات (DB Settings)
قضيت اليوم في بناء منصة. برزت فكرة معمارية واحدة باستمرار: يجب أن تضع فاصلاً (seam) بين ما تفعله وبين المكان الذي تخزن فيه البيانات.
يتيح لك هذا استبدال الواجهة الخلفية (backend) لاحقاً دون الحاجة لتغيير الكود الأساسي.
نمط الفواصل (The Pattern of Seams)
أنا أقوم ببناء منصة مراقبة (observability platform). تقوم المنصة بجمع الأخطاء والمقاييس من مصادر متعددة. اتبعت كل مهمة تخزين نفس النمط:
• إنشاء واجهة برمجية صغيرة (interface) - (العقد). • إنشاء مشغل Eloquent (driver) - (التنفيذ).
تتواصل لوحات التحكم (Dashboards) ومسارات البيانات (pipelines) مع الواجهة فقط. أستخدم Postgres حالياً لأنها موثوقة. إذا احتجت إلى قاعدة بيانات أسرع لاحقاً، سأقوم ببساطة بكتابة مشغل (driver) جديد، ولن أحتاج لتغيير كود لوحة التحكم.
الدرس بسيط: لست بحاجة إلى مشغل ثانٍ في اليوم الأول، بل أنت بحاجة إلى الواجهة (interface) في اليوم الأول. ملف إضافي واحد الآن يمنع إعادة كتابة ضخمة للكود لاحقاً.
ثلاث عادات جيدة
• استخدم معرفات مزدوجة. استخدم معرفات auto-increment لعمليات الربط (joins) الداخلية السريعة، واستخدم UUIDs لأي شيء يخرج من نظامك، مثل الروابط (URLs) أو واجهات البرمجة (APIs). هذا يحافظ على خصوصية عدد الصفوف لديك.
• استخدم الـ Enums. قم بتخزين الأدوار والحالات في PHP enums. يضمن ذلك أن تستخدم واجهة المستخدم (UI) والمنطق البرمجي (logic) نفس المصدر الموثوق للحقيقة (source of truth).
• قم بإصدار بياناتك (Version your data). قم دائماً بتضمين حقل إصدار (version field) في حمولات البيانات (payloads). أضف حقولاً اختيارية جديدة، ولكن لا تقم أبداً بإعادة تسمية الحقول القديمة أو حذفها؛ فهذا يمنع تعطل العملاء (clients) القدامى.
خطأ رابط التتبع (The Tracking URL Bug)
وجدت خطأً (bug) في حزمة لتتبع البريد الإلكتروني. تقوم هذه الحزمة بإعادة كتابة الروابط لتتبع النقرات؛ حيث تقوم بتشفير الرابط (URL) ثم استعادته أثناء عملية إعادة التوجيه (redirect).
المشكلة: يقوم Laravel بعمل HTML-escape للروابط في قوالب البريد الإلكتروني. يستخدم الرابط الموقع (signed URL) رموز "&". وفي لغة HTML، تتحول هذه الرموز إلى &.
إذا قمت بتشفير السلسلة النصية التي تم عمل escape لها، فستبقى & داخل الرابط. وعندما يحاول Laravel التحقق من التوقيع (signature)، سيفشل لأن السلسلة النصية قد تغيرت. يحدث هذا فقط مع الروابط الموقعة (signed URLs)، مما يجعل اكتشافه صعباً.
الحل: قم بفك تشفير الكيانات النصية (HTML entities) قبل التقاط الرابط.
استخدام قاعدة البيانات للإعدادات (Config)
قمت ببناء طريقة للمسؤولين (admins) لتغيير إعدادات التطبيق من خلال لوحة تحكم. تعيش هذه الإعدادات في قاعدة البيانات، ولكن التطبيق لا يزال يقرأها باستخدام دالة config() القياسية.
أستخدم طبقة تغطية رقيقة (thin overlay) في AppServiceProvider. تقوم هذه الطبقة بقراءة إعدادات قاعدة البيانات وتمريرها إلى الـ config للطلب الحالي (current request). هذا يحافظ على بقاء بقية الكود بسيطاً ومعيارياً.
الموضوع المشترك هنا هو الحدود (boundaries). حدد أين يوضع الفاصل (seam). ضع الحد في المكان الصحيح مرة واحدة، وسيبقى كل شيء آخر بسيطاً.
