Это хорошая практика, чтобы сделать дополнительные проверки в коде только для внутреннего использования? - PullRequest
0 голосов
/ 09 апреля 2011

Есть ли смысл проверять все аргументы и другие условия в коде, если я знаю, что я никогда не передаю неправильный аргумент, и он должен работать нормально (скажем, я уже сделал некоторые проверки вне этого кода).

Пример:

этот код:

/**
 * Applies function to all elements of array in specified
 * context.
 * If array is empty, returns null.
 */
MyNameSpace.foreach = function(arr, callback, context) {
   if (!(arr instanceof Array)) {
       throw new Error('first argument is not an array');
   }
   if (typeof callback !== 'function') {
       throw new Error('callback is not a function');
   }
   if (typeof arr.length === 'undefined') {
      throw new Error('Length undefined');
   }

   var con = typeof context === 'object' ? context : window;

   var i = arr.length;
   if ( i <= 0 ) {
       return null;
   }

   for ( j = 0; j < i; j++ ) {
        callback.call(con, j, arr[j]);
   }
}

может быть:

MyNameSpace.foreach = function(arr, callback, context) {
   var con = typeof context === 'object' ? context : window;

   var i = arr.length;
   if ( i <= 0 ) {
       return null;
   }

   for ( j = 0; j < i; j++ ) {
        callback.call(con, j, arr[j]);
   }
}

Ответы [ 4 ]

3 голосов
/ 09 апреля 2011

Абсолютно это может быть хорошей практикой.Это может помочь стабильности вашего приложения и помочь с отладкой.Недостатком является то, что он может загромождать код (затрудняя его чтение) и может влиять на производительность (хотя для большинства приложений JavaScript производительность не будет критичной).вид в каждом конкретном случае.Это действительно зависит от (1) вероятности того, что параметры будут неверными, и (2) насколько большой ущерб он нанесет, если они есть.

1 голос
/ 09 апреля 2011

Хотя это может немного замедлить выполнение, если вы оставите его включенным в производственной среде, вы можете использовать библиотеку проверки типов, как в производственной, так и во время отладки:

function TypeEnforce (func, ctx, config) {
    if (!(this instanceof TypeEnforce)) {
        return new TypeEnforce(func, ctx);
    }
    if (typeof func === 'string' && ctx) {
        this.funcString = func;
        func = ctx[func];
    }
    this.ctx = ctx;
    this.autoset = config && config.autoset;
    this.oldFunc = func;
}
TypeEnforce.prototype.argTypes = function (args) {
    var that = this;
    this.reqArgTypesFunc = function () {
        for (var i=0, argl = args.length; i < argl; i++) {
            if (
                (args[i] === 'Array' && Object.prototype.toString.call(arguments[i]) !== '[object Array]') ||
                (args[i] !== 'Array' && typeof arguments[i] !== args[i])
            ) {
                throw 'Argument ' + i + ' [' + arguments[i] + '] should be of type ' + args[i];
            }
        }
        that.oldFunc.apply(that.ctx, arguments);
    };
    if (this.autoset) {
        this.ctx[this.funcString] = this.reqArgTypesFunc;
    }
    return this;
};
TypeEnforce.prototype.props = function (props) {
    var that = this;
    this.reqPropsFunc = function () { 
        for (var p in props) {
            if (typeof arguments[p][props[p]] === 'undefined') {
                throw 'The property "' + props[p] + '" of argument no. ' + p + 
                        ' [' + arguments[p] + '] should not be undefined';
            }
        }
        var method = that.reqArgTypesFunc || that.oldFunc;
        method.apply(that.ctx, arguments);
    };
    if (this.autoset) {
        this.ctx[this.funcString] = this.reqPropsFunc;
    }
    return this;
};
TypeEnforce.prototype.get = function (props) {
    return this.reqPropsFunc || this.reqArgTypesFunc || this.oldFunc;
};

... который в вашем случае вы можете использовать следующим образом:

if (!MyNameSpace) {
    var MyNameSpace = {};
}
MyNameSpace.foreach = function(arr, callback, context) {
   var con = typeof context === 'object' ? context : window;

   var i = arr.length;
   if ( i <= 0 ) {
       return null;
   }

   for ( j = 0; j < i; j++ ) {
        callback.call(con, j, arr[j]);
   }
};

TypeEnforce('foreach', MyNameSpace, {autoset:true}).
    argTypes(['Array', 'function']).
    props({0:'length'});

MyNameSpace.foreach(['a', 'b'], function (k, v) {
    alert(k+':'+v);
});

При таком подходе вы можете выделить уродливый код проверки типа и даже отключить его, если он понадобится вам только во время тестирования. Вы также можете добавить методы для проверки аргумента или значения свойства.

1 голос
/ 09 апреля 2011

Это определенно хорошая практика, поскольку любой код, использующий ваш класс или функцию, может неосознанно передавать вам значения, которые могут привести к сбою кода.
Например: программист однажды случайно отправил нулевой указатель на мой код, который должен былсделать глубокую копию объекта, на который указатель указал.
Но так как я клонировал указатель на экземпляр в списке инициализации конструктора копирования, никто не мог понять, почему произошел сбой программы.
Программист сказал, что я долженМы сохранили проверку на NULL-указатель, но в итоге мы решили сохранить проверку на его конце, так как нам нужно было сохранить эффективность копирования через список инициализации, что было быстрее.

Таким образом, вы можете принять решение о размещении чеков в зависимости от:
1. Эффективности использования списка инициализации copy-ctor.
2. Насколько хорошо вы задокументировали входные параметры и ограничения ваших функций/classes.
3. Может ли ваш код вызвать сбой / вызвать проблемы с безопасностью из-за вредоносного ввода
4. Какой тип обработки исключений вам необходим для вашего программного обеспечения.

1 голос
/ 09 апреля 2011

Общий принцип в программном обеспечении, когда дело доходит до тестирования входов и выходов: «Будьте гибкими на входах, строгими на выходах». У вас всегда должны быть дополнительные проверки ваших входных данных, чтобы ваш код не сломался, если ваш метод получил что-то, чего он не ожидал.

...