سؤال

وفقا ل Wikipedia، قرد التصحيح يكون:

طريقة لتوسيع أو تعديل رمز وقت التشغيل للغات الديناميكية [...] دون تغيير شفرة المصدر الأصلية.

البيان التالي من نفس الدخول مشوش لي:

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

أود أن أعلم المعنى الدقيق للتصحيح القرد في روبي. هل تفعل شيئا مثل ما يلي، أم أنه شيء آخر؟

class String
  def foo
    "foo"
  end
end
هل كانت مفيدة؟

المحلول

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

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

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

يؤكد البيان أعلاه أن استخدام Ruby غير صحيح - لكن المصطلحات تتطور، وهذا ليس دائما شيء سيء دائما.

نصائح أخرى

أفضل تفسير سمعت عنه قرد الترقيع / بطة اللكم هو باتريك إيوينغ في Railsconf 2007.

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

قرد الترقيع هو عندما يستبدل طرق الفصل في وقت التشغيل (ليس إضافة طرق جديدة كما وصف الآخرون).

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

انت على حق؛ إنه عند تعديل أو تمديد فئة موجودة بدلا من تصنيفها.

هذا هو الترقيع القرد:

class Float
  def self.times(&block)
    self.to_i.times { |i| yield(i) }
    remainder = self - self.to_i
    yield(remainder) if remainder > 0.0
  end
end

الآن أتصور أن هذا قد يكون مفيدا في بعض الأحيان، ولكن تخيل لو رأيت روتينا.

def my_method(my_special_number)
  sum = 0
  my_special_number.times { |num| sum << some_val ** num }
  sum
end

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

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


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

في بيثون، يشار إلى الكثير كعلامة على الإحراج: "اضطررت إلى الرد هذه الفئة لأن ..." (واجهتها أولا عند التعامل مع Zope، والتي تذكر المقالة). تم استخدامه ليقول أنه من الضروري إجراء عقد من فئة المنبع وإصلاحه في وقت التشغيل بدلا من الضغط على السلوكيات غير المرغوب فيها الثابتة في الفصل الفعلي أو إصلاحها في فئة فرعية. في تجربتي، لا يتحدث الناس روبييون عن الرصم كثيرا، لأنه لا يعتبر سيئا للغاية أو أكثر جديرة بالملاحظة (وبالتالي "اللكم بطة"). من الواضح أن عليك أن تكون حريصا بشأن تغيير قيم العودة للطريقة التي سيتم استخدامها في تبعيات أخرى، ولكن إضافة أساليب إلى فئة بالطريقة التي تعمل بها Active_Support و Joints آمنة تماما.

تحديث بعد 10 سنوات: أود أن أدى الجملة الأخيرة إلى القول "آمنة نسبيا". يمكن أن يؤدي تمديد فئة مكتبة أساسية ذات طرق جديدة إلى مشاكل إذا حصل شخص آخر على الفكرة نفسها وتضيف نفس الطريقة بتنفيذ أو توقيع طريقة مختلفة، أو إذا كان الناس يخلطون الأساليب الموسعة لوظائف اللغة الأساسية. غالبا ما تحدث كلتا الحالتين في Ruby (خاصة فيما يتعلق بطرق نشط_support).

عادة ما يكون المقصود حول تغييرات مخصصة، باستخدام فصول روبي المفتوحة، في كثير من الأحيان مع رمز الجودة المنخفض.

متابعة جيدة حول هذا الموضوع:

http://www.infoq.com/articles/rouby-open-classes-mass-mankypatching.

شرح المفهوم دون رمز:

مناقشة المفهوم الدقيق هو Waaaay الأكاديمي للغاية وإطفاء مما يجب أن يكون. دعونا نبقيها بسيطة مع المثال التالي:

التشغيل الطبيعي للسيارة

كيف تبدأ سيارة عادة؟ إنه أمر بسيط: يمكنك تشغيل الإشعال، وتبدأ السيارة، وفويلا أنت خارج الأجناس!

قرد الترقيع سيارة

ولكن ماذا لو صنع شخص آخر السيارة وما إذا كنت ترغب في تغيير كيفية عمله؟

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

فابريزيو، أين أنت ذاهب؟

فقاعة!

Monday, Tuesday, Wed-nes-day, Thursday, Friday, Sat-a-day. Image is free and open source from unsplash - https://unsplash.com/photos/dyrehVIidQk

"حافظ على إغلاق التعليمات البرمجية المصدرية، ولكن بقع قرد أقرب."

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top