التوقف عن استخدام التاريخ

خصيصا لطلاب Backend Developer في دورة PHP ، أعدوا ترجمة لمقال مثير للاهتمام حول الآثار الجانبية للأداة الشائعة.





العمل مع التواريخ والأوقات في PHP مزعج أحيانًا لأنه يؤدي إلى أخطاء غير متوقعة في الكود:

$startedAt = new DateTime('2019-06-30 10:00:00'); $finishedAt = $startedAt->add(new DateInterval('PT3M')); var_dump($startedAt->format('Ymd H:i:s')); //2019-06-30 10:03:00 var_dump($finishedAt->format('Ymd H:i:s')); //2019-06-30 10:03:00 

تعد كلتا $startdate و $finishdate في عجلة من $finishdate لمدة ثلاث دقائق ، لأن أساليب مثل add () أو sub() أو modify() تعدل أيضًا كائن DateTime الذي يتم استدعاؤه قبل إعادته. المثال أعلاه ، بالطبع ، يظهر السلوك غير المرغوب فيه.

يمكننا إصلاح هذا الخطأ عن طريق نسخ الكائن المشار إليه قبل التفاعل معه ، على سبيل المثال:

 $startedAt = new DateTime('2019-06-30 10:00:00'); $finishedAt = clone $startedAt; $finishedAt->add(new DateInterval('PT3M')); 

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

بدلاً من ذلك ، يمكن حل المشكلة عن طريق تحويل مثيل DateTime الأصلي إلى DateTimeImmutable :

 $startedAt = new DateTime('2019-06-30 10:00:00'); $finishedAt = DateTimeImmutable::createFromMutable($startedAt)->add(new DateInterval('PT3M')); 

لماذا لا تستخدم DateTimeImmutable من البداية؟

لا هوادة فيها استخدام DateTimeImmutable


بدلاً من تطبيق أساليب الأمان يدويًا لمنع حدوث تغييرات غير متوقعة عند تمرير كائنات التاريخ / الوقت ، استخدم DateTimeImmutable ، والذي يتضمن طرقًا ، مما يجعل الكود الخاص بك أكثر موثوقية.

 $startedAt = new DateTimeImmutable('2019-06-30 10:00:00'); $finishedAt = $startedAt->add(new DateInterval('PT3M')); var_dump($startedAt->format('Ymd H:i:s')); //2019-06-30 10:00:00 var_dump($finishedAt->format('Ymd H:i:s')); //2019-06-30 10:03:00 

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

أسلوب الترميز مفصل


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

 $this->expiresAt = $this->expiresAt->modify('+1 week'); 

يمكن أن تحذرنا أدوات التحليل الإحصائي ، مثل PHPStan وأحد امتداداتها ، إذا تجاهلنا المهمة ونستخدم DateTimeImmutable بشكل غير صحيح.

ومع ذلك ، يتم كبح هذا التحيز المعرفي تجاه التباين عندما نقوم بإجراء عمليات حسابية على قيم البدائية ، على سبيل المثال: $a + 3; . في حد ذاته ، يُنظر إلى هذا على أنه عبارة بلا معنى تفتقر بوضوح إلى إعادة التعيين: $a = $a + 3; أو $A += 3; . سيكون من الرائع استخدام شيء مثل هذا في حالة كائنات القيمة ، أليس كذلك؟

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

 $this->expiresAt += '1 week'; 

الحسابات لمرة واحدة


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

مكتبات التاريخ / الوقت


Carbon هي مكتبة شائعة للغاية تعمل على توسيع واجهة برمجة تطبيقات التاريخ / الوقت في PHP ، مضيفة مجموعة ميزات غنية. بتعبير أدق ، فإنه يمدد واجهة برمجة التطبيقات (API) للفئة القابلة للتاريخ من DateTime ، والتي يتعارض استخدامها مع موضوع هذه المقالة.

لذلك ، إذا كنت تستمتع بالعمل مع Carbon لكنك تفضل الثبات ، أقترح عليك أن تتعرف على Chronos . هذه مكتبة قائمة بذاتها ، تستند في الأصل إلى Carbon ، وتهتم بشكل خاص بتوفير كائنات التاريخ / الوقت الافتراضية غير القابلة للتغيير ، ولكنها تتضمن أيضًا خيارات قابلة للتغيير في حالة الحاجة.
تحرير (07/05/2019): اتضح أن الكربون لديه خيار تاريخ / وقت ثابت ، وهو زائد كبير. ومع ذلك ، فإن السبب الذي يجعلني أفضل Chronos هو أنه ، على عكس Carbon ، يشجع ويعزز ثبات التقصير ، سواء في التعليمات البرمجية أو في الوثائق ، وهذه عوامل حاسمة في سياق هذه المقالة.

الفكر الماضي


تم تقديم DateTimeImmutable لأول مرة في PHP 5.5 القديم ، ولكن لدهشتي ، اكتشف العديد من المطورين ذلك الآن. استخدم DateTimeImmutable افتراضيًا كلما كان ذلك ممكنًا ، ولكن ضع في اعتبارك بعض المفاضلات التي تحدثت عنها والتي أعتقد أنها أكثر من العادة وتحول في العقلية.

هذا كل شيء. بالتقليد ، نحن في انتظار تعليقاتكم ، الأصدقاء.

Source: https://habr.com/ru/post/ar464253/


All Articles