- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Выразительный JavaScript - Марейн Хавербеке
Шрифт:
Интервал:
Закладка:
});
10. Модули
Начинающий программист пишет программы так, как муравьи строят муравейник – по кусочку, без размышления над общей структурой. Его программы как песок. Они могут недолго простоять, но вырастая, они разваливаются.
Поняв проблему, программист тратит много времени на размышления о структуре. Его программы получаются жёстко структурированными, как каменные изваяния. Они тверды, но когда их нужно менять, над ними приходится совершать насилие.
Мастер-программист знает, когда нужна структура, а когда нужно оставить вещи в простом виде. Его программы словно глина – твёрдые, но податливые.
Мастер Юан-Ма, «Книга программирования»У каждой программы есть структура. В частностях она определяется тем, как программист делит код на функции и блоки внутри этих функций. Программисты вольны в создании структуры своей программы. Структура определяется больше вкусом программиста, нежели функциональностью программы.
В случае больших программ отдельные функции уже теряются в коде, и нам необходима единица организации кода больших масштабов. Модули группируют программный код по каким-то определённым признакам. В этой главе мы рассмотрим преимущества такого деления и техники создания модулей в JavaScript.
Зачем нужны модули
Есть несколько причин, по которым авторы делят свои книги на главы и секции. Это помогает читателю понять, как построена книга, и найти нужные им части. Автору это помогает концентрироваться на каждой конкретной части. Преимущества организации программ в нескольких файлах, или модулях, примерно те же. Структуризация помогает незнакомым с кодом людям найти то, что им нужно, и помогает программистам хранить связанные друг с другом вещи в одном месте.
Некоторые программы организованы по модели обычного текста, где порядок следования чётко определён, и где читателю предлагается последовательное изучение программы и множество прозы (комментариев) для описания кода. Это делает чтение кода менее пугающим (а чтение чужого кода обычно пугает), но требует больших усилий при создании кода. Также такую программу сложнее менять, потому что части прозы связаны между собой сильнее, чем части кода. Этот стиль называется литературным программированием. Те главы книги, в которых обсуждаются проекты, можно считать литературным кодом.
Обычно структурирование чего-либо требует затрат энергии. На ранних стадиях проекта, когда вы ещё не уверены, что где будет, и какие модули вообще нужны, я пропагандирую бесструктурную минималистическую организацию кода. Просто размещайте все части там, где удобно, пока код не стабилизируется. Таким образом не придётся тратить время на перестановку кусков программы, и вы не поймаете себя в такую структуру, которая не подходит для вашей программы.
Пространство имён
У большинства современных ЯП есть промежуточные области видимости (ОВ) между глобальной (видно всем) и локальной (видно только этой функции). У JavaScript такого нет. По умолчанию, всё, что необходимо видеть снаружи функции верхнего уровня, находится в глобальной ОВ.
Загрязнение пространства имён (ПИ), когда не связанные друг с другом части кода делят один набор переменных, упоминалась в главе 4. Там объект Math был приведён в качестве примера объекта, который группирует функциональность, связанную с математикой, в виде модуля.
Хотя JavaScript не предлагает непосредственно конструкции для создания модуля, мы можем использовать объекты для создания подпространств имён, доступных отовсюду. А функции можно использовать для создания изолированных частных пространств имён внутри модуля. Чуть дальше мы обсудим способ построения достаточно удобных модулей, изолирующих ПИ при помощи базовых концепций языка.
Повторное использование
В проекте, не разбитом на модули, непонятно, какие части кода необходимы для конкретной функции. В моей программе, шпионящей за врагами (глава 9), я написал функцию чтения файлов с настройками. Если мне понадобится использовать её в другом проекте, я должен буду скопировать части старой программы, которые вроде бы связаны с этой функцией, в мой новый проект. А если я найду там ошибку, я её исправлю только в том проекте, над которым работаю в данный момент, и забуду исправить её во всех остальных.
Когда у вас будет множество таких сдублированных кусков кода, вы обнаружите, что тратите кучу времени и сил на их копирование и обновление. Если разместить связанные между собой части программ в отдельные модули, их будет проще отслеживать, исправлять и обновлять, потому что везде, где этот функционал потребуется, вы сможете просто загрузить этот модуль из файла.
Эту идею можно использовать ещё лучше, если чётко прописать взаимоотношения разных модулей – кто от кого зависит. Тогда можно автоматизировать процесс установки и обновления внешних модулей (библиотек).
Если ещё развить идею – представьте себе онлайн-сервис, который отслеживает и распространяет сотни тысяч таких библиотек, и вы можете искать нужную вам функциональность среди них, а когда найдёте – ваш проект автоматически скачает её.
И такой сервис есть! Он называется NPM (npmjs.org). NPM – онлайн-база модулей и инструмент для скачивания и апгрейда модулей, от которых зависит ваша программа. Он вырос из Node.js, окружения JavaScript, не требующего браузера, которое мы обсудим в главе 20, но также может использоваться и в браузерных программах.
Устранение связей (Decoupling)
Ещё одна задача модулей – изолировать несвязанные между собой части кода так, как это делают интерфейсы объектов. Хорошо продуманный модуль предоставляет интерфейс для его использования вовне. Когда модуль обновляют или исправляют, существующий интерфейс остаётся неизменным, чтобы другие модули могли использовать новую, обновлённую версию без изменений в них самих.
Стабильный интерфейс не означает, что в него не добавляют новые функции, методы или переменные. Главное, что существующая функциональность не удаляется и её смысл не меняется. Хороший интерфейс позволяет модулю расти, не ломая старый интерфейс. А это значит – выставлять наружу как можно меньше внутренней кухни модуля, при этом язык интерфейса должен быть достаточно гибким и мощным для применения в различных ситуациях.
Интерфейсы, выполняющие простую задачу, вроде чтения настроек из файла, выходят такими естественным образом. Для других – к примеру, для редактора текстов, у которого есть множество разных аспектов, требующих доступа извне (содержимое, стили, действия пользователя и т.п.) интерфейс необходимо скрупулёзно продумывать.
Использование функций в качестве пространств имён
Функции – единственная вещь в JavaScript, создающая новую область видимости. Если нам нужно, чтобы у модулей была своя область видимости, придётся основывать их на функциях.
Обратите внимание на простейший модуль, связывающий имена с номерами дней недели – как делает метод getDay объекта Date.
var names = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"];
function dayName(number) {
return names[number];
}
console.log(dayName(1));
// → Вторник
Функция dayName – часть интерфейса модуля, а переменная names – нет. Но хотелось бы не загрязнять глобальное пространство имён.
Можно сделать так:
var dayName = function() {
var names = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"];
return function(number) {
return names[number];
};
}();
console.log(dayName(3));
// → Четверг
Теперь names – локальная переменная безымянной функции. Функция создаётся и сразу вызывается, а её возвращаемое значение (уже нужная нам функция dayName) хранится в переменной. Мы можем написать много страниц кода в функции, объявить там сотню переменных, и все они будут внутренними для нашего модуля, а не для внешнего кода.
Подобный шаблон можно использовать для изолирования кода. Следующий модуль пишет в консоль значение, но не предоставляет никаких значений для использования другими модулями.
(function() {
function square(x) { return x * x; }
var hundred = 100;
console.log(square(hundred));
})();
// → 10000
Этот код выводит квадрат сотни, но в реальности это мог бы быть модуль, добавляющий метод к какому-то прототипу, или настраивающий виджет на веб-странице. Он обёрнут в функцию для предотвращения загрязнения глобальной ОВ используемыми им переменными.