项目组织和命名约定

3

这是一个关于重复模块名称的问题的后续。

我们决定遵循Angular应用结构最佳实践建议博客文章中提到的angular项目组织和命名约定,在构建一个用于测量连接质量的小型内部应用程序时使用。

这就是我们目前所拥有的:

$ tree -L 1
.
├── app-config-service.js
├── app-config-service_test.js
├── app-connection-service.js
├── app-connection-service_test.js
├── app-controller.js
├── app-controller_test.js
├── app-countdown-directive.js
├── app-countdown-directive_test.js
├── app-footer-directive.js
├── app-footer-directive_test.js
├── app-footer-service.js
├── app-footer-service_test.js
├── app-math-service.js
├── app-math-service_test.js
├── app-stats-directive.js
├── app-stats-directive_test.js
├── app-status-directive.js
├── app-status-directive_test.js
├── app-status-service.js
├── app-status-service_test.js
├── app-time-directive.js
├── app-time-directive_test.js
├── app.css
├── app.js
├── bower_components
├── config.json
├── countdown.html
├── footer.html
├── img
├── index.html
├── ping
├── stats.html
└── status.html

如您所见,这里有几个指令、服务、局部文件、单一控制器、模块声明文件以及几个与主题无关的配置和应用程序特定文件。这些文件混乱不堪,难以阅读和操作。
这可能是因为我们只有一个单一的模块,并把所有东西都放在里面。
对于这样一个简单的应用程序,使用传统的组件化方法并为服务、控制器、指令和局部文件设置特殊目录是否可以?这是否意味着新的“按功能组织”的方法只适用于非常规的大型应用程序?

1
请查看这个风格指南... https://github.com/johnpapa/angularjs-styleguide#application-structure - Anthony Chu
@AnthonyChu 谢谢,这也是一个好方法。我可能已经读了太多的指南,现在是时候遵循常识而不是指南了 :) - alecxe
1
同一个城市,但不同的宇宙。在 ASP.NET 项目中(通常是企业级别的,通常非常庞大),我们会过度使用文件夹。事实上,我们会按层次结构堆叠文件夹。例如 Views->AdminViews->Reports 等等。所以你有 Components->Functionality 就是我们的范例。你也可以反过来。重点是你需要一种通过功能和特性来组织代码的方式。称之为“概览性”,甚至称之为地铁图。除非你遇到了一堆文件,否则这种需求并不明显。 - Dave Alperovich
@DaveA 谢谢您的意见。我想我可以理解为“根据特定应用程序的大小和复杂性,做出适合需求的决策”。这与您曾经帮助我回答的问题有些相似,但这一次我们面对的是一个真正的应用程序,我们正在尝试在团队内制定约定 - 又被搞糊涂了。我猜这总是基于个人观点和项目特定的,没有银弹。 - alecxe
1
一定要针对团队的操作风格、最新的代码和尽可能的预测来制定计划。团队和团队成员会形成适合他们自己的管理方式和协作关系。我认为,与其寻求最佳实践,不如花费大量时间分析团队趋势的发展方向和群集形式,设计一个能符合他们倾向性的约定。有许多方法可能可行,但只有几个方法能够很好地与您的团队流程和习惯相匹配。试着强调他们的优点,并结构化他们在错误方向上漂移的地方。 - Dave Alperovich
6个回答

