سؤال

هناك أسباب وجيهة لماذا هو ممارسة أفضل أن يكون واحد فقط العودة البيان في وظيفة ؟

أو هو حسن في العودة من وظيفة في أقرب وقت كما هو الصحيح منطقيا أن تفعل ذلك ، وهذا يعني قد يكون هناك العديد من عودة البيانات في وظيفة ؟

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

المحلول

أنا غالبا ما يكون عدة بيانات في بداية طريقة للعودة عن "سهل" الحالات.على سبيل المثال هذا:

public void DoStuff(Foo foo)
{
    if (foo != null)
    {
        ...
    }
}

...يمكن أن تكون أكثر قابلية للقراءة (IMHO) مثل هذا:

public void DoStuff(Foo foo)
{
    if (foo == null) return;

    ...
}

لذا نعم, أعتقد أنه من الجيد أن يكون لديك عدة "نقاط الخروج" من وظيفة/طريقة.

نصائح أخرى

ذكرها أحد أو نقلت رمز كاملة ولذا فإنني سوف تفعل ذلك.

17.1 العودة

تقليل عدد العائدين في كل الروتين.من الصعب أن نفهم روتين إذا قراءته في الجزء السفلي ، أنت على علم من احتمال أنه عاد في مكان ما فوق.

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

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

string fooBar(string s, int? i) {
  string ret = "";
  if(!string.IsNullOrEmpty(s) && i != null) {
    var res = someFunction(s, i);

    bool passed = true;
    foreach(var r in res) {
      if(!r.Passed) {
        passed = false;
        break;
      }
    }

    if(passed) {
      // Rest of code...
    }
  }

  return ret;
}

قارن هذا إلى رمز فيها عدة نقاط الخروج هي المسموح به:-

