سؤال

بالنظر إلى مقتطفات الكود التالية ، هل هناك أي فرق ملحوظ؟

public boolean foo(int input) {
   if(input > 10) {
       doStuff();
       return true;
   }
   if(input == 0) {
       doOtherStuff();
       return true;
   }

   return false;
}

ضد.

public boolean foo(int input) {
   if(input > 10) {
      doStuff();
      return true;
   } else if(input == 0) {
      doOtherStuff();
      return true;
   } else {
      return false;
   }
}

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

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

هل هناك أي اختلاف في الأداء الملموس؟ هل تشعر أن أحدهما يمكن صيانته/قابلاً للقراءة أكثر أو أقل من الآخرين؟

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

المحلول

مع المثال الثاني ، ذكرت بوضوح شديد أن كلا الشرطين حصريين بشكل متبادل.
مع الأول ، ليس من الواضح جدًا ، وفي الحدث (غير المحتمل) input يضاف بين كل من IFS ، وسيتغير المنطق.
افترض أن شخصًا ما في المستقبل يضيف input = 0 قبل الثانية إذا.
بالطبع ، من غير المرجح أن يحدث هذا ، ولكن إذا كنا نتحدث عن القدرة على الصيانة هنا ، إذا كان Else يقول بوضوح أن هناك ظروفًا حصرية متبادلة ، في حين أن مجموعة من IFs لا تفعل ذلك ، وهم لا يعتمدون على بعضهم البعض كما لو -الكتل.

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

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

نصائح أخرى

استخدم أي شكل يصف أفضل ما لديك.

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

  • في الاول:

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

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

    إذا كان كل الرمز الذي نكتبه ضمن if حيثما طول 10 خطوط على الأكثر ، لن يكون هذا مهمًا حقًا ، ولكن لسوء الحظ ، هذا ليس هو الحال ، فهناك مبرمجون آخرون يظنون أنه إذا كان يجب أن يكون الجسم أكثر من 200 خط ... على أي حال.

  • لا أحب الثالث ، فهو يجبرني على البحث عن متغير الإرجاع ، ومن الأسهل العثور على return الكلمة الرئيسية

حول أداء السرعة ، فهي متطابقة (تقريبًا). لا تقلق بشأن ذلك.

في مثالك الأخير ، لا تفعل هذا:

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

لكن هذا (لاحظ استخدام جافا نهائي):

public boolean foo(int input) {
   final boolean toBeReturned;    // no init here
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   } else {
      toBeReturned = false;
   }
   return toBeReturned;
}

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

بهذه الطريقة أنت بالتأكيد لا تنسى تهيئة قيمة الإرجاع الخاصة بك. هذا رائع إذا قررت لاحقًا أنه بعد كل ما تحتاج إلى حالة أخرى.

أفعل ذلك طوال الوقت وحتى Moreso منذ أن بدأت في استخدام Idea Intellij (الإصدار 4 أو نحو ذلك ، منذ وقت طويل) وقد أنقذني هذا الكثير من أخطاء الهاء السخيفة ...

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

خلاف ذلك ، إذا كان "الإلمام" هو اسم اللعبة ، فأنا أكتب:

public boolean foo(int a) {
  return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false; 
}

حيث كلاهما افعل اشياء و دوثستوف سوف يعود صحيح.

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

قد يكون الإصدار رقم 1 و #2 أسرع من رقم 3 ، لكنني أفترض أن فرق الأداء ضئيل. أفضل التركيز على مقروئية.

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

فكر في هذه الحالة عندما لن يكون المثالان متشابهان:

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        }
        System.out.println("do some other intermediary stuff");
        if (input == 0) {
            // doOtherStuff();
            return true;
        }

        return false;
    }

ضد.

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        } 
        //System.out.println("doing some intermediary stuff... doesn't work");
        else if (input == 0) {
            // doOtherStuff();
            return true;
        } else {
            return false;
        }
        return false;
    }

النهج الأول ربما أكثر مرونة, ، ولكن الاثنين الصيغ استخدامها في ظروف مختلفة.

فيما يتعلق بالأداء ، أعتقد أن الاختلافات هي الصغيرة التي يجب أخذها في الاعتبار ، لأي تطبيق Java منتظم ، مشفر من قبل المبرمجين Sane :).

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

بمعنى آخر ، هناك حالات يكون فيها الفرق بين If-Else-If و If-If يهم ، لكن هذا ليس واحدًا منها.

مثال: جرب هذا ثم جربه بعد إزالة آخر. تحصل على مخرجين مختلفين:

int someNumber = 1;
if(someNumber < 5)
{
    someNumber += 5;
    Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
    Console.WriteLine("Second call.");
}

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

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