【问题标题】:Large AngularJS application design大型 AngularJS 应用程序设计
【发布时间】:2014-09-16 17:17:39
【问题描述】:

我需要有关设计具有多个复杂模块的 AngularJS 应用程序的建议,并根据用户角色在身份验证和授权后加载模块。有些用户可以访问一个简单的模块,有些用户可以拥有仪表板,有些用户可以访问 2 个以上的模块。

我们已经确定了许多可以跨不同模块重用的指令。在设计阶段,我们已经确定了以下应该存在的内容,并且我们对以下一些项目有了答案,但我们仍然需要专家的建议:

  • 一个模块可以有
    • 部分
    • 控制器
    • 指令
    • 服务
  • 异常处理(HTTP 状态代码或业务错误)
  • 日志记录(带行号,来自哪个函数)
  • 可能还需要将记录的信息保存在服务器中
  • 应该能够打开和关闭日志记录
  • 通过工厂类自定义小部件(在其他模块中重用)
  • 共享指令(隔离范围)
  • 共享模块
  • 共享实用程序(排序、过滤等)
  • 根据主数据的枚举数
  • 通过单例的常量
  • 身份验证 (CSRF)
  • 离线存储
  • REST 服务
  • 从一个模块调度并在另一个模块中处理的事件处理

应用程序的 UI 看起来像页面顶部的固定菜单栏,左上角有一个下拉导航,其中包含多个链接,具体取决于用户的角色。当用户点击一个链接时,相应的模块应该被加载到页面中。必须有一个空项目,手动引导并在运行时加载其他模块。

我们的方法是具有以下文件夹结构:

  • 应用程序
    • 资产
      • CSS
      • lib js
      • 图片
    • 常用组件
      • 指令
      • 实用程序
      • 身份验证
      • 保存 $resource 调用的服务代理
      • 枚举
      • 常量
    • 型号
      • 实体 json(例如客户、产品等)
    • 业务模块A
      • 部分
      • 指令
      • 服务
      • 控制器
    • 业务模块 B
    • 业务模块 C
    • index.html
    • Requirejs 配置文件

所以我的问题是:

  • 模块内的服务如何与其他模块通信?
  • 模块应该独立开发和运行?
  • 模块之间的通信如何处理传输数据?
  • 如何整合以上所有元素,尤其是异常处理、日志记录?
  • 开发人员应该了解我们定义的约定吗?
  • 调用什么方法进行日志记录,在模块之间发送信息?

【问题讨论】:

  • 我认为完整的例子在这里ify.io/…
  • 感谢 Shohel,我们已经处理了延迟加载。我的疑问更多的是如何设计一个具有 20 多个开发人员的可扩展应用程序可以工作的最小依赖性。以及如何将所有功能与一些定义的约定结合在一起。尝试绘制架构图。
  • 我想学很多东西,你还没有给我任何关于角度大型应用程序设计的建议。每天晚上 7 点到晚上 11 点(格林威治标准时间 +6)我都有空。您可以尝试通过 Skype 寻求任何帮助
  • RequireJS 不建议与 AngularJS 一起使用 (stackoverflow.com/questions/12529083/…),如果您正在寻找适合大型团队和大型项目的项目结构,您应该阅读以下内容:github.com/toddmotto/angularjs-styleguide(制作Todd Motto,谷歌开发专家)

标签: javascript angularjs


【解决方案1】:

我建议将yeoman 包含在您的工作流程中,并为您的项目使用生成器,这样可以更轻松地构建应用程序,特别是如果您在团队中工作。

今年早些时候,来自 Angular 的人们发布了一个 document ,其中包含您的应用程序结构的最佳实践,我建议您阅读它,据说有一个基于名为 cg-angular 的最佳实践的生成器,我完全推荐.

我将引用 cg-angular 网站:

所有子生成器都会提示用户指定新的保存位置 文件。因此,您可以创建任何您想要的目录结构, 包括嵌套。生成器将在 项目的根目录,包括 index.html、app.js 和 app.less。你 确定项目其余部分的结构。

关于您的问题:

  • 模块内的服务如何与其他模块通信?

你可以为你要去的指令/和服务/创建一个文件夹 在不同的模块中重用。

  • 模块应该独立开发和运行?

您可以在一个应用程序中拥有多个模块(您可以将它们加载为 需要,也许使用 require js 但这是题外话)

  • 如何处理模块之间的通信与传输数据?

使用服务在不同的控制器之间传递信息 模块

  • 如何整合以上所有元素,尤其是异常处理、日志记录?

你可以做一个通用的错误处理程序和一个通用的 http 拦截器 所有模块

  • 开发人员应该了解我们定义的约定吗?

使用他们认为的生成器,他们给出命令和 团队需要的约定。

