ظهور مدونة 2019 وكيف تعلمت أن أحب الألفة

كتقليد سنوي لي ، طعنت في تحدي برمجة Advent of Code طوال شهر ديسمبر. لقد كانت دائمًا فرصة بالنسبة لي إما لاختبار نفسي لوضع ما تعلمته خلال العام على المحك.

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

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

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

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

كانت شفريتي بسيطة بما يكفي ، كما علمت عن Get-Content ، وكيفية القيام بوظيفة ، وكيفية تمثيل القيمة على الشاشة على الأقل ، على الرغم من أنني لم أفهم تمامًا كيف أن مجرد ذكر $ TotalMass في النهاية أثر بالفعل على الإجمالي حالة البرنامج. كل ما كنت أعرفه هو أنني كنت أغمس أصابع قدمي على الأقل في PowerShell ، وكنت على استعداد لمواصلة تعلم أشياء جديدة.

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

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

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

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

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

بدون التخمين الثاني ، قررت فقط كتابة حل في C # ، والذي كان لغتي لغتي منذ فترة طويلة. لقد جاءني الحل بشكل طبيعي ، لأنه كان بالضبط ما فكرت به من قبل. في الواقع ، تم حل الحل الخاص بي للجزء الأول بالكامل تقريبًا باستخدام وظيفة LINQ البسيطة ؛ احصل على جميع الإحداثيات التي يغطيها كلا المسارين ، وتقاطعها ، وابحث عن القيمة الدنيا. لأعلى من ذلك ، قمت بترحيل أيام العمل السابقة (التي كانت بسيطة للغاية بغض النظر) ، وأعدت تنفيذ الاختبار باستخدام Xunit.

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

وبالتأكيد شعرت أن التحرك نحو C # كان خطوة رائعة لمجرد نطاق التحديات اللاحقة. استمر مترجم الشفرة هذا في التطور كل يوم ، وستعطي العديد من التحديات برنامجًا عليك العمل عليه من أجل إيجاد حل. كانت التحديات التي تتطلب منك تشغيل عدة في نفس الوقت مثيرة للاهتمام ، خاصة وأن كل مترجم يحتاج إلى معالجة المدخلات والمخرجات. قمت بتطبيق هذا مع الخيوط و lambdas ، مما يعني بشكل ملائم أنني كان لدي فئة معممة لمشكلات الرمز الدولي هذه من اليوم التاسع فصاعدًا ، وكل ما احتاجه هو التلاعب بكيفية عمل I / O حوله. هذا يعني أيضًا أنه يمكنني بسهولة استهداف وظائف محددة للاختبار إذا أردت (على الرغم من أنني فوجئت بأن معظم المشاكل لم يكن لديها العديد من الأمثلة لاحقًا).

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

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