الابتعاد عن السحر - أو: لماذا لا أرغب في استخدام Laravel بعد الآن

حان الوقت لتغيير الأدوات التي أستخدمها. وسأخبرك لماذا!

بادئ ذي بدء ، أريد أن أتأكد من أنك تعرف نواياي. أنا لا أحاول التشدق حول Laravel أو لماذا قد تكون الأطر الأخرى أفضل.

هذه المقالة ذاتية للغاية. سأعطيك أفكاري وسأحاول إقناعك بإعادة التفكير في خيارات إطار العمل أيضًا. وعندما تتمسك باستخدام Laravel بعد إعادة التقييم ، فلا بأس بذلك. ليس لدي أي نية لتحويل الأشخاص بعيدًا عن Laravel إلى أطر أو لغات أخرى. ولكن من المهم أن تنظر عن كثب وتتأكد من أنك تعرف ما تستخدمه ولماذا تستخدمه.

مقدمة

لقد عملت مع Laravel لمدة عامين تقريبًا. لطالما استمتعت بمدى سهولة إنشاء تطبيق والبدء في العمل خلال دقائق. إنه يوفر العديد من الأدوات المفيدة خارج الصندوق. تدعمك أوامر وحدة التحكم في كل جانب أثناء الترميز. إنهم ينشئون فصولًا وسقالات للمصادقة وغير ذلك الكثير.

لكن كلما تعمقت وأصبحت المشاريع أكبر ، زاد تعقيد تطوير Laravel. أو دعني أعيد صياغته: كلما كانت الأدوات الأخرى الأفضل هي التي ستؤدي المهمة. أنا لا أقول إنه خطأ Laravel فقط. يرجع ذلك جزئيًا أيضًا إلى عدم تصميم PHP جيدًا.

الآن ، لنبدأ!

بليغ ORM

إذا كنت قد عملت بالفعل مع Laravel ، فأنت تعرف بالتأكيد Eloquent. إنها ORM التي يتم شحنها مع التثبيت الافتراضي. يأتي مع الكثير من الميزات الأنيقة. لكن تصميمه يجعل تطبيقك معقدًا بلا داع ويمنع IDE من تحليل الكود الخاص بك بشكل صحيح.

يرجع هذا جزئيًا إلى نمط Active Record ORM الذي يتم استخدامه ، ويرجع ذلك جزئيًا إلى حقيقة أن Eloquent يريد إنقاذ المطور من الاضطرار إلى كتابة المزيد من التعليمات البرمجية. للقيام بذلك ، فإنه يسمح للمطور بإدخال الكثير في النموذج الذي لا ينتمي إليه.

يبدو أن النوايا الحسنة ، لكنني بدأت أكره هذا أكثر وأكثر.

دعنا نلقي نظرة على مثال:

أول شيء تراه هو أنه لا توجد خصائص في النموذج. هذا يبدو غير ذي صلة ولكن بالنسبة لي ، فإنه يحدث فرقًا كبيرًا. يتم حقن كل شيء "بطريقة سحرية" في الفصل عن طريق قراءة البيانات الوصفية للجدول. بالطبع ، IDE الخاص بك لا يفهم ذلك بدون مساعدة. ولن تحصل على فرصة لتسمية عقاراتك بشكل مختلف عن أعمدتك.

تحقق الآن من طريقة النطاق. بالنسبة لمستخدمي Laravel ، من الواضح تمامًا ما يفعله. إذا قمت باستدعاء هذه الطريقة ، فإنها تحدد نطاق استعلام SQL الأساسي عن طريق إضافة جملة WHERE المحددة.

يمكنك أن ترى أنها ليست ثابتة. هذا يعني أن هذه الطريقة تعمل على كائن معين من الفصل. لكن في هذه الحالة ، لا يحدث ذلك . يتم استدعاء النطاق في منشئ الاستعلام. كان لديه شيء للقيام مع الكائن النموذج نفسه. سأشرح ذلك بعد أن ترى كيف تسمي هذه النطاقات عادةً:

أنت تستدعي طريقة ثابتة popular()لم يحددها أحد من قبل. ولكن منذ لارافل يعرف __call()و __callStatic()سيلة، ويحصل على التعامل معها من خلالها. تقوم هذه الطرق بإعادة توجيه المكالمة إلى منشئ الاستعلام.

