【问题标题】:Repeating module name for each module component每个模块组件的重复模块名称
【发布时间】:2014-09-20 06:28:03
【问题描述】:

著名的Best Practice Recommendations for Angular App Structure 博客文章概述了新推荐的 angularjs 项目结构,该结构现在是面向组件的,而不是面向功能的,或者在 initial github issue 中命名 - “按功能组织”。

博文建议每个模块内的每个文件都应以模块名称开头,例如:

userlogin/
    userlogin.js
    userlogin.css                
    userlogin.html                
    userlogin-directive.js
    userlogin-directive_test.js
    userlogin-service.js
    userlogin-service_test.js 

问题是:在模块中的每个文件名中重复模块名称而不是按功能命名文件有什么意义,优点和缺点?例如:

userlogin/
    userlogin.js
    userlogin.css                
    userlogin.html   
    controllers.js             
    directives.js
    services.js

我问的原因是我来自Django 世界,那里有projects and apps 的类似想法。每个应用程序通常都有自己的models.pyviews.pyurls.pytests.py。脚本名称中没有重复的应用名称。

我希望我没有越过基于意见的界限,并且遵循这种方法是有正当理由的。

【问题讨论】:

  • 在 IDE 中打开多个选项卡(文件)时,在文件名中重复组件的名称非常有用。在大多数 IDE 中,选项卡的标题是打开文件的名称。只需查看选项卡的标题,您就可以立即推断出文件部分是哪个组件。在不重复名称的情况下,您很容易最终打开多个具有相同标题的选项卡,并且在项目中导航会变得有点复杂且容易出错。
  • 我也是 Django+ Angular 用户,我没有将模块名称放在文件名中。我个人的看法是,它在项目中创造了一种整洁的感觉,并且在重新访问我有一段时间没有工作的代码时有所帮助。

标签: javascript angularjs naming-conventions code-organization project-structure


【解决方案1】:

有一个很好的理由,它是为了改进任何重要代码库的一个非常重要的方面(尤其是当涉及到大型开发团队时),即我们所说的“可概览性”。

“概览性”是代码库组织(文件夹结构、文件命名、元对象等)提供已实施软件的快速且信息丰富的概览的能力。

“可概览性”的重要性随着代码库的大小和从事项目的开发人员团队的大小呈指数增长,原因如下(非详尽列表):

  1. 当代码库很大时,代码的某些部分在特定时间段内保持不变的可能性会增加(随着这个“冷”期的持续时间增加)。

  2. 当新成员加入团队时,您希望他们尽快跟上进度(不要让他们在此过程中感到沮丧)。 “Overviewability”有助于为整个项目提供良好的高级抽象,通常还可以很好地了解事物的工作方式(通常会产生熟悉的感觉;就好像您以前看过代码库一样——尽管你没有)。


“所以,好吧,“概览性”很重要。这就是为什么我们有这种以组件为中心的良好结构等等。但是为什么在每个文件前加上组件的名称?” em>

好吧,这听起来可能很有趣,但是为所有与组件相关的文件名添加前缀可以确保特定的顺序。例如。 HTML 部分或 CSS 将始终出现在控制器等之前:

...               
userlogin.html                
userlogin-controller.js
...

如果不是前缀,您最终会根据组件的名称得到各种订单。例如:

...                       ...                      ...
controller.js             controller.js            bookself.html
...                       ...                      ...
service.js         VS     service.js        VS     controller.js
...                       ...                      ...
userlogin.html            zombi.html               service.js
...                       ...                      ...

使用前缀确保文件以特定顺序出现:控制器总是在 HTML 部分之后,服务也在等等。例如:

...                             ...                         ...
userlogin.html                  zombi.html                  bookself.html
...                             ...                         ...
userlogin-controller.js    VS   zombi-controller.js    VS   bookself-controller.js
...                             ...                         ...
userlogin-service.js            zombi-service.js            bookself-service.js
...                             ...                         ...

这可能看起来微不足道,但事实并非如此;尤其是当人们习惯了它时。
请注意,人脑非常擅长识别视觉模式(例如由文件浏览器中文件夹和文件结构的树节点表示创建的模式)。

即控制器不驻留在名为“-controllers.js”的文件中
它驻留在第一个文件名明显比以前的文件长的文件中
服务(如果有的话)驻留在末尾具有较小名称的文件中,等等。

弄乱了(即由于起始字母弄乱了顺序,或者由于长/短的组件名称弄乱了它们的相对长度)并且您遇到了类似于必须从硬盘驱动器读取某些内容的情况,而不是只是从 RAM 中读取它。 (没有开发者愿意去那里:))


