التعامل مع الأخطاء والتعليقات عند إجراء العمليات السائبة في بنية متعددة المستويات

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

سؤال

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

Set<Person> selectedPeople = ... // fetch list of people
for ( Person person : selectedPeople ) {
    String lotteryNumber = callLotteryNumberWebService( person );
    // ...
}

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

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

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

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

المحلول

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

  • قائمة الأخطاء وكائنات المجال المتأثرة. قد يكون كائن المجال الأساسي أو أي شيء به معرف مستمر مفيدًا لإعادة الاستخدام. مثل مجموعة من الأخطاء التي تشير إلى كائنات المجال.
  • يمكنك حقن (AOP ، DI) في كائن الشخص نوعًا من كائن/رسالة الخطأ. على سبيل المثال (شخص. أخطاء) {...}
  • يمكنك لف مجموعة الأشخاص في رسالة برأس وجسم ومعلومات خطأ
  • يمكن أن تتضمن جميع كائنات المجال مجموعة خطأ يمكن الوصول إليها عبر واجهة ؛ أو يدعم الشخص واجهة ihaserrors. يمكنك جعل هذا العام واستخدام كائن خطأ أساسي يدعم التحذيرات والتحقق من صحة وجميع أنواع الأشياء.

إذا كنت في نظام حقيقي متعدد المستويات (بدلاً من الطبقات) ، فقد يكون لديك بنية قائمة على الرسائل يمكن أن تستوعب بسهولة نوعًا من آلية الخطأ/التحذير/التحقق من الصحة. أنظمة SOA/AJAX تضفي على هذا.

يسعدني أن تخوض أعمق قليلاً إذا كان لديك بعض الأسئلة المحددة.

نصائح أخرى

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

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

إنها مشكلة شائعة ، أولاً بعض الخلفية حول نهج المعاملات الذي تحاول حاليًا:

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

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

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

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

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

ملخص:

  • لقد تجاوزت مشكلتك مفهوم المعاملة -> ابحث عن تعويض سير العمل.

حظا طيبا وفقك الله -

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

أعتقد أنك تتفوق على الاستثناءات إذا كنت تفكر في هذه الشروط!

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

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

من الناحية المثالية ، يجب أن تكون مكالمة خدمة الويب الخاصة بك هكذا.

List<Person> selectedPeople = ... //fetch list of people
callLotteryNumberWebService(selectedPeople.ToArray );

إن إجراء مكالمة خدمة ويب لكل شخص مكلف. في نهاية الخادم ، تحتاج إلى التكرار على القائمة وتنفيذ العملية. يمكن أن يرمي الرمز الجانبي لخادم 2 استثناءات: BulkOperationFailedException - إذا كان هناك خطأ فادح بسبب DB Down أو Config File مفقود. مزيد من المعالجة غير ممكنة. BulkoperationException - هذا يحتوي على مجموعة من الاستثناءات المتعلقة بالشخص. يمكنك استمرار بعض الهوية للإشارة بشكل فريد إلى كل كائن. سيكون الرمز الخاص بك هكذا:

List<Person> selectedPeople = ... // fetch list of people 

try{
    callLotteryNumberWebService(selectedPeople.ToArray);
}catch  (BulkOperationFailedException e) {
    SOP("Some config file missing/db down.No person records processed")
}catch(BulkOperationException e)  {
    UserDefinedExceptions us =  e.getExceptions()
    foreach(exception ein us)   {
        // read unique id to find which person object failed
    }
}

construct msg based on which personobject succeeded and which failed

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

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

من المحتمل أن أعيد خريطة نتيجة النوع Map<Person,Future<String>> من وجهة نظري getLotteryNumbers<Collection<Person>> الخدمات.

سأقوم بعد ذلك بالتكرار من خلال الخريطة وأستخدم Future.get() للحصول على رقم اليانصيب أو الاستثناء.

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

في هذا السيناريو أعيد أ Future<Thing> الذي ينتظر أن تكون نتائج الدُفعات متاحة باستخدام أ CountdownLatch.

ألقِ نظرة على تزامن Java في الممارسة العملية لمعرفة كيف يمكن لهذه المكونات أن تعمل جميعًا معًا http://jcip.net/

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

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