هذا ليس شيئًا لا يفهمه IDE الخاص بك. إنه يجعل إعادة البناء أكثر صعوبة ، وقد يربك المطورين الجدد ، كما أن التحليل الثابت يصبح أكثر صعوبة أيضًا.

بالإضافة إلى ذلك ، عند وضع مثل هذه الأساليب على النموذج الخاص بك ، فإنك تنتهك S of SOLID. في حال لم تكن معتادًا على ذلك ، فإن SOLID هو اختصار يرمز إلى:

  • S المسؤولية إنجل المبدأ
  • يا قلم / مبدأ مغلق
  • مبدأ الإحالة L iskov
  • أنا nterface Segregation Principle
  • د مبدأ انعكاس التبعية

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

Global Helpers

يأتي Laravel مع عدد غير قليل من الوظائف المساعدة الشاملة. يبدو أنها مفيدة جدا ونعم، وأنها هي في متناول يدي.

عليك فقط أن تعرف أنك تضحي باستقلالك من أجل سهولة الاستخدام وأن مساحة الاسم العالمية الخاصة بك تتلوث. نادرا ما يؤدي إلى صراعات ، ولكن تجنب ذلك تماما هو الأفضل.

لنلق نظرة على بعض الأمثلة. فيما يلي قائمة بثلاث طرق مساعدة لدينا ولكننا لسنا بحاجة إليها نظرًا لوجود بدائل أفضل:

  • app_path()- لماذا ا؟ إذا كنت بحاجة إلى مسار التطبيق ، فاسأل كائن التطبيق. تحصل عليه عن طريق تلميح الكتابة.
  • app()- هاه؟ لسنا بحاجة إلى هذه الطريقة. يمكننا حقن نسخة التطبيق!
  • collect()- يؤدي هذا إلى إنشاء مثيل جديد لفئة المجموعة. يمكننا فقط إنشاء شيء جديد بأنفسنا.

مثال آخر ملموس:

نحن نستخدم المساعد العام في Laravel request()لاسترداد بيانات POST ووضعها في نموذجنا كسمات .

بدلاً من استخدام المساعد العام ، يمكننا كتابة تلميح Requestكائن كمعامل في طريقة وحدة التحكم. يعرف المرسل في Laravel كيفية تزويدنا بالكائن المطلوب. سوف تستدعي طريقتنا بها ولا يتعين علينا استدعاء المساعد.

ويمكننا اتخاذ هذه الخطوة إلى الأمام لفصل المزيد. Laravel متوافق مع PSR-7. لذلك ، بدلاً من كتابة تلميح إلى كائن الطلب ، يمكنك أيضًا كتابة تلميح ServerRequestInterface. يسمح لك ذلك باستبدال الإطار بأكمله بأي شيء متوافق مع PSR-7. كل شيء في هذه الطريقة سيستمر في العمل. قد يفشل هذا إذا كنت لا تزال تستخدم الطرق المساعدة. لن يأتي إطار العمل الجديد مع الطريقة المساعدة ، وبالتالي ، سيتعين عليك إعادة كتابة هذا الجزء من التعليمات البرمجية الخاصة بك.

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

كنت سعيدًا عندما قرأت أنه باستخدام Laravel 5.8 ، يتم إزالة مساعدي السلسلة والمصفوفة من النواة ووضعها في حزمة منفصلة. وهذه خطوة أولى جيدة. لكن يجب أن تبدأ الوثائق في تثبيط استخدام جميع الوظائف المساعدة.

واجهات

تظهر هنا أيضًا الحجج من الجزء الأخير. يبدو أن الواجهات أداة جيدة للوصول بسرعة إلى بعض الأساليب غير الثابتة حقًا. لكنهم يربطونك بالإطار مرة أخرى. يمكنك استخدامها لحل التبعيات يدويًا بدلاً من توجيه البيئة لتوفيرها.

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

نظرًا لأننا كنا نتحدث عن دعم IDE ، أعلم أن بعضكم قد يوجهني إلى حزمة IDE helper من barryvdh. لا داعي لذلك. أنا أعرف بالفعل هذه الحزمة. ولكن لماذا هو مطلوب حتى؟ لأن بعض قرارات التصميم في Laravel ليست جيدة. هناك أطر لا تحتاج إليها. خذ Symfony على سبيل المثال. لا حاجة لملفات IDE المساعد ، لأنها مصممة ومنفذة بشكل جيد.