*:实际上,我们所说的“开发团队流量”在这里很重要,即团队成员离开的频率(例如从事其他工作、离开公司等)或引入新成员的频率。
通常,团队越大,流量越大。

【讨论】:

  • 哇,没想到这么多。完全有道理,非常感谢!
  • 人类的大脑非常擅长识别视觉模式——说得好!
  • 这个问题有后续:Project organization and naming conventions - 非常感谢您的洞察力。谢谢。
【解决方案2】:

tl;dr;虽然其他答案的大部分观点都没有错,但他们没有认识到当今开发人员可用的文件导航工具的重要性。


快速浏览项目文件

一旦我们对一个项目相当熟悉,我们将希望在文件之间导航而不查看源代码树。我们的命名方案将在让我们快速导航方面发挥重要作用。通过输入文件名的片段,我们可以非常快速地导航到文件。例如,如果您的模块名称是forsee,您可以通过在文件搜索框中输入fo.js 来查看forsee javascript 文件列表(假设您的编辑器具有此功能)。 Chrome 开发工具 Source 选项卡内置了此功能。您可以看到它的实际效果,here(打开开发工具并按 Cmd+O):

我曾经认为在所有文件名前加上模块名是有效搜索所必需的,但后来意识到这根本不是真的。我们可以同样有效地搜索fo/js

所以现在应该清楚无论模块名称是否附加在文件名前面,我们都可以快速导航到文件


概览

我同意 ExpertSystem 的观点,即将文件分组在一起可以让您一目了然。但是,再次预先添加模块名称并不是必需的。相反,在您的编辑器中激活适当的选项:

在上面的屏幕截图中,我激活了按类型排序选项以启用按文件扩展名排序文件。


为什么我们不应该

如果在小屏幕(即笔记本电脑)上编码并使用左侧栏树视图导航文件夹结构,则较短的文件名将更好地服务于有限的屏幕空间。模块文件夹名称将可见,因此看到每个文件都重复该名称是没有用的。


注意事项

显然,我上面介绍的大部分内容确实依赖于开发人员使用正确的工具并知道如何很好地使用它们。如果您的团队没有这些工具,或者您怀疑他们能否有效地使用它们、培训它们或坚持使用冗长的命名方案。


结论

使用当今开发人员可用的高级工具,为每个文件重复模块名称是不合时宜的。但是,过于冗长的文件命名不会造成任何严重的危害或效率问题。在构建一个新项目时,我们必须做出许多其他架构决策,这些决策远比这个重要。


顺便说一句:我确实根据 ExpertSystems 的建议命名了 js 文件。即,dialog.jsdialog-ctrl.jsdialog-services.js 等。由于他所说的原因,这是有道理的,但是当一个模块有多个部分时,最好不要遵循 html 的这种命名模式文件。

【讨论】:

  • 非常感谢!真的很高兴有不同的意见。我们大多数人使用 sublime 和 webstorm,我们仍在争论命名。
  • 关于组织(切线相关)check out my sass guide。我并不热衷于将 css 文件与 javascript 文件放在一起,因为我认为它鼓励跨模块重用的 CSS 代码较少。也就是说,我认为 CSS 模块和应用程序模块应该被视为两个独立的东西。
  • 这个问题有后续:Project organization and naming conventions - 非常感谢您的洞察力。谢谢。
【解决方案3】:

一切都是为了组织大型项目(代码库):


我发现名称和文件夹层次结构对于 组织大型项目。同样,有意义的分层名称 极大地帮助了我。

来自 ASP.NET 世界,项目规模庞大,我们有:

解决方案 -> 管理项目(程序集)-> 使用文件夹 -> 和 子文件夹,用于文件

所以 ASP.NET MVC 项目将在 Controllers 文件夹中具有 Home 控制器MVC 演示项目,以及 Views 文件夹中的Views


在我的项目中使用 AngularJS 时,我喜欢命名的方式

App(Module)-type(directive/service)-(sometimes more detail)

除了命名应用程序文件夹之外,还有指令服务 在文件夹中为其类型命名,文件夹以 app 命名,而应用程序通常以功能命名或以 ASP.NET 视图 命名em>(就像我的视图可能是Account-Login)。

这一切都是因为我的项目非常非常大。我最终拥有许多 AngularJS apps,疯狂数量的 directives,甚至相当数量的 services

当您的项目是小型甚至中等规模时,优势是有争议的。但是,当您的项目变大时,组织就变得至关重要!既可以帮助您找到所需的代码,也可以继续传播更多内容。

