
عندما كنت أنا وصديقي في سن المدرسة ونطمح لأن نصبح مطورين برامج ، حلمنا في تصميم بعض الأشياء الرائعة معًا - مثل لعبة أو تطبيق مفيد للغاية.
اخترت أن أتعلم C ++ و C # ، اختار JavaScript. انتهينا من المدرسة ، وتخرجنا من جامعاتنا ، وخدمنا في الجيش وبدأنا وظائفنا. لقد قضينا وقتًا ممتعًا جدًا في هندسة البرمجيات الصناعية ، مع الكثير من الوظائف والمناصب المختلفة ، وبعد أن بدأ كل شيء يرتد علينا ، تذكرنا من حيث بدأ كل شيء.
بعد أن تضافرت معًا كمطورين ناضجين ، قررنا العمل في مشروعنا - لعبة فيديو ثنائية الأبعاد. نظرًا لأن مجال صديقي كان بمثابة واجهة أمامية وكنت مطورًا متكاملاً ، فقد كان اختيارنا الفوري لمنصة التطوير بمثابة متصفح إنترنت. نظرًا لأنني كنت معتادًا على العمل مع TypeScript فقط عند تصميم الواجهة الأمامية ، فكرنا ، حسنًا ، لا مشكلة ، بعد كل شيء ، TS هو مجرد JavaScript على نطاق واسع. دعونا نستخدمها وسوف تسير الامور بسلاسة. إذا كنت أعرف فقط كيف كنت مخطئا! عندما بدأنا مناقشة المشروع ، واجهنا فجوة واسعة من سوء الفهم بيننا.
هنا كانت رؤيتي للعبة. كنت مثل ، حسنا ، لدينا أنواع مثل اللعبة ، الأداة ، العنصر ، الخريطة ، الموقع. لدي فهم أساسي لكيفية عملهم معًا ، لذلك أصفهم ، وقم بتجميع المشروع - وهو يعمل. بعد كل شيء ، قام المترجم بالتحقق من الكود ، وفعلت ذلك بشكل صحيح. بعد ذلك ، أبدأ كتابة التعليمات البرمجية التي تستخدم هذه الأنواع. أنها تجعل حياتي أسهل بكثير. بلدي IDE يعطيني تلميحات الأدوات والتحقق من أي أخطاء. إذا كان يمكن تجميع مشروع ، فمن المحتمل أن يعمل. قضيت بعض الجهد في وصف النوع وقد أسفرت عن نتائج. هذا هو مقاربي باختصار.
كان لدى صديقي الفكرة المعاكسة - القفز إلى كتابة التعليمات البرمجية على الفور دون أن يستغرق أي وقت لوصف الأنواع. لم يكن مستعدًا لتعريف المشكلة باعتبارها عائلة من الأنواع. لم يكن حريصًا على استخدامه كأساس ، لأنه لم ير المشكلة كمجموعة من الفصول ، أنواع ، سجلات أي شيء من هذا القبيل. اعتقدت انه كان لا يمكن تصوره. كلانا كان عنده نقطة ، هو فقط أن نقاطنا كانت حصرية بشكل متبادل.
على محمل الجد ، كنا نتحدث لساعات ، ولكن كل منهم كان يقول شيئه الخاص ، كما لو كنا نتحدث بلغات مختلفة. مانع لك ، لم أتمكن من إلقاء اللوم علينا عالقين في طرقنا القديمة. منذ عام واحد فقط ، هاجرت من عالم البرمجة الموجهة إلى عالم البرمجة الوظيفية والعودة. علاوة على ذلك ، قضيت بعض الوقت في تعلم JS ، وهو - على تعلم عدد من اللغات المكتوبة بشكل ثابت.
ومع ذلك ، فبالنسبة لأي مطور ، فإن التكنولوجيا التي استخدموها في أول عمل حقيقي لهم غالباً ما يعرّفهم إلى الحد الذي ينقصه شخصان بالغان من ذوي الخبرة ببساطة الصبر للاستماع إلى بعضهم البعض. خلال هذه السنوات من هندسة البرمجيات ، تم تشكيل رؤيتنا بطرق مختلفة بحيث لم تتوافق مناهجنا لحل المشكلات مع بعضها البعض.
في النهاية تخلينا عن فكرة العمل كفريق واحد. قد يكون ردك الأول هو أن المشكلة كانت في شخصياتنا. قد تكون على حق ، لكنني رأيت هذا يحدث أيضًا للآخرين في الصناعة.
الفرق الأساسي غير القابل للتوفيق بين الكتابة الثابتة والديناميكية
توفر الكود الخاص بي حلاً لمشكلة كيفية التعامل معها ، في حين أن كود دعاة الكتابة الديناميكية المتمرسين يحل مشكلة كيفية عمله. كلا العقليتين شرعيتان ومدعومتان من قبل مجموعات الأدوات الحالية ، لكن يمكن أن يكون لأحدهما أولوية قصوى في أي لحظة.
تعد الكتابة الثابتة مفيدة للمشروعات الكبيرة التي تضم مئات من المطورين الذين يعملون عليها لسنوات ، في حين أن الكتابة الديناميكية جيدة للمجموعات الصغيرة والمشاريع التي تتطلب غالبًا رموز للكتابة فقط. تتيح لك الكتابة الديناميكية توفير الوقت والجهود في بداية التطوير ، في حين أن الكتابة الثابتة تمنحك دفعة في نهاية الأمر.
أثرت فكرة وضع الأنواع أولاً على تفكيري كمطور. بعد أن اخترت C # في بداية حياتي المهنية ، لدي كتابة ثابتة مشفرة في ذهني ، وأنا أدفع ثمن عدم المرونة هذا الآن. بمجرد أن أرى مهمة ، أحاول أن أتخيل حلها كمجموعة من أنواع وقواعد علاقتها. عندما أقوم بتطوير وحدة نمطية ، فإن خطوتي الأولى هي تحديد الأنواع التي تعمل بها واستخدامها للتفاعل مع بيئتها. أنا فقط لا أتذكر كيف اعتدت على حل المشاكل قبل ذلك.
تدور العملية الكاملة لتعلم البرمجة في Java حول تعلم تصميم واستخدام الأنواع. تم تصميم .NET CLR - وقت تشغيل C # - على أنواع وأنواع. تقف الكتابة الثابتة في صميم نموذج البرمجة الموجهة للكائنات (مرحباً ، فصول JS ، قررت أن أعطيك استراحة). يتم تشبع التطبيقات المتعارف عليها لمعظم أنماط OOP باستخدام الكلمة الأساسية Interface ، والتي لا معنى لها على الإطلاق في لغة مكتوبة ديناميكيًا.
أنماط التصميم نفسها عبارة عن مفاهيم متعددة اللغات ، لكن هل يستطيع أحد أن يقول لي لماذا على الأرض ، أحتاج إلى نمط الحالة بلغة مكتوبة ديناميكيًا؟ ماذا عن باني؟ هذه الأنماط لا علاقة لها بالتطور ، فهي تتعلق أساسًا بالأنواع. أنواع و OOP لها رابط ضيق.
لا يمكنك بناء منطق عملك على أنواع ومع ذلك لا تعرف شيئًا عنها عند بدء كتابة التعليمات البرمجية. لهذا السبب لدينا مطورو الواجهة الأمامية الذين يقومون بتسليح الكود الخاص بهم بعدد لا يصدق من اختبارات الوحدات التي تتحقق بشكل خاص من قاعدة الشفرات بحثًا عن أي أخطاء في النوع.
نعلم جميعًا أن الحماية المستندة إلى تغطية الكود هي وهم. تتم كتابة الاختبارات يدويًا ، وهي بحكم تعريفها أقل موثوقية من نظام التحقق من النوع المضمن في اللغة.
هذا لا يعني أن اللغات المكتوبة بشكل حيوي لا معنى لها (على الرغم من أنني أعترف أنني أعتقد أنها لا تفعل ذلك). هذا يعني أنه أثناء استخدامها ، تحتاج إلى التراجع عن OOP كنموذج مهيمن. كل هذه الوحدة من البيانات والعمليات المستندة إلى البيانات هي للزملاء الذين لديهم كتابة ثابتة.
لا يعتقد مطورو البرامج الذين قابلتهم أن الكتابة الثابتة تؤثر على طريقة الترميز إلى أي حد ، لذلك يكتبون فقط الكود الخاص بهم كما لو كانوا يستخدمون لغة ديناميكية ، لكنهم يضيفون تدقيق الكتابة فقط. أعتقد أن هذا خطأ بطبيعته. من الواضح بشكل خاص في حالة الواجهة الأمامية الحديثة.
وأنا أعلم ، وأنا أعلم ، أن هناك من المحرمات في انتقاد مطوري الواجهة الأمامية. صديقي وأنا أعددنا روبوتًا من الذكاء الاصطناعى قام بتجول مستخدمي تويتر ، وحصلنا على بريندان إيتش. على محمل الجد ، كان لمنشئ جافا سكريبت JavaScript اتصالًا سريعًا مع شبكتنا العصبية في التعليقات.
لسبب ما ، هؤلاء الشباب ليسوا مستعدين للعيش في عالم تعاني فيه رؤيتهم من أوجه قصور ملموسة. لهذا السبب أنتقد فقط أولئك الذين يعبثون بمشروعي المكتوب بالتأكيد لإعادة صياغته بطريقة مريحة "بأي طريقة".
سوف نستمر في السكن في عوالمنا الصغيرة ، ولكن TypeScript جمعنا
خذني على سبيل المثال: بسبب قيود الكتابة ، من المستحيل استخدام الشفرة بشكل غير صحيح. عندما أعمل في مشروع ، فأنا أعتمد على الآخرين لاستخدام الأنواع أيضًا. ثم ستعمل الكود الخاص بي بنفس التصميم. لذلك أنا لا أغطي جميع الحالات التي يمكن فيها استخدام هذا الرمز بطريقة غير صحيحة (لأن الكتابة تجعل من المستحيل). ولكن بعد ذلك ينضم مطور JS إلى مشروعي ، ويأخذ نوعي ، ويختتمه في أي ويبدأ استخدامه بطريقة غير صحيحة ، مما ينتج عنه أخطاء يصعب تكرارها.
مطورو JavaScript على ثقة من أن TypeScript هو نفس JS القديم ، ولكن مع وجود خيار لإضافة اختبارات النوع الثابت إذا احتاجوا إليها. هذا خطأ TypeScript أقوى بمائة مرة ، لكنهم مهتمون فقط بجزء بسيط من إمكاناته.
حجة القاتل هي أن TypeScript هو مجرد مجموعة من JS. في الممارسة العملية ، لا يمكن للمرء أن يتجاهل حقيقة أن TypeScript هي لغة مستقلة ، حتى لو كان أحدهم ملكًا غريبًا للواجهة الأمامية. لأنه يتطلب نهجًا مختلفًا - نهج التحقق الثابت ، وليس الديناميكي.
الفائدة الرئيسية للكتابة الثابتة هي أنها تمنحك ضمانات. إذا كنت تستخدمها في وحدة نمطية واخترت عدم استخدامها في وحدة أخرى ، فأنت تضيع وقتك وطاقتك في وصف تلك الأنواع وتصميمها ، دون الحصول على أي ضمانات على الإطلاق.
يعتقد الكثيرون أن TypeScript هو حل وسط لأنظمة الكتابة بين JS و Java. حسنًا ، إنه ليس حل وسط من أي نوع ، بل لديه نظام خاص من نوعه.
الأسوأ من ذلك كله ، اليوم واحد في اثنين من المواقف الأمامية يتطلب الكفاءة في TypeScript. هذا يحفز مطوري JS لإلقاء نظرة على ميزات TypeScript والانتقال على الفور لكتابة التعليمات البرمجية فيها ، مما يؤدي إلى تكاثر الممارسات الضارة. تحدث المواقف عندما لا يحتاجون حقًا إلى التحقق من النوع الثابت ، ولكنه كان نوعًا ما مفروضًا عليهم ، لذا فقد عابثوا به. نحتاج أن نعترف أخيرًا بأن مناهج البرمجة مع الكتابة الديناميكية الثابتة مقابل الكتابة تتعارض مع بعضها البعض ولا يمكن خلطها.
أرى جافا سكريبت أداة رائعة لكتابة رمز الاختراق السريع الذي يوفر حلولًا دون حل التجريدات غير الضرورية. المثال الأكثر فظاعة هنا هو نمط مصنع الثلج. يمكنك إطعامها مثيلاتك ، وسوف تغلفها في ثبات وقت التشغيل. إذا قمت بمعالجة الكائن الخاص بي من خلال هذا المصنع ، فسوف يُرجع هذا المكافئ ، لكن إذا حاولت تغيير أحد خصائصه ، فستكون هناك مشكلة. ماذا؟
ظهر هذا النمط لأن مطوري الواجهة الأمامية سمعوا في مكان ما عن ثباته البارد ، لذلك قرروا سحب هذا القرف إلى لغتهم ، الأمر الذي يحتاجه مثل ثقب في الرأس. في TypeScript ، يمكنني تصميم مصنع مشابه ، لكن مع فرض قيود على وقت الترجمة على الطفرات وبدون أي استثناءات.
من ناحية أخرى ، أنا بالكاد أحتاج إلى هذا لأن هناك البرمجة الوظيفية الخالصة. خذ F # و Haskell و OCaml و Clojure و ReasonML على سبيل المثال - لديهم حظر غير قابل للتطبيق للتبادل. ولكن هناك شيء ما يخبرني أنه إذا وضع مطور الواجهة الأمامية يديه على لغة وظيفية ، فسيكون مستعدًا لترقيتها لجعل سلوكه مشابهًا لسلوك JavaScript.
ذلك لأن اختيار دين الكتابة هو تذكرة ذهاب فقط. الكل في ما بين الحلول لا يوفر إلا وهم التسوية. أنت إما تعتمد على أنواع أو لا. لا أعرف ما إذا كانت حياتي ستكون مختلفة لو أنني بدأت في تعلم C # وجافا سكريبت بالتوازي. اليوم أنا أعرّف نفسي بشكل يائس مع ذهني لدرجة أنني لا أرى أي مزايا للكتابة الديناميكية (وليس لدي أي رغبة في رؤيتها). إنها موجودة ، فقط خارج نطاق الرؤية الخاصة بي ، لذلك كل ما يمكنني فعله هو أن أغمض عيني عنهم كما أفعل لأية ظواهر يجب أن أتحملها في هذا العالم. أعلم أنني مخطئ ، لكن يجب أن أعمل هنا والآن ، وليس لدي ميزانية لأستمر في الجلوس على السياج.
لذلك أنا لا أريد البحث عن حلول وسط ، بدلاً من ذلك سأضعها في نصابها الصحيح. إذا كنت تقوم بخطواتك الأولى في التطوير ، فابدأ بالكتابة الثابتة!