8
您说您决定遵循“Angular应用程序结构最佳实践建议”中的建议,但似乎并未完全遵循...
根据推荐方法,每个组件/特性应该在自己的目录下(位于 components 目录下)。
Gil Birman所指出的原因以及上述博客文章每个模块组件重复使用模块名称中详细说明的原因,通过特性进行目录组织(例如,foo-feature 目录包含与该特性相关的所有指令、服务、控制器、部分等),比按类型(例如,一个目录中的所有控制器,另一个目录中的所有服务)进行组织更有意义。
无论如何,上述内容都是指南(更像是思维方式),而不是可以决定每个文件放在哪里的精确配方或确定性算法(例如,是否会有 components/lib/ 目录,服务是否放在特性的目录下还是放在 components/common/ 目录下等)。
您需要理解这些指南(以及它们试图满足的目的/需求),并制定适合您团队风格的约定。
有时您可能不确定要将文件放在哪里。您可以与团队进行讨论,做出决策并执行。
这是完全正常的(尤其是在最初阶段),但随着时间的推移,此类情况将越来越少发生。
话虽如此,我希望您的目录和文件结构更像这样(假设某些服务可能更通用/实用):
app/
|___ app.css
|___ app.js
|___ app-controller.js
|___ app-controller_test.js
|___ bower_components
|___ config.json
|___ index.html
|
|___ components/
|    |___ common/ or util/
|    |    |___ config-service.js
|    |    |___ config-service_test.js
|    |    |___ connection-service.js
|    |    |___ connection-service_test.js
|    |    |___ math-service.js
|    |    |___ math-service_test.js
|    |
|    |___ countdown/
|    |    |___ countdown.html
|    |    |___ countdown-directive.js
|    |    |___ countdown-directive_test.js
|    | 
|    |___ footer/
|    |    |___ footer.html
|    |    |___ footer-directive.js
|    |    |___ footer-directive_test.js
|    |    |___ footer-service.js
|    |    |___ footer-service_test.js
|    |
|    |___ img/
|    |    |___ ...
|    |
|    |___ stats/
|    |    |___ stats.html
|    |    |___ stats-directive.js
|    |    |___ stats-directive_test.js
|    | 
|    |___ status/
|    |    |___ status.html
|    |    |___ status-directive.js
|    |    |___ status-directive_test.js
|    |    |___ status-service.js
|    |    |___ status-service_test.js
|    |
|    |___ time/
|         |___ time-directive.js
|         |___ time-directive_test.js
|
|___ misc/
     |___ ping

1
这是一个非常详细的答案,非常感谢您的帮助。您说得对,我们现在有一堆文件的原因是我们没有将应用程序拆分为组件(Angular模块)。实际上,这是由于应用程序的增长 - 起初看起来非常小,只有几个服务和指令,但随着时间的推移,越来越多的东西出现了。然后,我们看了看这个问题,考虑将其划分为更小的Angular模块,但决定例如页脚太小而无法成为单独的模块。您的观点对我来说完全有道理。 - alecxe
是的,我也喜欢将页脚放在“components”目录下的“footer”文件夹中 - 不需要将其制作成一个Angular模块。 - alecxe
@alecxe:只是确保清楚:components/内的目录不一定包含Angular模块(使用angular.module(..., [...]);定义的模块)。从博客文章中可以看出:“如果合适,组件可以包含模块定义。[...]模块定义可以在主模块文件中或者在子目录中进行,以满足应用程序的需求。”因此,如果组件很小,它不必成为单独的模块-将其放入自己的目录中就足够分离了。 - gkalpak
@alecxe:在看到你的最后一条评论之前,我已经发布了我的上一条评论,所以我想一切都已经足够清楚了 :) - gkalpak
现在情况更加清晰了,谢谢。由于悬赏期间,我将保持话题开放一段时间 :) - alecxe

2

模块化架构模仿我们大脑的工作方式

即使是一个小项目,我仍然会将项目分成模块文件夹,原因很简单,这样更容易找到需要处理的代码。这是因为程序员通常按照模块进行工作。

例如,一个小时内我们将会处理页脚模块,其中包括指令和服务,它们将位于footer目录中。相比之下,我们不太可能决定一个小时内只处理指令文件夹中的各种指令而从未触及任何服务。

模块化架构使得跨项目复制代码更加容易

当我开始一个新项目时,无论这个项目的大小如何,我通常都会从现有项目中复制模块。使用模块化架构,这非常容易和直观。

当然,如果一个模块高度可重用,你应该将其打包成 bower 模块,但大多数小模块最终都会根据每个项目进行定制。


