هل من المقبول تصحيح فئات روبي الأساسية، مثل Fixnum؟
-
04-07-2019 - |
سؤال
ما زلت جديدًا جدًا على روبي (أقرأ الفأس وأقضي معظم وقتي فيه irb
)، والآن بعد أن علمت أنه من الممكن تصحيح الفئات في روبي، أتساءل متى يكون من المقبول القيام بذلك، وتحديدًا ما إذا كان من المقبول تصحيح الفئات الأساسية في روبي.على سبيل المثال:أجبت على سؤال روبي آخر هنا حيث أراد الملصق معرفة كيفية طرح ساعات من أ DateTime
.منذ DateTime
لا يبدو أن الفصل الدراسي يوفر هذه الوظيفة، فقد قمت بنشر إجابة تعمل على تصحيح الخطأ DateTime
و Fixnum
الطبقات كحل ممكن.هذا هو الكود الذي أرسلته:
require 'date'
# A placeholder class for holding a set number of hours.
# Used so we can know when to change the behavior
# of DateTime#-() by recognizing when hours are explicitly passed in.
class Hours
attr_reader :value
def initialize(value)
@value = value
end
end
# Patch the #-() method to handle subtracting hours
# in addition to what it normally does
class DateTime
alias old_subtract -
def -(x)
case x
when Hours; return DateTime.new(year, month, day, hour-x.value, min, sec)
else; return self.old_subtract(x)
end
end
end
# Add an #hours attribute to Fixnum that returns an Hours object.
# This is for syntactic sugar, allowing you to write "someDate - 4.hours" for example
class Fixnum
def hours
Hours.new(self)
end
end
لقد قمت بتصحيح الفئات لأنني اعتقدت في هذه الحالة أنها ستؤدي إلى بناء جملة واضح وموجز لطرح عدد محدد من الساعات من DateTime
.على وجه التحديد، يمكنك أن تفعل شيئا من هذا القبيل نتيجة للكود أعلاه:
five_hours_ago = DateTime.now - 5.hours
والذي يبدو جميلًا إلى حدٍ ما عند النظر إليه وسهل الفهم؛ومع ذلك، لست متأكدًا مما إذا كان من الجيد العبث بوظائف DateTime
'س -
المشغل أو العامل.
البدائل الوحيدة التي يمكنني التفكير فيها لهذا الموقف هي:
1.ببساطة قم بإنشاء جديد DateTime
الكائن أثناء التنقل، وحساب قيمة الساعة الجديدة في المكالمة إلى new
new_date = DateTime.new(old_date.year, old_date.year, old_date.month, old_date.year.day, old_date.hour - hours_to_subtract, date.min, date.sec)
2.اكتب طريقة فائدة تقبل a DateTime
وعدد الساعات التي سيتم الطرح منها
في الأساس، مجرد طريقة ملتفة (1):
def subtract_hours(date, hours)
return DateTime.new(date.year, date.month, date.day, date.hour - hours, date.min, date.sec)
end
3.إضافة طريقة جديدة ل DateTime
بدلاً من تغيير السلوك الحالي لـ #-()
وربما جديد DateTime#less
الطريقة التي يمكن أن تعمل جنبا إلى جنب مع Fixnum#hours
patch، للسماح ببناء الجملة مثل هذا:
date.less(5.hours)
ومع ذلك، وكما ذكرت سابقًا، فقد اتبعت أسلوب التصحيح لأنني اعتقدت أنه أدى إلى بناء جملة أكثر تعبيرًا.
هل هناك أي خطأ في النهج الذي أتبعه، أم يجب أن أستخدم أحد البدائل الثلاثة (أو بديل آخر لم أفكر فيه) للقيام بذلك؟لدي شعور بأن التصحيح أصبح "مطرقتي" الجديدة لحل المشكلات في روبي، لذا أود الحصول على بعض التعليقات حول ما إذا كنت أفعل الأشياء "بطريقة روبي" أم لا.
المحلول
إجابتي الشخصية باختصار: يجب أن تكون مطرقة الترقيع من الفئة الأساسية في الجزء السفلي من صندوق الأدوات الخاص بك.هناك الكثير من التقنيات الأخرى المتاحة لك، وفي جميع الحالات تقريبًا تكون كافية وأنظف وأكثر من ذلك مستمر.
يعتمد الأمر حقًا على البيئة التي تقوم بالبرمجة فيها.إذا كان مشروعًا شخصيًا - فبالتأكيد، قم بالتصحيح بما يناسب قلبك!تبدأ المشاكل في الظهور عندما تعمل على قاعدة تعليمات برمجية كبيرة لفترة طويلة من الزمن مع مجموعة كبيرة من المبرمجين.في المؤسسة التي أعمل بها، والتي تحتوي على قواعد بيانات روبي لأكثر من 100KLOC وعشرين مطورًا أو نحو ذلك، بدأنا في اتخاذ إجراءات صارمة ضد تصحيح القرود، لأننا رأينا ذلك يؤدي إلى سلوك مربك وإهدار ساعات العمل. كثيرا جدا.في هذه المرحلة، نحن نتسامح إلى حد كبير فقط مع تصحيح كود الطرف الثالث مؤقتًا والذي إما لم يتم دمجه بعد أو لن يتضمن تصحيحات المصدر الخاصة بنا.
نصائح أخرى
أنا شخصياً أعتقد أنه من المقبول إضافة أساليب إلى الفئات الأساسية، ولكن من غير المقبول تعديل تنفيذ الأساليب الحالية.
ال الأكثر أمانا الطريقة هي تحديد فصلك الخاص الذي يرث من الفصل المدمج، ثم إضافة الأشياء الجديدة إلى فصلك الجديد.
class MyDateTime < DateTime
alias...
def...
لكن من الواضح الآن أنك لن تحصل على السلوك الجديد إلا إذا أعلنت عن كائنات من صفك الجديد.
أعتقد أنها مثل هذا:إذا كنت تشعر بصدق أن معظم المبرمجين الآخرين سيوافقون على تصحيحاتك، فلا بأس.إذا لم يكن الأمر كذلك، فربما يجب عليك بدلاً من ذلك تنفيذ مكتبة الأكواد؟