هل يجب أن أتجنب استخدام بيانات تسمية Java؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

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

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

المحلول

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

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

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

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

نصائح أخرى

التسميات تشبه goto:استخدمها بشكل مقتصد، وفقط عندما تجعل التعليمات البرمجية الخاصة بك أسرع و والأهم من ذلك، أكثر قابلية للفهم،

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

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

عندما يتم إساءة استخدام التصنيفات (وgoto's)، فإنها تجعل التعليمات البرمجية أقل قابلية للقراءة، مما يسبب الحزن لك وللمطور التالي.المترجم لا يهتم.

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

بالمناسبة:هذا يجمع ويعمل.

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}

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

تعتبر التسميات قياسية جدًا عندما يكون لديك حلقات متداخلة.الطريقة الوحيدة لتقليل إمكانية القراءة حقًا هي عندما لا يراها مطور آخر من قبل ولا يفهم ما يقصدونه.

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

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

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

سأجادل لصالحهم في بعض المواقع، وقد وجدتهم مفيدًا بشكل خاص في هذا المثال:


nextItem: for(CartItem item : user.getCart()) {

  nextCondition : for(PurchaseCondition cond : item.getConditions()) {
     if(!cond.check())
        continue nextItem;
     else
        continue nextCondition;

  }
  purchasedItems.add(item);
}

أعتقد أنه مع حلقة for-each الجديدة، يمكن أن تكون التسمية واضحة حقًا.

على سبيل المثال:

sentence: for(Sentence sentence: paragraph) {
  for(String word: sentence) {
    // do something
    if(isDone()) {
      continue sentence;
    }
  }
}

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

لقد استخدمت حلقة Java المسماة لتنفيذ طريقة Sieve للعثور على الأعداد الأولية (تم إجراؤها لإحدى مشاكل الرياضيات في مشروع Euler) مما جعلها أسرع بـ 10x مقارنة بالحلقات المتداخلة.على سبيل المثال، إذا (حالة معينة) العودة إلى الحلقة الخارجية.

private static void testByFactoring() {
    primes: for (int ctr = 0; ctr < m_toFactor.length; ctr++) {
        int toTest = m_toFactor[ctr];
        for (int ctr2 = 0; ctr2 < m_divisors.length; ctr2++) {
            // max (int) Math.sqrt(m_numberToTest) + 1 iterations
            if (toTest != m_divisors[ctr2]
                        && toTest % m_divisors[ctr2] == 0) {
                continue primes; 
            }
        } // end of the divisor loop
    } // end of primes loop
} // method

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

لذا فإن لها استخداماتها، ويعتمد ذلك على المشكلة التي كنت تحاول حلها.

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

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

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

تعد التصنيفات الشخصية إحدى تلك الميزات التي لا معنى لها كثيرًا بالنسبة لي، خارج لغة التجميع أو لغة BASIC وغيرها من اللغات المحدودة المماثلة.تحتوي Java على الكثير من بنيات التحكم والحلقة التقليدية/العادية.

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

@Test
public void should_Clear_Cached_Element() throws Exception {
    given: {
        elementStream = defaultStream();
        elementStream.readElement();
        Assume.assumeNotNull(elementStream.lastRead());
    }
    when:
        elementStream.clearLast();
    then:
        assertThat(elementStream.lastRead()).isEmpty();
}

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

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