目录
文章目录
一、单一职责
1. 单一法则
- 坚持每个文件只定义一样东西(例如服务或组件), 考虑把文件大小限制在 400 行代码以内。
这么做的理由:
- 单组件文件非常容易阅读、维护,并能防止在版本控制系统里与团队冲突。
- 单组件文件可以防止一些隐蔽的程序缺陷,当把多个组件合写在同一个文件中时,可能造成共享变量、创建意外的闭包,或者与依赖之间产生意外耦合等情况。
- 单独的组件通常是该文件默认的导出,可以用路由器实现按需加载。
- 最关键的是,可以增强代码可重用性和阅读性,减少出错的可能性。
2. 简单函数
- 坚持定义简单函数,考虑限制在 75 行之内。
这么做的理由:
- 简单函数更易于测试,特别是当它们只做一件事,只为一个目的服务时。
- 简单函数促进代码重用。
- 简单函数更易于阅读。
- 简单函数更易于维护。
- 简单函数可避免易在大函数中产生的隐蔽性错误,例如与外界共享变量、创建意外的闭包或与依赖之间产生意外耦合等。
二、命名
- 命名约定对可维护性和可读性非常重要。本指南为文件名和符号名推荐了一套命名约定。
1. 总体命名指导原则
- 坚持所有符号使用一致的命名规则。
- 坚持遵循同一个模式来描述符号的特性和类型。推荐的模式为feature.type.ts。
这么做的理由:
- 命名约定提供了一致的方式来查找内容,让我们一眼就能锁定。 项目的一致性是至关重要的。团队内的一致性也很重要。整个公司的一致性会提供惊人的效率。
- 命名约定帮助我们更快得找到不在手头的代码,更容易理解它。
- 目录名和文件名应该清楚的传递它们的意图。 例如,app/heroes/hero-list.component.ts包含了一个用来管理英雄列表的组件。
2. 使用点和横杠来分隔文件名
- 坚持在描述性名字中,用横杠来分隔单词。
- 坚持使用点来分隔描述性名字和类型。
- 坚持遵循先描述组件特性,再描述它的类型的模式,对所有组件使用一致的类型命名规则。推荐的模式为feature.type.ts。
- 坚持使用惯用的后缀来描述类型,包括*.service、.component、.pipe、.module、.directive。 必要时可以创建更多类型名,但必须注意,不要创建太多。
这么做的理由:
- 类型名字提供一致的方式来快速的识别文件中有什么。
- 利用编辑器或者 IDE 的模糊搜索功能,可以很容易地找到特定文件。
- 像.service这样的没有简写过的类型名字,描述清楚,毫不含糊。 像.srv, .svc, 和 .serv这样的简写可能令人困惑。
- 为自动化任务提供模式匹配。
3. 符号名与文件名
- 坚持为所有东西使用一致的命名约定,以它们所代表的东西命名。
- 坚持使用大写驼峰命名法来命名类。符号名匹配它所在的文件名。
- 坚持在符号名后面追加约定的类型后缀(例如Component、Directive、Module、Pipe、Service)。
- 坚持在符号名后面追加约定的类型后缀(例如.component.ts、.directive.ts、.module.ts、.pipe.ts、.service.ts)。
- 坚持在文件名后面追加约定的类型后缀(例如.component.ts、.directive.ts、.module.ts、.pipe.ts、.service.ts)。
这么做的理由:
- 遵循一致的约定可以快速识别和引用不同类型的资产。
# app.component.ts
@Component({ ... })
export class AppComponent { }
# hero-list.component.ts
@Component({ ... })
export class HeroListComponent { }
# validation.directive.ts
@Directive({ ... })
export class ValidationDirective { }
# app.module.ts
@NgModule({ ... })
export class AppModule
# init-caps.pipe.ts
@Pipe({ name: 'initCaps' })
export class InitCapsPipe implements PipeTransform { }
# user-profile.service.ts
@Injectable()
export class UserProfileService { }
4. 服务名
- 坚持使用一致的规则命名服务,以它们的特性来命名。
- 坚持为服务的类名加上Service后缀。 例如,获取数据或英雄列表的服务应该命名为DataService或HeroService。
这么做的理由:
- 提供一致的方式来快速识别和引用服务。
# hero-data.service.ts
@Injectable()
export class HeroDataService { }
# credit.service.ts
@Injectable()
export class CreditService { }
5. 指令选择器
- 坚持使用小驼峰命名法来命名指令的选择器。
这么做的理由:
- 保持指令中定义的属性名与绑定的视图 HTML 属性名字一致。
- Angular HTML 解析器是大小写敏感的,它识别小写驼峰写法。
6. 为组件添加自定义前缀
- 坚持使用带连字符的小写元素选择器值(例如admin-users)。
- 坚持为组件选择器添加自定义前缀。 例如,toh前缀表示 Tour of Heroes(英雄指南),而前缀`admin表示管理特性区。
- 坚持使用前缀来识别特性区或者应用程序本身。
这么做的理由:
- 防止与其它应用中的组件和原生 HTML 元素发生命名冲突。
- 更容易在其它应用中推广和共享组件。
- 组件在 DOM 中更容易被区分出来。
# app/users/users.component.ts
@Component({
selector: 'admin-users' # 这里为users添加一个前缀 admin
})
export class UsersComponent {}
7. 为指令添加自定义前缀
- 坚持为指令的选择器添加自定义前缀(例如前缀toh来自Tour of Heroes)。
- 坚持用小驼峰形式拼写非元素选择器,除非该选择器用于匹配原生 HTML 属性。
这么做的理由:
- 防止名字冲突。
- 指令更加容易被识别。
@Directive({
selector: '[tohValidate]' # 为 Validate 添加一个前缀toh
})
export class ValidateDirective {}
8. 管道名
- 坚持为所有管道使用一致的命名约定,用它们的特性来命名。
这么做的理由:
- 提供一致方式快速识别和引用管道。
9. 单元测试文件名
- 坚持测试规格文件名与被测试组件文件名相同。
- 坚持测试规格文件名添加.spec后缀。
这么做的理由:
- 提供一致的方式来快速识别测试。
- 提供一个与 karma 或者其它测试运行器相配的命名模式。
10. 端到端测试文件名
- 坚持端到端测试规格文件和它们所测试的特性同名,添加.e2e-spec后缀。
这么做的理由:
- 提供一致的方式快速识别端到端测试文件。
- 提供一个与测试运行器和构建自动化匹配的模式。
app.e2e-spec.ts
heroes.e2e-spec.ts
11. Angular NgModule 命名
- 坚持为符号名添加Module后缀.
- 坚持为文件名添加.module.ts扩展名。
- 坚持用特性名和所在目录命名模块。
- 坚持为 RoutingModule 类名添加RoutingModule后缀。
- 坚持为 RoutingModule 的文件名添加-routing.module.ts后缀。
这么做的理由:
- 提供一致的方式来快速标识和引用模块。
- 大驼峰命名法是一种命名约定,用来标识可用构造函数实例化的对象。
- 很容易就能看出这个模块是同名特性的根模块。
- RoutingModule是一种专门用来配置 Angular 路由器的模块。 “类名和文件名保持一致”的约定使这些模块易于发现和验证。
# app.module.ts
@NgModule({ ... })
export class AppModule { }
# heroes.module.ts
@NgModule({ ... })
export class HeroesModule { }
# villains.module.ts
@NgModule({ ... })
export class VillainsModule { }
# app-routing.module.ts
@N