这就是我担心的。我们有另一个正在发展壮大的应用程序,它非常严格地遵循模块化架构风格 - 我们有认证模块,其中包括登录、更改密码、忘记密码等Angular模块,页脚和页眉也被分成单独的模块。在这里,一开始我们认为这个应用程序非常小,页脚太微小,不能成为一个模块。但是,现在我看到这确实可以帮助更好地组织事物。非常感谢! - alecxe

1

对于初学者,我建议使用yeoman生成器提供的项目组织方式: http://yeoman.io/

它采用面向组件的方法;并提供多个生成器,将代码放在预期位置,为其生成单元测试,保持文件名模式,设置grunt构建描述等。

示例项目结构如下:

enter image description here

当然,即使是简单的应用程序也值得采用结构化方法。在代码库中创建混乱的可能性很多,因此最好从一开始就整齐地开始:)问题可能会出现在另一端 - 在某个点上,您可能需要不止一个模块,并且标准yeoman生成器无法很好地支持它。

1

正如ExpertSystem所述,您当前的目录结构与博客Angular应用程序结构的最佳实践建议没有关系。

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

为什么这很重要?

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

2. 开发容易性:您可以在多个开发人员之间拆分多个功能,并且他们可以针对不同的功能文件夹进行操作,因此他们不会触及相同的文件。合并冲突可以减少。

3. 更快的审查:由于应用程序被拆分成功能模块,因此可以更快地进行审查,并且知道该文件夹的代码是针对特定功能的。

4. TDD实现:该结构可用于启动测试驱动开发(TDD)。 TDD的好处在这篇文章中提到。

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

在开发中,您可以根据功能设置结构。但是,为了改善Web应用程序(或混合移动应用程序)的性能,最好的方法是将所有文件连接起来,缩小并使用GRUNT混淆。下面将提供相应的GRUNT文件示例。 您可以每次部署时使用任何持续集成工具(例如Jenkins)运行脚本。


1

我更喜欢按功能(module)为基础来组织我的项目,这是在顶层进行的,而在较低的层次上则按类型 (指令、控制器) 来组织:

enter image description here

在这个例子中,我有三个独立的(根)模块:主页、搜索和共享。这些模块是我的应用程序的根部分。每个模块可以包含指令、服务、视图、less文件等。一般来说,我喜欢尽可能地将应用程序的相关部分保持在一起。这就是为什么我将新闻指令的各个部分分组到新闻文件夹中的原因。但请记住,这个新闻指令只在我的主页模块中使用。如果它将在多个模块(主页和搜索)中使用,那么我将把新闻文件夹移动到共享文件夹中。
这与这个问题(每个模块组件重复模块名称)的基于前缀的方法类似,但我使用文件夹代替前缀。

是的,我仍然无法真正相信有前缀的存在。在团队内部,我们仍在争论是否要给文件加前缀,或者只是将它们放在子模块中就足够了。感谢您提供的示例! - alecxe

0

当你开始一个项目时,不仅要考虑文件结构。我建议你考虑如何创建你的模块,如何注入依赖项,以及如何压缩你的应用程序。

github.com上的Angular样板是一个样板项目,它让你使用grunt构建应用程序,使用bower管理依赖项,实时重新加载浏览器,并让你使用LESS而不是CSS。

它包含了一个像这样的起始结构:

ng-boilerplate/
|- grunt-tasks/
|- karma/
|- src/
|  |- app/
|  |  |- <app logic>
|  |- assets/
|  |  |- <static files>
|  |- common/
|  |  |- <reusable code>
|  |- less/
|  |  |- main.less
|- vendor/
|  |- angular-bootstrap/
|  |- bootstrap/
|  |- placeholders/
|- .bowerrc
|- bower.json
|- build.config.js
|- Gruntfile.js
|- module.prefix
|- module.suffix
|- package.json

它还包含有关如何设置所有内容的指南。祝你愉快地黑客!

https://github.com/ngbp/ngbp


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接