ما هي أفضل الممارسات في روبي لتجنب إساءة استخدام المهمة "="؟

StackOverflow https://stackoverflow.com/questions/5443068

سؤال

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

أستطيع أن أرى أنه سيكون من المنطقي تجنب البساطة x = y المهام دون سبب خاص، ولكن نفس الشيء يمكن أن يكون كامنًا في أماكن أخرى مثل

name = (person.last_name.blank? ? 'unknown' : person.last_name)

حيث في وقت لاحق name << title في الواقع سيتم تغيير person.last_name وليس الاسم فقط.

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

هل كانت مفيدة؟

المحلول

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

http://en.wikipedia.org/wiki/Functional_programming

لذلك، في المثال الخاص بك، ما عليك سوى إنشاء سلسلة جديدة باسم جديد:

complete_name = name + title

نصائح أخرى

مجرد إضافة إلى إجابة tokland:

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

لذا، هناك ثلاثة أشياء يجب تذكرها الآن:

  1. تعرف على المهمة في روبي:لا شيء سوى تسمية كائن.لذلك، عندما تقول y=x, ، أنت تقول فقط "نعطي اسمًا آخر y إلى ما سميت به x".
  2. name << title يتحول كائن يسمى name.
  3. name += title يأخذ الكائنات المسماة name و title, ، يسلسلهم في آخر كائن، ويعين اسم الكائن الجديد name.لا يتحول أي شيء.

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

hash = {....}
filename = object.file_name
hash.each |k, v| {file_name.gsub!(k, v) if file_name.include? k}

كان هذا الرمز داخل حلقة وفي الحلقة توقعت المتغير file_name ليتم ضبطها مرة أخرى على القيمة الأصلية.ولكن تم تغيير object.file_name أثناء أدائي file_name.gsub!.هناك طريقتان لحل هذه المشكلة.إما استبدال .gsub! الاتصال مع file_name = file_name.gsub أو افعل file_name = object.file_name.dup.اخترت الخيار الثاني.

أعتقد أننا يجب أن نكون حذرين مع الأساليب ! و <<, حيث يقومون بتغيير الكائن الأصلي الذي يتصرفون عليه، خاصة بعد مهام كهذه.

يجب ألا تقوم الطريقة بتعديل متغير (على سبيل المثال.باستخدام عامل التحول) ما لم ينص تعريفه على أنه سيتم تعديله.

لذا:لا تقم مطلقًا بتعديل كائن بطريقة لم تقم (أ) بإنشائه أو (ب) بتوثيق تعديله.

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