【讨论】:

    【解决方案2】:

    有很多好问题要问;它们似乎分为两大类——第一个是代码结构问题,第二个是关于指标(日志等)的问题。

    模块内的服务如何与其他模块通信?

    理想情况下,您应该为您的模块使用指令。通过这种方式,您可以利用通过require 属性链接控制器的能力。 Here is a page on sharing data between directives and controllers.

    模块应该独立开发和运行?

    我假设您正在考虑单元测试。是的,理想情况下,您的模块应该尽可能地缩小范围,以便更轻松地进行测试。

    模块之间的通信如何处理传输数据?

    这是通常使用services 的地方。注意:服务、工厂和提供者在 AngularJS 中的含义相同,只是声明方式略有不同。选择您最喜欢的那个。

    如何整合以上所有元素,特别是异常处理、日志记录?

    日志记录是一个单独的问题。 AngularJS 的美妙之处在于,您可以非常轻松地扩充框架的现有部分,以便添加您认为合适的功能或行为。您可以使用decorators 执行此操作。 Here is an example of exception logging that I think will cover any use cases you might be interested in

    开发者应该了解我们定义的约定吗?

    这个问题的答案总是一样的:沟通就是他们知道的方式。开发人员需要将约定社交化,否则您将永远无法获得支持。

    调用什么方法进行日志记录,在模块之间发送信息?

    上面已经回答了。

    【讨论】:

      【解决方案3】:

      大型 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 的下一个逻辑步骤是创建一个 一些原型的目录并将对象拆分为它们的 自己的文件。为了延续服装比喻,我们现在投资了一个 漂亮的莫哈格尼梳妆台,打算把袜子放在一个抽屉里,内衣 另一个,整齐地折叠我们的裤子和衬衫。

      假设我们正在构建一个带有登录名的简单电子商务网站 流程、产品目录和购物车 UI。我们还定义了新的 模型(业务逻辑和状态)和服务(代理)的原型 到 HTTP/JSON 端点)而不是将它们归为 Angular 的单一 “服务”原型。我们的 JavaScript 目录现在可以如下所示:

      controllers/ 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 产品/搜索/ SearchResultsController.js SearchResultsModel.js ProductDetailController.js ProductModel.js ProductService.js 用户/ LoginController.js RegistrationController.js UserModel.js UserService.js 任何随机的开发者现在都可以打开顶级文件夹 并立即深入了解应用程序的功能。对象 在同一个文件夹中有关系,有些会有依赖关系 在别人身上。了解登录和注册过程的工作原理 就像浏览该文件夹中的文件一样简单。通过原始重用 复制/粘贴至少可以通过将文件夹复制到 另一个项目。

      使用 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) { return new UserService($http); }]);
      userModule.factory('userModel', ['userService', function(userService) { 返回新的用户模型(用户服务); }]);
      userModule.controller('loginController', ['$scope', 'userModel', 登录控制器]); userModule.controller('registrationController', ['$scope', 'userModel', RegistrationController]);看法 rawUserModule.js 由 GitHub 托管 UserModule.js 进入用户文件夹它就变成了一个“manifest” 该模块中使用的对象。这也是一个合理的地方 为 RequireJS 或 Browserify 添加一些加载器指令。

      通用代码提示

      每个应用程序都有许多模块使用的通用代码。我们 只需要一个地方,它可以是一个名为“common”的文件夹或 “共享”或任何你喜欢的。在非常大的应用程序中,往往 是功能和横切关注点的很多重叠。 这可以通过一些技术来管理:

      如果您的模块对象需要直接访问几个“公共” 对象,为它们编写一个或多个 Facades。这可以帮助减少 每个对象的协作者数量,因为有太多 协作者通常是代码味道。如果您的“通用”模块 变大将其细分为解决特定问题的子模块 功能区或关注点。确保您的应用程序模块仅使用 他们需要的“通用”模块。这是“接口”的变体 隔离原则”来自 SOLID。将实用程序方法添加到 $rootScope 所以它们可以被子作用域使用。这可以帮助防止不得不 将相同的依赖项(例如“PermissionsModel”)连接到每个 应用程序中的控制器。请注意,这应该谨慎进行 避免弄乱全局范围并产生依赖关系 不明显。使用事件解耦两个不需要的组件 对彼此的明确引用。 AngularJS 使这成为可能 通过 Scope 对象上的 $emit、$broadcast 和 $on 方法。一种 控制器可以触发一个事件来执行一些动作,然后接收一个 动作完成的通知。资产和测试快速说明

      我认为在组织方面有更大的灵活性空间 HTML、CSS 和图像。将它们放在 模块可能在封装之间取得了最佳平衡 模块的资产依赖关系,而不是把东西弄得乱七八糟。 但是我认为这个内容有一个单独的顶级文件夹 包含反映应用程序包结构的文件夹结构 也很合理。我认为它也适用于测试。

      请看下面的链接,

      https://blog.safaribooksonline.com/2014/03/27/13-step-guide-angularjs-modularization/

      【讨论】:

        猜你喜欢
        • 2010-11-02
        • 2013-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多