سؤال

لدي معالج الأحداث في فئة الحدود التي تدير آلية الثبات لمعاملة عامة معينة:

void MyBoundaryClass::MyEventHandler(...)
{
  //retrieve stuff from the UI
  //...
  //declare and initialize trasaction to persist
  SimpleTransaction myTransaction(.../*pass down stuff*/);
  //do some other checks
  //...
  //declare transaction persistor
  TransactionPersistor myPersistor(myTransaction, .../*pass down connection to DB and other stuff*/);
  //persist transaction
  try
  {
    myPersistor.Persist();
  }
  catch(...)
  {
    //handle errors
  }
}

هل سيكون من الأفضل أن يكون لديك نوع من TransactionManager لتغليف كائنات SimpleTransaction وTransactionPersistor؟

هل هناك أي قاعدة أساسية مفيدة لفهم ما إذا كنت بحاجة إلى مستوى إضافي من التغليف؟

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

أي رأي؟

هتافات

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

المحلول

معتبرا أن:

  • ال مفهوم التغليف يتعلق الأمر بتعريف الحاوية، و
  • يعتمد التصميم الموجه للكائنات على مفهوم تمرير الرسائل (استدعاء الأساليب)

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

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

وإلا فمن المحتمل أن تكون مبالغة.

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

في حالتك، إذا كنت تريد اختبار المعاملة، فيجب عليك بالفعل اختبار MyEventHandler of MyBoundaryClass، من أجل استرداد البيانات من واجهة المستخدم.

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

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

لأنه يمكن القول بذلك يعد الاقتران والتماسك ركنين أساسيين في برمجة OO, ، يمكن تقييم تماسك فئة جديدة مثل TransactionManager من حيث مجموعة الإجراءات التي ستنفذها.

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

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

على سبيل المثال، أحد الجوانب المثيرة للاهتمام في TransactionManager هو تغليف مفهوم المعاملة بالكامل، والذي من شأنه:

  • تصبح غير معروفة فعليًا من قبل بقية النظام، وسوف تقلل من الاقتران بين الفئات الأخرى و"المعاملة"
  • تعزيز تماسك TransactionManager من خلال تركيز واجهة برمجة التطبيقات (API) الخاصة به حول خطوات المعاملة (مثل initTransaction()، وpersistTransaction()، ...)، وتجنب أي getter أو setter لأي مثيل للمعاملة.

نصائح أخرى

تفصيلًا لاقتراح VonC، ضع في اعتبارك الإرشادات التالية:

  • إذا كنت تتوقع استدعاء نفس الوظائف في مكان آخر، بنفس الطريقة، فمن المعقول تغليفها في كائن جديد.

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

تعتبر نقطة VonC حول واجهة برمجة التطبيقات بمثابة اختبار ممتاز:خلق فعالة واجهات, ، و ال أشياء غالبا ما تصبح واضحة.

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

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

بالنسبة لك القضية, ، أود أن ألخص فكرتك عن "TransactionManager".بهذه الطريقة سيتعامل "TransactionManager" مع كيفية عمل المعاملة وليس "MyBoundaryClass".

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