تطوير برمجيات مخصّصة
برمجيات مخصّصة بـ Laravel و PostgreSQL
ما يمنحه PostgreSQL لبناء Laravel ولا يمنحه MySQL - ترحيل يرتدّ عند فشله، وضمانات لا يستطيع Eloquent تجاوزها، وتقارير بلا قاعدة بيانات ثانية.
Laravel يعمل على الاثنتين، فاختيار PostgreSQL قرار لا إعداد افتراضي - ويستحق التحديد ما الذي يمنحه، لأن المقارنات المتاحة تتحدّث عن القياسات ولا تتحدّث تقريبًا عمّا يحدث فعلًا بعد ظهر الخميس أثناء نشر.
ترحيل Laravel الفاشل يرتدّ
هذا هو الفرق الذي يغيّر سلوك الفريق، وهو الذي يذكره أحد نادرًا.
يطبّق PostgreSQL تغييرات المخطّط معاملاتيًا. فترحيل بست عبارات يفشل في الرابعة يترك قاعدة البيانات كما كانت تمامًا. لا شيء نصفيّ، ولا شيء يُفَكّ، والترحيل يمكن تصحيحه وتشغيله مرة أخرى.
أما MySQL فلا. العبارات الثلاث الأولى مطبّقة، والترحيل مسجّل كأنه لم يعمل، وعلى أحد الآن أن يثبت يدويًا أي نصف منه موجود. في الإنتاج، تحت ضغط الوقت، والنشر نصفه قائم.
والنتيجة ثقافية لا تقنية. فحيث يكون الترحيل الفاشل قابلًا للاسترداد تُكتب الترحيلات كما ينبغي - صغيرة ومحدّدة ومراجَعة. وحيث يكون الترحيل الفاشل حادثة تُحزَم وتُؤجَّل وتُطبَّق في النهاية يدويًا. وهكذا تنزاح المخطّطات خارج التحكّم بالإصدارات، وهذه أكثر حالة نجدها في المشاريع الموروثة. والقراءة المتصلة الترحيل الذي أسقط الموقع.
قيود لا يستطيع Eloquent تجاوزها
القاعدة المفروضة في موديل تصمد للكود الذي يمرّ بالموديل.
ولا تصمد لتحديثة جماعية. ولا لنداء من query builder يكتب في الجدول مباشرة، وكل قاعدة كود فيها واحد في مكان ما. ولا لأمر الكونسول الذي كتبه أحدهم في التاسعة مساءً لإصلاح مشكلة بيانات، ولا للاستيراد الذي يعمل مرة كل ربع ولم يراجعه أحد.
ومفروضًا تحت التطبيق، يصمد لكل واحد منها. فالفهرس الفريد يحسم طلبين متزامنين على السجل نفسه، وهذا ما لا يحقّقه التحقّق المسبق أبدًا - فالتحقّق والإدراج عبارتان منفصلتان، والفجوة بينهما هي موضع ظهور المكرّر. والمفتاح الأجنبي يجعل الصف اليتيم مستحيلًا لا غير مرجّح. وقيد التحقّق يُبقي الكمية موجبة في الصف لا في النموذج الذي تحقّق أخيرًا.
ويضيف PostgreSQL اثنين يهمّان عمليًا. فقيد الاستبعاد يرفض حجزًا يتقاطع نطاق تاريخه مع حجز قائم للمورد نفسه، فيُغلق تنازعًا يصعب فعلًا إغلاقه في PHP. والفهرس الجزئي يغطّي الصفوف الجديرة بالتغطية وحدها، فلا يدفع استعلام على الأوامر المفتوحة كلفة خمس سنوات من المغلقة.
JSONB، وأين ينبغي أن يبدأ العمود
بعض البيانات لا مخطّط لها ليُصمَّم. حمولة من مزوّد يغيّرها بلا إشعار. إعدادات لكل عميل. نموذج يبنيه العميل بنفسه.
وPostgreSQL يعالج ذلك جيدًا لا على مضض - يُخزَّن JSONB مضغوطًا ويُستعلَم بمعاملات حقيقية ويُفهرَس بـ GIN ويُحوَّل بنظافة إلى خصيصة Eloquent. قرار تصميم معقول لا تراجع.
والانحدار تدريجي والقصة نفسها دائمًا. إضافة مفتاح إلى JSON لا تحتاج ترحيلًا ولا تجلب مراجعة، فهناك تبدأ الحقول بالذهاب. وفي السنة الثانية لا يستطيع أحد الإجابة عن سؤال حول البيانات دون قراءة PHP، وإخراج حقل إلى عمود يعني كتابة ترحيل يحلّل ثلاث سنوات من صفوف غير متّسقة الشكل.
والاختبار الذي يمنع ذلك: إن كنتم ستُصفّون أو ترتّبون أو تربطون أو تقرّرون به يومًا، فهو عمود. وكل ما عداه يمكن أن يسكن JSONB، وينبغي أن يسكنه.
تقارير بلا قاعدة بيانات ثانية
كثير جدًا من تطبيقات Laravel يجرّ آلاف الصفوف إلى PHP ويدور عليها لإنتاج رقم، لأن الاستعلام الذي يفعل ذلك في SQL بدا غير مألوف.
دوال النوافذ تجعل المجاميع الجارية والترتيبات ومقارنات الفترات استعلامًا واحدًا. وتعبيرات الجداول المشتركة تجعل حسابًا متعدّد الخطوات مقروءًا لا متداخلًا. والوصلات الجانبية تعالج شكل أفضل-ثلاثة-لكل-عميل الذي يصير حلقة N+1 بدونها. وكل واحدة منها تستبدل صفحة كود باستعلام تنفّذه قاعدة البيانات في مرور واحد.
وموجّهةً إلى نسخة قراءة، تبقى هذه التقارير خارج الحمل المعاملاتي تمامًا. أما المستودع المنفصل فجواب حقيقي عندما تتنازع التقارير فعلًا مع الإنتاج أو تمتدّ على عدة أنظمة - لكن ينبغي أن يتبع ذلك قياسًا لا أن يسبقه، وأكثر التطبيقات تبلغه متأخرة عمّا تتوقّع. وهندسة قواعد البيانات و Eloquent هي موضع هذا العمل.
ما يتغيّر فعلًا في Eloquent
صدقًا بشأن الاحتكاك، فهو موجود.
مقارنة النصوص تحسب حالة الأحرف، فـ where على بريد أو مرجع كان يعمل على MySQL
قد يتوقّف عن المطابقة. وLIKE يحسب الحالة وILIKE هو الشكل الذي لا يحسبها،
وذلك غير منقول بين القاعدتين - فالاستعلام المكتوب لإحداهما يحتاج انتباهًا في
الأخرى.
والمقارنات مُقيّدة النوع. تمرير نص حيث العمود عدد صحيح يرفع خطأً بدل التحويل الصامت، وهذا هو السلوك الأفضل وسيظهر في كود كان يعتمد على التحويل.
والمفاتيح المتزايدة تلقائيًا تستخدم تسلسلات، وهذا يهمّ عند زرع بيانات بمعرّفات صريحة وعند نسخ صفوف بين البيئات. وكل ما كُتب SQL خامًا صار الآن خاصًّا بقاعدة بيانات، وهذه حجّة لإبقاء الـ SQL الخام في أماكن قليلة مسمّاة بدل تفريقه على الموديلات.
لا شيء من هذا عقبة. وكلها أرخص معرفةً في الأسبوع الأول من اكتشافها في مجموعة اختبارات تنجح محليًا وتفشل على staging.
شكل العمل مع Laravel و PostgreSQL، وأين يقع المخطّط فيه
في المرحلة الأولى، بقصد، إلى جانب المسار الذي يُبنى حوله - لا في وثيقة تصميم تسبقه ولا في مراجعة تليه.
وأربعة قرارات تستحق التسمية لأنها، إن أُجّلت، تصير ترحيلات تمسّ كل جدول مرتبط. مجموعة القيود وما يُراد لكل واحد أن يجعله مستحيلًا. والحدّ بين العمود وJSONB. وكيف يتصرّف تغيير المخطّط على جدول سيحمل لاحقًا أربعين مليون صف، وهذا يحدّد إن كان الفهرس يُنشأ على التوازي أم بقفل لم يحسبه أحد. وهل تقرأ التقارير من نسخة قراءة، لأن إضافة ذلك لاحقًا تعني تدقيق كل استعلام في أي اتصال استخدمه.
وبقية العمل مُهيكلة كما في صفحة البرمجيات المخصّصة - مراحل، كل واحدة متّفق عليها كتابةً، وكل واحدة تنتهي بشيء منشور.
ما تحصلون عليه مع بناء بـ Laravel و PostgreSQL
إلى جانب التطبيق نفسه ومستودعه، الأشياء الخاصة بهذا الاختيار.
الترحيلات، وهي تاريخ قاعدة البيانات وسبب إمكان مراجعة تغيير المخطّط كأي كود آخر. وملاحظة عن نموذج البيانات تشرح الشكل بدل إعادة سرده. وجرد فهارس يقول لأي استعلام يوجد كل فهرس، حتى يعرف مطوّر قادم يحذف واحدًا ما الذي سيتباطأ. والقيود مشروحة بما تمنعه. واستعلامات التقارير مكتوبة ومُفسَّرة - فدالة نوافذ لا يفهمها أحد ستُستبدَل بحلقة في PHP أول مرة تحتاج تغييرًا.
متى يكون MySQL هو الجواب الأفضل
إن كانت استضافتكم أو فريق تشغيلكم أو سياسة عميلكم مبنية حول MySQL، فذلك قيد حقيقي لا نقص تقني. والفريق الذي يعرف كيف يستعيد قاعدة بيانات ويراقبها ويضبطها أثمن من مجموعة مزايا أفضل بقليل في قاعدة لم يشغّلها أحد.
وإن كان تطبيق قائم على MySQL وسليمًا، فترحيله من أجل المزايا أعلاه قلّما يستحق الاضطراب وحده. افعلوه إن وُجد سبب آخر لمسّ طبقة البيانات.
وإن كان التطبيق صغيرًا وغالبه قراءة والمخطّط مستقرًّا، فالفرق بين الاثنتين لن يكون ما يحدّد نجاح المشروع.
