هل هناك اسم لهذه الرائحة المضادة للنمط/الرمز؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

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

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

class FunctionResult<T>
{
    public T payload;
    public int result;
}

ثم أعلن عن وظائفك مثل هذا:

FunctionResult<string> MyFunction()
{
    FunctionResult<string> result;
    //...

    return result;
}

أحد الاختلافات في هذا النمط هو استخدام التعداد لرمز الخطأ بدلاً من السلسلة.والآن أعود إلى سؤالي:هل هناك اسم لهذا، وإذا كان الأمر كذلك فما هو؟

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

المحلول

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

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

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

نصائح أخرى

حسنا انها لا نمط مضاد.تستفيد مكتبة C++ القياسية من هذه الميزة، كما يقدم .NET ميزة خاصة FunctionResult فئة في إطار عمل .NET.تسمى Nullable.نعم، لا يقتصر هذا على نتائج الوظائف ولكن يمكن استخدامه لمثل هذه الحالات وهو في الواقع مفيد جدًا هنا.إذا كان .NET 1.0 يحتوي بالفعل على Nullable فئة، فمن المؤكد أنه كان سيتم استخدامه ل NumberType.TryParse الأساليب بدلاً من out معامل.

عادةً ما أقوم بتمرير الحمولة كمرجع (ليس ثابتًا) ورمز الخطأ كقيمة إرجاع.

أنا مطور ألعاب، ونحن نستبعد الاستثناءات

كونراد على حق، يستخدم C# قيم الإرجاع المزدوجة طوال الوقت.لكنني أحب نوعًا ما TryParse وDictionary.TryGetValue وما إلى ذلك.الأساليب في C #.

int value;
if (int.TryParse("123", out value)) {
    // use value
}

بدلاً من

int? value = int.TryParse("123");
if (value != null) {
    // use value
}

...في الغالب لأن النمط Nullable لا يتناسب مع أنواع الإرجاع غير ذات القيمة (أي مثيلات الفئة).لن يعمل هذا مع Dictionary.TryGetValue().يعد TryGetValue أجمل من KeyNotFoundException (لا توجد "استثناءات الفرصة الأولى" باستمرار في مصحح الأخطاء، ويمكن القول إنها أكثر كفاءة)، وأجمل من ممارسة Java المتمثلة في الحصول على () إرجاع قيمة فارغة (ماذا لو كان من المتوقع وجود قيم فارغة)، وأكثر كفاءة من الاضطرار إلى ذلك استدعاء يحتوي على مفتاح () أولا.

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

(يمكن أن يكون Java باستثناء أن نوع "السلسلة" مكتوب بأحرف صغيرة.في Java بالطبع، يتعين عليك استخدام فئة لمحاكاة قيم الإرجاع المزدوجة.)

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

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

على سبيل المثال، في حالة وجود كمية X من الغاز، هل يمكن لسيارة أن تنتقل من A إلى B، وإذا كان الأمر كذلك، فما هي كمية الغاز المتبقية؟يعد هذا النوع من الأسئلة مثاليًا لبنية البيانات التي قدمتها.من المتوقع عدم القدرة على القيام بالرحلة من A إلى B، وبالتالي لا ينبغي استخدام الاستثناء.

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

لقد أمضيت ساعات في محاولة تصحيح أخطاء كود الإشارة على جهاز MacBook الخاص بي قبل أن أكتشف أخيرًا أن sem_init لا يعمل على OSX!لقد تم تجميعه بدون أخطاء وتم تشغيله دون التسبب في أي أخطاء - ومع ذلك لم تعمل الإشارة ولم أتمكن من معرفة السبب.أنا أشفق على الأشخاص الذين يقومون بنقل التطبيق الذي يستخدم إشارات POSIX إلى OSX ويجب أن يتعامل مع مشكلات التنافس على الموارد التي تم تصحيح أخطائها بالفعل.

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

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

لن أسميها نمطًا مضادًا.إنها طريقة عملية ومثبتة جيدًا وغالبًا ما تكون مفضلة على استخدام الاستثناءات.

إذا كنت تتوقع أن تفشل طريقتك من حين لآخر، ولكن لا تعتبر ذلك استثنائيًا، فأنا أفضل هذا النمط كما هو مستخدم في .NET Framework:

bool TryMyFunction(out FunctionResult result){    

     //...    
     result = new FunctionResult();
}

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

دفاعًا عن التعيين المضاد للنمط، يمكن استخدام هذا الرمز بعدة طرق:

  1. Object x = MyFunction().payload; (تجاهل نتيجة الإرجاع - سيء جدًا)
  2. int code = MyFunction().result; (التخلص من الحمولة - قد يكون أمرًا جيدًا إذا كان هذا هو الاستخدام المقصود.)
  3. FunctionResult x = MyFunction();//... (مجموعة من كائنات FunctionResult الإضافية ورمز إضافي للتحقق منها في كل مكان)

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

إذا كنت لا تزال لا توافق على هذا التقييم، قم بإلغاء التصويت على هذه الإجابة (وليس السؤال بأكمله).إذا كنت تعتقد أنه مضاد للنمط، فقم بالتصويت عليه.سنستخدم هذه الإجابة لنرى ما يفكر فيه المجتمع.

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