Записки на лету

Организация скриптов на форме

Все начинается с малого, как и скрипты на форме сущности, сначала одна функция, затем еще одна и т.д.

На одном проекте, я помню, дошло до того, что общий размер файлов скриптов пошел на мегабайты и количество функций перевалило за сотню. Все это находилось в разных файлах и писалось разными людьми и в результате всего этого так называемого «Спагетти кода» полезли ошибки, появлялись функции и переменные с одинаковыми именами и т.д.

В общем, хаос рос с объемом кода. 🙂

Чтобы решить эту проблему я задумался, какой же способ организации скриптов, называя более умными словами — паттерн, применить.

Сначала пришла мысль взять так называемый Неймспейс паттерн (Namespace Pattern), который используется, можно сказать, у нас прямо под носом, в примерах SDK.

Выглядит он так:

if (typeof (MYCODE) == "undefined")
{ MYCODE = { __namespace: true }; }
MYCODE.QuoteFormEvents = {
    //Приватные функции
    _doSomethingPrivate: function (param) {

    },
    //Публичные функции
    doSomethingPublic: function (param) {

    },
    __namespace: true
};

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

Для меня ответ пришел, когда я начал разрабатывать приложения для Windows 8 на HTML5 и JScript, а именно начал разбираться, как там принято писать на JScript. Естественно, в этих приложениях очень много скриптов, и также среда исполнения накладывает некоторые ограничения. Так вот, организованы они там по паттерну раскрывающийся модуль, мой вольный перевод — Revealing Module Pattern.

Немного переделанный для использования в CRM он выглядит так:

var QuoteFormEvents = function () {
    //Переменные
    var tempString = "";
    var userId = Xrm.Page.context.getUserId();

    //Функции
    function doSomething() {

    }

    function formOnLoad() {
        doSomething();
    }
    //Объявления
    return {
        UserId: userId,
        FormOnLoad: formOnLoad
    };
}();

Здесь также есть объекты, которые олицетворяют пространство имен, но суть в том, что мы весь наш код запихиваем в самовызывающуюся функцию, т.к. область видимости в JS определяется именно функцией. Внутри этой функции друг другу видны и переменные, и функции, а в конце мы объявляем только те функции и переменные, которые будут публичными, все остальное снаружи не видно.

Если Вы собираетесь написать что-то вроде библиотеки, которая будет использоваться в нескольких местах и для которой понадобится возможность переопределения функций, я бы предложил паттерн раскрывающийся прототип (Revealing Prototype Pattern) как более подходящий.

Про Revealing Module Pattern подробнее здесь: Revealing Module Pattern: Structuring JavaScript Code – Part III

Про Revealing Prototype Pattern подробнее здесь: Revealing Prototype Pattern: Structuring JavaScript Code – Part IV

 

 
Comments