مؤشرات فارغة في كل مكان لأن البيانات أصبحت متفرقة فجأة

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

سؤال

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

هناك أكثر من 100 سطر من التعليمات البرمجية مثل هذا:

functionDoSomething(foo, bar, getRoot().getChild("1").getChild("A").
    getChild("oo").getContent());

فيما عدا الآن، قد يُرجع getChild("A") قيمة فارغة.أو أي من أساليب getChild(xxx) قد تفعل ذلك.

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

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

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

أفكار؟

getChild () هي طريقة ملائمة في الواقع.إن أنظف طريقة أفكر بها هي أن تجعل الطرق الملائمة تُرجع كائنًا تابعًا صالحًا، ولكن تجعل getContent() الخاص بالطفل "الفارغ" يُرجع دائمًا "".

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

المحلول

ما وصفته (إرجاع كائن فرعي خاص) هو شكل من أشكال NullObject النمط، والذي ربما يكون الحل الأفضل هنا.

نصائح أخرى

يرجى التفكير في استخدام XPATH بدلاً من هذه الفوضى.

الحل هو استخدام ملف DTD لـ XML.إنه يتحقق من صحة ملف XML الخاص بك getChild("A") لن يعود فارغًا عندما يكون A إلزاميًا.

ماذا عن:

private Content getChildContent(Node root, String... path) {
    Node target = root;
    for ( String pathElement : path ) {
         Node child = target.getChild(pathElement);
         if ( child == null ) 
            return null; // or whatever you should do

         target = child;
    }

    return target.getContent();

}

لاستخدامها كما

functionDoSomething(foo, bar, getChildContent(root, "1", "A", "oo"));

يمكن أن تكون مشكلتك مشكلة في التصميم: قانون ديميتر.

إذا لم يكن الأمر كذلك، يمكنك استخدام شيء مثل نوع الخيار تغيير نوع الإرجاع لـ getChild إلى Option<Node>:

for(Node r : getRoot())
  for(Node c1 : r.getChild("1"))
    for(Node c2: c1.getChild("A"))
      return c2.getChild("oo")

يعمل هذا لأن الخيار ينفذ Iterable، وسيتم إحباطه عندما لا يتم تعريف قيمة الإرجاع.وهذا مشابه لـ Scala حيث يمكن التعبير عنه بمفردة للتعبير.

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


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

وبهذه الطريقة يمكنك تعديل الطريقة لتكون أكثر ذكاءً، بدلاً من تعديل كل سطر على حدة

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