سؤال

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

أرى الكثير من الناس الذين يؤدون الاستثناءات مثل:

throw new RuntimeException('MyObject is not an array')

أو تمديد الافتراضي استثناءات مع العرف الاستثناءات التي لا تفعل الكثير ولكن تغيير الاسم من الاستثناء:

throw new WrongTypeException('MyObject is not an array')

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

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

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

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

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

أود التعليق على هذه الفكرة ، وأفضل الممارسات ثابتة ومرنة رسالة الاستثناء الإطار.

/**
* @package MyExceptions
* MyWrongTypeException occurs when an object or 
* datastructure is of the incorrect datatype.
* Program defensively!
* @param $objectName string name of object, eg "\$myObject"
* @param $object object object of the wrong type
* @param $expect string expected type of object eg 'integer'
* @param $message any additional human readable info.
* @param $code error code.
* @return Informative exception error message.
* @author secoif
*/
class MyWrongTypeException extends RuntimeException {
    public function __construct($objectName, $object, $expected, $message = '', $code = 0) {
        $receivedType = gettype($object) 
        $message = "Wrong Type: $objectName. Expected $expected, received $receivedType";
        debug_dump($message, $object);
        return parent::__construct($message, $code);
    }
}

....

/**
 * If we are in debug mode, append the var_dump of $object to $message
 */
function debug_dump(&$message, &$object) {
     if (App::get_mode() == 'debug') {
         ob_start();
         var_dump($object);
         $message = $message . "Debug Info: " . ob_get_clean();
    }
}

ثم استخدامها مثل:

// Hypothetical, supposed to return an array of user objects
$users = get_users(); // but instead returns the string 'bad'
// Ideally the $users model object would provide a validate() but for the sake
// of the example
if (is_array($users)) {
  throw new MyWrongTypeException('$users', $users, 'array')
  // returns 
  //"Wrong Type: $users. Expected array, received string
}

ونحن قد تفعل شيئا مثل nl2br في العرف استثناء معالج لجعل أشياء لطيفة عن إخراج html.

تم قراءة:http://msdn.microsoft.com/en-us/library/cc511859.aspx#

ولم يذكر أي شيء من هذا القبيل, لذلك ربما انها فكرة سيئة...

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

المحلول

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

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

  1. توليد سلسلة نصية إلى مكان في الاستثناء
  2. تولد كل استثناء الرسالة

ما هو مطلوب.

النهج 1 هو أكثر وضوحا ، ولكن قد يؤدي إلى أكثر من ذلك بقليل مطول الاستخدام ، 2 هو عكس ذلك ، تداول terser جملة أقل وضوح.

علما بأن الوظائف يجب أن تكون آمنة للغاية (كان يجب ألا يسبب لها استثناء أنفسهم) و لا قوة توفير البيانات التي يتم اختياري في بعض معقول الاستخدامات.

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

تتبع مكدس في الدنيا يعطيك وظيفة ، وربما رقم السطر ، وبالتالي يجب التركيز على توفير المعلومات التي ليس من السهل العمل للخروج من هذا.

نصائح أخرى

لن ينتقص من المشورة فيما يتعلق كرزيستوف بلوق, ولكن هنا هو ميت-طريقة سهلة لإنشاء مخصص استثناءات.

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

<?php
   require_once "CustomException.php";
   class SqlProxyException extends CustomException {}

   throw new SqlProxyException($errorMsg, mysql_errno());     
?>

رمز وراء ذلك (التي اقترضت في مكان ما اعتذر لمن كان)

<?php

interface IException
{
    /* Protected methods inherited from Exception class */
    public function getMessage();                 // Exception message
    public function getCode();                    // User-defined Exception code
    public function getFile();                    // Source filename
    public function getLine();                    // Source line
    public function getTrace();                   // An array of the backtrace()
    public function getTraceAsString();           // Formated string of trace

    /* Overrideable methods inherited from Exception class */
    public function __toString();                 // formated string for display
    public function __construct($message = null, $code = 0);
}

abstract class CustomException extends Exception implements IException
{
    protected $message = 'Unknown exception';     // Exception message
    private   $string;                            // Unknown
    protected $code    = 0;                       // User-defined exception code
    protected $file;                              // Source filename of exception
    protected $line;                              // Source line of exception
    private   $trace;                             // Unknown

    public function __construct($message = null, $code = 0)
    {
        if (!$message) {
            throw new $this('Unknown '. get_class($this));
        }
        parent::__construct($message, $code);
    }

    public function __toString()
    {
        return get_class($this) . " '{$this->message}' in {$this->file}({$this->line})\n"
                                . "{$this->getTraceAsString()}";
    }
}

انظر كيفية تصميم استثناء الهرمية على بلوق من كرزيستوف Cwalina, والمؤلف المشارك "إطار المبادئ التوجيهية تصميم".

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

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

هذا التفكير يعني الطريقة التي يمكنك جمع المعلومات وتسجيل ذلك ، وهو ما يعني ضمنا باستخدام var_dump() في مكان ما.

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

ومع ذلك الكثير من التفاصيل يمكنك إضافة تأكد إما

  • تجعل من السهل قص ولصق كل شيء ، أو
  • زر تقرير الخطأ بالنسبة لهم
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top