string fooBar(string s, int? i) {
  var ret = "";
  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

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

أنا حاليا أعمل على تعليمات البرمجة الأساسية حيث اثنين من العاملين على هذا عمياء الاشتراك في "نقطة الخروج" نظرية أستطيع أن أقول لك هذا عن تجربة انه الرهيبة الرهيبة الممارسة.يجعل رمز من الصعب للغاية الحفاظ على و سوف تظهر لك لماذا.

مع "نقطة الخروج" نظرية أنت حتما تصل الرياح مع رمز التي تبدو مثل هذا:

function()
{
    HRESULT error = S_OK;

    if(SUCCEEDED(Operation1()))
    {
        if(SUCCEEDED(Operation2()))
        {
            if(SUCCEEDED(Operation3()))
            {
                if(SUCCEEDED(Operation4()))
                {
                }
                else
                {
                    error = OPERATION4FAILED;
                }
            }
            else
            {
                error = OPERATION3FAILED;
            }
        }
        else
        {
            error = OPERATION2FAILED;
        }
    }
    else
    {
        error = OPERATION1FAILED;
    }

    return error;
}

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

هذا الأسلوب يجعل رمز الصيانة صعبة للغاية وعرضة للخطأ.

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

كما كينت بيك ملاحظات عند مناقشة بنود في الحرس تنفيذ أنماط جعل روتين واحد نقطة الدخول والخروج ...

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

أجد وظيفة مكتوبة مع حارس الأحكام أسهل بكثير لمتابعة أكثر من واحدة طويلة متداخلة مجموعة من if then else التصريحات.

في وظيفة له أي آثار جانبية, ليس هناك سبب وجيه أن يكون أكثر من واحد العودة و يجب أن تكتب لهم في نمط وظيفي.في الأسلوب مع الآثار الجانبية الأمور أكثر متتابعة (الوقت-فهرسة) ، لذلك كنت أكتب في حتمية أسلوب بيان العودة كما أمر وقف التنفيذ.

وبعبارة أخرى, عندما يكون ذلك ممكنا ، صالح هذا النمط

return a > 0 ?
  positively(a):
  negatively(a);

أكثر من هذا

if (a > 0)
  return positively(a);
else
  return negatively(a);

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

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

لقد رأيت ذلك في معايير الترميز C++ التي تم شنق أكثر من ج ، كما إذا لم يكن لديك RAII أو غيرها من إدارة الذاكرة التلقائي ثم لديك لتنظيف لكل العودة ، مما يعني قص ولصق من تنظيف أو غوتو (منطقيا نفس 'أخيرا' في إدارتها اللغات) ، وكلاهما يعتبر شكل سيء.إذا كانت الممارسات لاستخدام المؤشرات الذكية و مجموعات في C++ أو أخرى أوتوماتيكية نظام الذاكرة, ثم ليس هناك سبب قوي لذلك ، أصبح كل شيء عن قراءة و أكثر من حكم الكلمة.

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

هناك أسباب وجيهة لماذا هو ممارسة أفضل أن يكون واحد فقط العودة البيان في وظيفة ؟

نعم, هناك:

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

السؤال هو في كثير من الأحيان تشكل زائف بين عدة عوائد أو بالغ عبارات if المتداخلة.هناك دائما تقريبا حل ثالث وهو خطية جدا (لا تداخل عميق) مع واحد فقط نقطة الخروج.

التحديث:على ما يبدو ميسرا المبادئ التوجيهية وتعزيز واحدة الخروج, أيضا.

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

وجود واحد نقطة الخروج لا توفر ميزة في التصحيح ، لأنه يسمح لك تعيين واحد نقطة في نهاية الدالة لمعرفة قيمة ما يجري في الواقع أن تعاد.

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

لا, لأن نحن لا نعيش في 1970s المزيد.إذا وظيفة الخاص بك هو طويل بما فيه الكفاية متعددة ترجع هي المشكلة انها طويلة جدا.

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

أفضله أن يكون واحد مخرج ما يعقد الأمور.لقد وجدت أنه في بعض الحالات وجود متعددة النقاط قناع أخرى أكثر أهمية تصميم المشاكل:

public void DoStuff(Foo foo)
{
    if (foo == null) return;
}

على رؤية هذا الرمز ، وأود أن تطلب فورا:

  • هو 'فو' من أي وقت مضى باطل?
  • إذا كان الأمر كذلك ، كيف العديد من عملاء 'DoStuff' من أي وقت مضى استدعاء الدالة مع null 'فو'?

اعتمادا على إجابات على هذه الأسئلة قد يكون ذلك

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

في كل من الحالات المذكورة أعلاه رمز يمكن على الأرجح أن تكون صياغتها مع التأكيد على ضمان أن 'فو' أبدا فارغة ذات الصلة المتصلين تغيرت.

هناك نوعان من الأسباب الأخرى (محددة أعتقد أن C++ code) حيث متعددة موجودة في الواقع يمكن أن يكون السلبية تؤثر.فهي رمز حجم مترجم التحسينات.

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

void foo (int i, int j) {
  A a;
  if (i > 0) {
     B b;
     return ;   // Call dtor for 'b' followed by 'a'
  }
  if (i == j) {
     C c;
     B b;
     return ;   // Call dtor for 'b', 'c' and then 'a'
  }
  return 'a'    // Call dtor for 'a'
}

إذا كان حجم التعليمات البرمجية مسألة - ثم هذا قد يكون شيئا يستحق تجنب.

المسألة الأخرى تتعلق "اسمه إرجاع القيمة الأمثل" (ويعرف أيضا باسم نسخ ترخيم, ISO C++ '03 12.8/15).C++ يسمح تنفيذ لتخطي استدعاء منشئ نسخة إذا كان يمكن أن:

A foo () {
  A a1;
  // do something
  return a1;
}

void bar () {
  A a2 ( foo() );
}

مجرد أخذ الكود كما هو الكائن 'a1' هي التي شيدت في 'فو' ثم نسخ بناء وسوف يطلق لبناء "a2".ومع ذلك, نسخ ترخيم يسمح مترجم إلى بناء 'a1' في نفس المكان على المكدس "a2".ولذلك هناك حاجة إلى "نسخ" الكائن عند ترجع الدالة.

عدة نقاط الخروج يعقد عمل مترجم في محاولة للكشف عن هذا و على الأقل نسبيا النسخة الأخيرة من VC++ التحسين لا تأخذ مكان في الجسم وظيفة متعددة العوائد.انظر اسمه إرجاع القيمة الأمثل في Visual C++ 2005 للحصول على مزيد من التفاصيل.

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

أنا أجبر نفسي على استخدام واحد فقط return البيان ، كما أنه سيتم بمعنى توليد رمز رائحة.اسمحوا لي أن أشرح:

function isCorrect($param1, $param2, $param3) {
    $toret = false;
    if ($param1 != $param2) {
        if ($param1 == ($param3 * 2)) {
            if ($param2 == ($param3 / 3)) {
                $toret = true;
            } else {
                $error = 'Error 3';
            }
        } else {
            $error = 'Error 2';
        }
    } else {
        $error = 'Error 1';
    }
    return $toret;
}

(الشروط arbritary...)

المزيد من الشروط ، أكبر وظيفة يحصل على أكثر صعوبة القراءة.حتى إذا كنت منسجمة مع قانون رائحة, عليك أن تدرك ذلك و تريد أن ريفاكتور القانون.اثنين من الحلول الممكنة:

  • متعددة ترجع
  • إعادة بيع ديون إلى مهام منفصلة

متعددة ترجع

function isCorrect($param1, $param2, $param3) {
    if ($param1 == $param2)       { $error = 'Error 1'; return false; }
    if ($param1 != ($param3 * 2)) { $error = 'Error 2'; return false; }
    if ($param2 != ($param3 / 3)) { $error = 'Error 3'; return false; }
    return true;
}

مهام منفصلة

function isEqual($param1, $param2) {
    return $param1 == $param2;
}

function isDouble($param1, $param2) {
    return $param1 == ($param2 * 2);
}

function isThird($param1, $param2) {
    return $param1 == ($param2 / 3);
}

function isCorrect($param1, $param2, $param3) {
    return !isEqual($param1, $param2)
        && isDouble($param1, $param3)
        && isThird($param2, $param3);
}

إنها أطول قليلا فوضوي ، ولكن في عملية إعادة بيع ديون وظيفة هذه الطريقة ، لقد

  • إنشاء عدد من القابل لإعادة الاستخدام من المهام ،
  • جعل وظيفة الإنسان أكثر قابلية للقراءة ،
  • التركيز على المهام على السبب القيم الصحيحة.

أود أن أقول يجب أن يكون كما هو مطلوب ، أو أي أنه جعل رمز نظافة (مثل حارس الشروط).

أنا شخصيا لم أسمع/أر أي "أفضل الممارسات" أقول أنه يجب أن يكون واحد فقط العودة البيان.

بالنسبة للجزء الأكبر, أنا أميل إلى خروج وظيفة في أقرب وقت ممكن على أساس منطق المسار (حارس بنود هي مثال ممتاز على هذا).

وأعتقد أن العديد يعود عادة ما تكون جيدة (في التعليمات البرمجية التي أكتب في C#).واحد العودة الاسلوب هو من بقايا C.ولكن ربما لا الترميز في C.

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

أكثر من عودة النمط قد تكون هذه العادة السيئة في التعليمات البرمجية C ، حيث الموارد يجب أن تكون صراحة دي-تخصص اللغات مثل Java, C#, Python أو جافا سكريبت التي يبني مثل آلية جمع القمامة ، try..finally كتل (و using كتل في C#) و هذه الحجة لا تنطبق في هذه اللغات ، فمن النادر جدا أن تحتاج مركزية دليل الموارد deallocation.

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

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

تحدثت عن هذا في زيادة طول على بلدي بلوق.

هناك الأشياء الجيدة ليقوله عن وجود مخرج واحد-نقطة, كما أن هناك أشياء سيئة يقول عن لا مفر منه "السهم" برمجة النتائج.

إن استخدام عدة نقاط الخروج أثناء التحقق من صحة المدخلات أو تخصيص الموارد ، أنا أحاول أن أضع كل 'خطأ-مخارج جدا واضح في الجزء العلوي من وظيفة.

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

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

int f(int y) {
    int value = -1;
    void *data = NULL;

    if (y < 0)
        goto clean;

    if ((data = malloc(123)) == NULL)
        goto clean;

    /* More code */

    value = 1;
clean:
   free(data);
   return value;
}

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

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

int g(int y) {
  value = 0;

  if ((value = g0(y, value)) == -1)
    return -1;

  if ((value = g1(y, value)) == -1)
    return -1;

  return g2(y, value);
}

اعتمادا على المشروع أو الترميز المبادئ التوجيهية الأكثر من المرجل لوحة رمز يمكن استبدال وحدات الماكرو.كملاحظة جانبية, كسر أسفل هذا الطريق يجعل وظائف g0 g1 ,g2 من السهل جدا أن اختبار على حدة.

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

باختصار ؛

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

تعرف القول المأثور - الجمال هو في عين الناظر.

بعض الناس أقسم NetBeans وبعض من قبل IntelliJ IDEA, بعض من قبل بيثون وبعض من قبل PHP.

في بعض المحلات التجارية يمكن أن تفقد عملك إذا كنت تصر على القيام بذلك:

public void hello()
{
   if (....)
   {
      ....
   }
}

السؤال هو كل شيء عن الرؤية والصيانة.

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

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

أتذكر قبل 20 عاما ، زميل لي أطلق توظيف اليوم ما يمكن أن يسمى التنمية رشيق استراتيجية.كان الدقيق تدريجي الخطة.ولكن مدير أعماله كان يصرخ في وجهه "لا يمكنك تدريجيا الإصدار الميزات للمستخدمين!يجب أن العصا مع شلال." رده على المدير أن التنمية المتزايدة سيكون أكثر دقة لاحتياجات العملاء.كان يؤمن النامية على احتياجات العملاء ، ولكن المدير يعتقد في الترميز إلى "متطلبات العملاء".

نحن في كثير من الأحيان بالذنب كسر البيانات التطبيع ، MVP و MVC الحدود.نحن مضمنة بدلا من بناء وظيفة.نأخذ اختصارات.

شخصيا, وأعتقد أن PHP هي الممارسة السيئة, ولكن ما أعرف.كل الحجج النظرية يتلخص في محاولة تحقيق مجموعة من القواعد

الجودة = الدقة الصيانة والربحية.

جميع القواعد الأخرى تتلاشى في الخلفية.وبالطبع هذه القاعدة يتلاشى أبدا:

الكسل هو فضيلة جيد مبرمج.

أميل نحو استخدام الحرس شروط للعودة في وقت مبكر وإلا الخروج في نهاية الأسلوب.واحد للدخول والخروج القاعدة لها أهمية تاريخية كانت مفيدة بشكل خاص عند التعامل مع التعليمات البرمجية القديمة التي هربت إلى 10 صفحات A4 واحد C++ الأسلوب مع العديد من عوائد (و العديد من العيوب).ومؤخرا قبول ممارسة جيدة للحفاظ على أساليب صغيرة مما يجعل مخارج متعددة أقل من مقاومة إلى الفهم.في ما يلي Kronoz سبيل المثال نسخ من فوق ، السؤال هو ما يحدث في //باقي كود...?:

void string fooBar(string s, int? i) {

  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

أدرك المثال إلى حد ما مفتعلة ولكن أود أن يميل إلى ريفاكتور foreach حلقة في LINQ البيان أنه يمكن النظر حارس شرط.مرة أخرى في المفتعلة سبيل المثال القصد من القانون ليس واضحا ، someFunction() قد يكون لها بعض الآثار الجانبية الأخرى أو قد تكون النتيجة المستخدمة في // باقي كود....

if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;

إعطاء التالية بتعميل الترميز وظيفة:

void string fooBar(string s, int? i) {

  if (string.IsNullOrEmpty(s) || i == null) return null;
  if (someFunction(s, i).Any(r => !r.Passed)) return null;

  // Rest of code...

  return ret;
}

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

وقد قلت ذلك, مرة واحدة كان العمل في المكتبة من حيث معايير الترميز فرض واحد العودة البيان في وظيفة', ووجدت أنها صعبة جدا.أنا أكتب الكثير من حسابات رقمية رمز و هناك في كثير من الأحيان هناك حالات خاصة ، لذلك رمز انتهى من الصعب جدا أن تتبع...

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

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

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

واحد نقطة الخروج - كل الأمور الأخرى متساوية يجعل التعليمات البرمجية بشكل ملحوظ أكثر قابلية للقراءة.ولكن هناك الصيد:شعبية البناء

resulttype res;
if if if...
return res;

هي وهمية ، "res=" ليس أفضل بكثير من "العودة".وقد وحيد عودة البيان عدة نقاط حيث وظيفة ينتهي في الواقع.

إذا كان لديك وظيفة متعددة يعود (أو "res="s), فإنه غالبا ما يكون فكرة جيدة إلى تقسيمه إلى عدة أصغر الوظائف مع واحد نقطة الخروج.

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

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

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

بيرل 6:مثالا سيئا

sub Int_to_String( Int i ){
  given( i ){
    when 0 { return "zero" }
    when 1 { return "one" }
    when 2 { return "two" }
    when 3 { return "three" }
    when 4 { return "four" }
    ...
    default { return undef }
  }
}

سيكون من الأفضل كتابة مثل هذا

بيرل 6:خير مثال

@Int_to_String = qw{
  zero
  one
  two
  three
  four
  ...
}
sub Int_to_String( Int i ){
  return undef if i < 0;
  return undef unless i < @Int_to_String.length;
  return @Int_to_String[i]
}

ملاحظة هذا هو مجرد مثال سريع

اصوت واحد في نهاية العودة كمبدأ توجيهي.هذا يساعد مدونة مشتركة تنظيف التعامل مع ...على سبيل المثال, نلقي نظرة على التعليمات البرمجية التالية ...

void ProcessMyFile (char *szFileName)
{
   FILE *fp = NULL;
   char *pbyBuffer = NULL:

   do {

      fp = fopen (szFileName, "r");

      if (NULL == fp) {

         break;
      }

      pbyBuffer = malloc (__SOME__SIZE___);

      if (NULL == pbyBuffer) {

         break;
      }

      /*** Do some processing with file ***/

   } while (0);

   if (pbyBuffer) {

      free (pbyBuffer);
   }

   if (fp) {

      fclose (fp);
   }
}

وربما هذا هو وجهة نظر غير, ولكن أعتقد أن أي شخص يعتقد أن عودة متعددة بيانات يفضل أبدا استخدام مصحح أخطاء على المعالج الذي يدعم فقط 4 أجهزة نقاط.;-)

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

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

ولكن لا يوجد شيء خاطئ مع واحد/العديد من عودة البيانات.في بعض اللغات ، وهو أفضل الممارسات (C++) من غيرها (ج).

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