Организация кода в приложениях Large AngularJS и JavaScript
Многие разработчики борются с тем, как организовать код приложения когда он растет по размеру. Я видел это недавно в AngularJS и JavaScript, но исторически это была проблема все технологии, включая множество приложений Java и Flex, над которыми я работал прошлое.
Общая тенденция - одержимость организацией вещей по типу. Это имеет поразительное сходство с тем, как люди организуют свои одежда.
Сваи на полу
Посмотрим на angular -seed, официальную отправную точку для Приложения AngularJS. Каталог "app" содержит следующую структуру:
css/img/js/app.js controllers.js directives.js filters.js services.js lib/partials/Каталог JavaScript имеет один файл для каждый тип объекта, который мы пишем. Это очень похоже на организацию вашего одежду в разные сваи на полу. У вас есть куча носков, нижнее белье, рубашки, брюки и т.д. Вы знаете, что ваши носки из черной шерсти находятся в что куча в углу, но это займет некоторое время, чтобы выкопать их из.
Это беспорядок. Люди не должны так жить, а разработчики не должен выглядеть так. Когда вы выйдете за полдюжины или около того контроллеры или службы, эти файлы становятся громоздкими: объекты, которые вы найти трудно найти, файловые изменения в исходном управлении становятся непрозрачный и т.д.
Ящик для носка
Следующий логический проход при организации JavaScript включает создание каталог для некоторых архетипов и разделение объектов в их собственные файлы. Чтобы продолжить метафору одежды, мы теперь инвестировали в симпатичный кофейник-мохагони и планируйте положить носки в один ящик, нижнее белье в другой, и аккуратно складывать наши брюки и рубашки в других.
Предположим, что мы создаем простой сайт электронной коммерции с логином поток, каталог продуктов и пользовательский интерфейс корзины покупок. Мы также определили новые архетипы для моделей (бизнес-логика и состояние) и сервисы (прокси к конечным точкам HTTP/JSON), а не привязывать их к Angular одиночному "служебный" архетип. Теперь наш каталог JavaScript выглядит следующим образом:
контроллеры/LoginController.js RegistrationController.js ProductDetailController.js SearchResultsController.js directives.js filters.js модели /CartModel.js ProductModel.js SearchResultsModel.js Сервисы UserModel.js/CartService.js UserService.js ProductService.js Ницца! Теперь объекты можно легко найти, просмотрев файлное дерево или используя ярлыки IDE, изменения в управлении источником теперь четко указывают что было изменено и т.д. Это значительное улучшение, но все еще страдает от некоторых ограничений.
Представьте, что вы находитесь в офисе и понимаете, что вам нужно несколько нарядов уборка по утрам для деловой поездки завтра утром. Вы звоните домой и попросите вашего значительного другого взять черный уголь и синий полоска подходит для чистящих средств. И не забывайте, что серая рубашка с черный пейсли-галстук и белая рубашка с твердым желтым галстуком. Представьте себе, что ваш значительный другой человек совершенно не знаком с ваш комод и шкаф. Когда они просеивают ваш ящик для галстуков, они см. три желтые связи. Какой из них выбрать?
Было бы неплохо, если бы ваша одежда была организована снаряжением? В то время как существуют практические ограничения, такие как стоимость и пространство, которые делают это трудно с одеждой в реальном мире, что-то подобное может быть с кодом с нулевой стоимостью.
Модульность
Надеюсь, банальные метафоры не слишком утомительны, но здесь резюме:
Ваш существенный другой - новый разработчик в команде, которая была попросил исправить ошибку на одном из многих экранов вашего приложения. разработчик просачивается через структуру каталогов и видит все контроллеров, моделей и сервисов. К сожалению, это ничего не говорит о том, какие объекты связаны или имеют зависимости друг от друга. Если в какой-то момент разработчик хочет повторно использовать часть кода, им необходимо собирать файлы из кучи разные папки и всегда будут забывать код из другой папки где-нибудь еще. Верьте или нет, вам редко приходится повторно использовать все контроллеров из приложения электронной коммерции в новом приложении для отчетов вы строите. Тем не менее, вы можете повторно использовать некоторые из логики аутентификации. Было бы неплохо, если бы все было в одном место? Позвольте реорганизовать приложение на основе функциональных областей:
cart/CartModel.js CartService.js common/directives.js filters.js product/search/SearchResultsController.js SearchResultsModel.js ProductDetailController.js ProductModel.js Пользователь продукта ProductService.js/ LoginController.js RegistrationController.js UserModel.js UserService.js Любой случайный разработчик теперь может открыть папку верхнего уровня и немедленно получить представление о том, что делает приложение. Объекты в той же папке есть отношения, а у некоторых будут зависимости на других. Понимание процесса регистрации и регистрации так же просто, как просмотр файлов в этой папке. Примитивное повторное использование через copy/paste можно, по крайней мере, выполнить, скопировав папку в другой проект.
С помощью AngularJS мы можем сделать этот шаг дальше и создать модуль этот связанный код:
1 2 3 4 5 6 7 8 9 10 11 12 13 var userModule = angular.module( 'userModule', []); userModule.factory( 'UserService', ['$ http', function ($ http) {вернуть новый UserService ($ http); }]);
userModule.factory('userModel', ['userService', function (userService) {вернуть новый UserModel (userService); }]);
userModule.controller('loginController', ['$ scope', 'userModel', LoginController]); userModule.controller( 'registrationController', ['$ scope', 'userModel', RegistrationController]); Посмотреть rawUserModule.js, размещенный с помощью ❤ от GitHub. Если мы затем разместим UserModule.js в пользовательскую папку становится "манифестом" объекты, используемые в этом модуле. Это также было бы разумным местом для добавьте некоторые директивы загрузчика для RequireJS или Browserify.
Советы для общего кода
Каждое приложение имеет общий код, который используется многими модулями. Мы просто нужно место для него, которое может быть папкой с именем "common" или "разделял" или как угодно. В действительно больших приложениях чтобы быть много перекрытия функциональности и сквозных проблем. Это можно сделать управляемым с помощью нескольких методов:
Если объекты вашего модуля требуют прямого доступа к нескольким "общим", объекты, напишите один или несколько Фасадов для них. Это может помочь уменьшить количество соавторов для каждого объекта, поскольку у них слишком много Коллабораторы обычно представляют собой запах кода. Если ваш "общий" модуль становится большим, подразделяют его на подмодули, которые обращаются к определенному функциональной области или проблемы. Убедитесь, что ваши прикладные модули используют только "общие" модули, в которых они нуждаются. Это вариант "Интерфейса принцип сегрегации" от SOLID. Добавить методы утилиты на $rootScope поэтому они могут использоваться дочерними областями. Это может помочь предотвратить подключите одну и ту же зависимость (например, "PermissionsModel" ) к каждой контроллер в приложении. Обратите внимание, что это следует делать экономно во избежание загромождения глобального масштаба и создания зависимостей не очевидно. Используйте события для развязки двух компонентов, которые не требуют явная ссылка друг на друга. AngularJS делает это возможным с помощью методов $emit, $broadcast и $on объекта Scope. контроллер может запустить событие для выполнения какого-либо действия, а затем получить уведомление о завершении действия. Быстрая заметка об активах и тестах
Я думаю, что есть больше возможностей для гибкости в отношении организации HTML, CSS и изображения. Размещение их в подпапке "активы" модуль, вероятно, наилучший баланс между инкапсулированием зависимостей между модульными активами, а не слишком много затуманивания. Однако я думаю, что отдельная папка верхнего уровня для этого контента, которая содержит структуру папок, которая отражает структуру пакета приложения также является разумным. Я думаю, что это хорошо работает и для тестов.