【讨论】:

  • 我讨厌 .NET 项目最终在同一个文件夹中有许多 NameOfTheModuleController。视图也一样。我尝试始终使用可以将每个控制器放在不同文件夹中的区域。
  • @LGama,我同意这两种观点。企业项目永远不会停止增长。这不仅仅是他们的预期大小或最终大小。你最终会管理大量荒谬的代码。冗余命名的好处是可以最大限度地减少误解——我讨厌拥有多个数据服务而不区分它们的应用范围。
  • 这个问题有后续:Project organization and naming conventions - 非常感谢您的洞察力。谢谢。
【解决方案4】:

我在我的blog posts 之一中写过这个

模块通常具有重叠功能

假设正在构建一个帐户设置页面。 admin 帐户可以sendNotifications,而user 帐户可以updateNotificationsadminuser 帐户都可以updateAvatar

描述特征和关系

抽象成独立模块、文件和文件夹的组件更易于使用。

包含所有这些模块的父级可以称为帐户。我们知道帐户将有两个不同的角色和三个不同的功能。如果 account 是“角色不可知论”,您的定义可能类似于:

angular.module("account",  [
  "account.updateAvatar",
  "account.sendNotifications", 
  "account.updateNotifications"
]);

但是为这些功能定义父模块可以促进组织和继承:

angular.module("account",  [
  "account.common",
  "account.admin", 
  "account.user"
]);

angular.module("account.common",  [
"account.common.updateAvatar"
]);

angular.module("account.admin",  [
"account.admin.sendNotifications"
]);

angular.module("account.user",  [
"account.user.updateNotifications"
]);

功能模块可以遵循类似的模式:

angular.module("account.common.updateAvatar",  [ 
"account.common.updateAvatar.services",  
"account.common.updateAvatar.controllers",  
"account.common.updateAvatar.directives",
"account.common.updateAvatar.filters"
]);

视图和资产:

account.common.updateAvatar.less
account.common.updateAvatar.tpl.html
account.common.updateAvatar.heading.tpl.html
account.common.updateAvatar.body.tpl.html

点表示法可以实现简单的通配模式

将所有 HTML 部分编译成缓存的 JavaScript:

module.exports = function(grunt) {
  grunt.initConfig({
    html2js: {   
      partials: {
        src: ["src/**/*.tpl.html"],
        dest: "build/js/app.tpls.js",
        module: "app.tpls"
      }
    }
  )};
};

连接你所有的 admin JavaScript 独立于你的 user JavaScript:

module.exports = function(grunt) {
  grunt.initConfig({
    concat: {
      admin: {
        src: ["src/**/*.admin.*.js"],
        dest: "build/js/admin.js"
      },
      user: {
        src: ["src/**/*.user.*.js"],
        dest: "build/js/user.js"
      }
  )};
};

【讨论】:

【解决方案5】:

正如 ExpertSystem 所说,您当前的目录结构与博客 Best Practice Recommendations for Angular App Structure 无关。

我与 ExpertSystems 以及 Gil Birman 合作,认为设计应用程序结构的方法应该是模块化的。如您所知,Angular 本身遵循模块化结构,因此无论您有多个模块还是单个 Angular 模块,您都需要根据您要满足的功能进行思考。例如,如果你有一个“倒计时”功能,它应该有自己的结构。

为什么这很重要?

1.代码维护: 随着代码的增长,您的维护成本也会增加。例如,如果在生产环境中,您的 Angular 代码出现错误并希望使用 1 小时的 KRA 进行纠正,您首先需要在本地复制该场景,然后遍历该特定文件。如果它是模块,您将知道要定位哪个文件夹并快速获得解决方案。

2。易于开发: 您可以在多个开发人员之间拆分多个功能,他们可以针对不同的功能文件夹,这样他们就不会接触相同的文件。可以减少合并冲突。

3.更快的审核: 由于应用程序被分解为功能,因此可以更快、更轻松地进行审核,因为知道该文件夹的代码是针对特定功能的。

4. TDD 实施: 该结构可用于启动测试驱动开发 (TDD)。 article

中提到了 TDD 的好处

开发和生产代码/结构之间的区别

在开发中,您可以根据功能拥有结构。然而,为了提高您的 Web 应用程序(或混合移动应用程序)的性能,最好的方法是连接所有文件,将其缩小并使用GRUNT 对其进行模糊处理。将给出相同的 GRUNT 文件示例。您可以在每次部署期间使用任何持续集成工具(例如 Jenkins)运行脚本。

【讨论】:

    猜你喜欢
    • 2013-10-23
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    相关资源
    最近更新 更多