بدلاً من الواجهات ، يمكننا استخدام حقن التبعية مرة أخرى كما فعلنا في المثال السابق. سيكون لدينا كائن حقيقي ويمكننا استدعاء أساليب حقيقية عليه. أفضل بكثير.

سأقدم لك مرة أخرى مثالاً:

يمكننا بسهولة تنظيف هذا. دعنا نخبر Laravel أن يضخ a ويمرر ResponseFactoryالطلب الحالي:

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

سمعت أن بعض الأشخاص يقدمون "عددًا كبيرًا جدًا من معاملات المُنشئ" كحجة ضد حقن كل شيء. لكني لا أتفق مع ذلك. إنه يخفي فقط التبعيات وبالتالي التعقيد في المقام الأول. إذا كنت لا تحب وجود 10 إلى 20 وسيطة في المُنشئ ، فأنت على حق.

لكن الحل ليس السحر. إن الحاجة إلى العديد من التبعيات في فئة واحدة تعني أن هذه الفئة على الأرجح لديها الكثير من المسؤوليات. بدلاً من إخفاء هذا التعقيد ، أعد تشكيل تلك الفئة. قم بتقسيمها إلى أخرى جديدة وتحسين بنية التطبيق الخاص بك.

حقيقة ممتعة: هناك نمط تصميم حقيقي يسمى "نمط الواجهة" ، تم تقديمه في كتاب Gang of Four. لكن لها معنى مختلف تمامًا. تعد واجهات Laravel أساسًا محددات مواقع خدمة ثابتة . التسمية فقط لا تنقل ذلك. كما أن التسمية نفسها لأشياء مختلفة تجعل المناقشات حول الهندسة المعمارية في المشاريع أكثر صعوبة ، لأن الطرف الآخر قد يتوقع شيئًا مختلفًا تمامًا وراء هذا الاسم.

استنتاج

دعونا ننتهي. قد أكتب متابعة قريبًا حول التقنيات التي أفضل استخدامها في الوقت الحاضر. لكن في الوقت الحالي ، دعني ألخص ما تعلمناه:

نهج Laravel في جعل كل شيء أسهل ما يمكن هو نهج جيد. لكن من الصعب التوافق عندما تصبح تطبيقاتك أكثر تقدمًا. أفضل دعم IDE الرائع ، وكتابة أقوى ، وكائنات حقيقية ، وهندسة جيدة. قد أعود إلى Laravel عندما أرغب في كتابة تطبيق أصغر.

الكثير من نقاطي ليست فقط خطأ Laravel. يمكنني تبديل الأجزاء التي لا أحبها ، على سبيل المثال ORM. ولكن بدلاً من ذلك ، سأقوم فقط بتبديل مجموعة الأدوات ، حيث تناسب الإعدادات الافتراضية احتياجاتي بشكل أفضل. لا أرى أي فائدة من استخدام إطار عمل حيث يتعين علي قضاء المزيد من الوقت في تجنب الفخاخ التي تحددها للهندسة السيئة أكثر من تطوير تطبيقي. تأتي الأطر والأدوات الأخرى مع افتراضيات مصممة بشكل أفضل وسحر أقل.

حتى الآن ، سأقول وداعا لارافيل.

شكرا لك على وقتك. أقدر مناقشة لطيفة في التعليقات وأنا بالطبع منفتح على أسئلتكم واقتراحاتكم.

ملاحظة: شكر خاص لماركو بيفيتا لإثبات القراءة والإدخال الإضافي!

تحرير 1 آذار (مارس) 2019:

منذ أن تم نشر مقالتي على Reddit ، قمت بإنشاء حساب Reddit للإجابة على بعض التعليقات. حسابي ليس الحساب الذي تم نشر المقال منه ، ولكن هذا الحساب: //reddit.com/u/nschoellhorn

تعديل 13 آذار (مارس) 2019:

إذا قرأت هذا الآن ، يمكنك أيضًا التحقق من ملفي الشخصي على Twitter. شكرا لك على اهتمامك المستمر بهذا الموضوع! أنا منفتح دائمًا على المناقشات المثمرة ، لذا لا تتردد في الاتصال ، إما هنا أو على Twitter.