如何雇用 Angular 开发人员:需要寻找的关键技能和知识

已发表: 2022-09-14

凭借其高度可扩展的架构,许多 Web 开发团队选择 Angular 来创建高效、复杂的单页应用程序。 但是,雇用 Angular 开发人员说起来容易做起来难。 虽然有很多候选人,但无缝开发体验的关键是找到一位优秀的Angular 开发人员,他应用最佳实践和先进技术来满足高质量的编码标准。

了解有关 Google 流行的前端框架的关键概念将使您准备好自信地采访潜在客户并聘请最优秀的开发人员 - 那些努力将代码库提升到新水平的人。 本文列出了高级 Angular 专业人员应具备的关键技能和知识。

TL;博士

高质量的 Angular 候选人将是那些:

  • 了解 Angular 的核心功能。
  • 在他们开始编码之前进行设计。
  • 了解 Angular 应用程序生命周期。
  • 对反应式编程有扎实的了解。
  • 知道什么是状态以及如何使用它。
  • 熟练并支持自动化测试。
  • 随时了解最新的 Angular 版本。

注意:本指南适用于不再称为 AngularJS 的最新 Angular 版本——“Angular”自 Angular 2 起就适用。如果您正在招聘维护或升级旧版 AngularJS Web 应用程序项目(1.x分支),查看如何聘请优秀的 AngularJS 开发人员。

了解 Angular 的核心功能

Angular 框架在TypeScript上运行,并且在应用程序中编写的所有代码都被转换为 JavaScript。 TypeScript 是 JavaScript 的超集,可编译为纯 JavaScript。 Angular 代码由这个超集表示。

许多开发人员学习 Angular,但对 JavaScript、TypeScript、HTML 或 CSS 所需的核心概念缺乏很好的理解。 如果缺少这些基础,开发人员往往会使用不适当的解决方法,从而增加项目的技术债务。

因此,请询问候选人是否了解 HTML5 和 CSS3。 一个优秀的 Angular 开发人员不需要是 HTML 或 CSS 专家,只要团队中的其他人是,但他们应该了解以下关键概念:

  • 弹性盒
  • SCSS 变量
  • spandiv的区别
  • CSS中的重要类
  • 属性

Angular 开发人员应该对 JavaScript 和 TypeScript 以及一些 HTML 和 CSS 技能有深入的了解。

鸣叫

编码前设计

好的设计是好的应用架构的关键。 询问您的候选人他们是如何进行设计的,并将他们的想法与这些理想的考虑因素进行比较:

  • 代码将去哪里? 是否需要新的库或模块?
  • 输入和输出是什么?
  • 是否应该有任何可重用的组件或指令?
  • 国家将何去何从? (在下面的状态管理下进一步讨论。)
  • 业务逻辑将走向何方——即,在哪个服务中?
  • 是否可以在库之间共享某些组件以创建本质上的 UI 设计系统?

特定设计的全部细节不如候选人是否有制作设计的习惯重要。 所有设计都是临时的,因此对于大多数应用程序,除非需要正式文档,否则文档可以像白板上的素描照片一样简单。 在稍后阶段,开发人员可以从代码(使用正确的工具)生成技术设计,以明确所有部分如何相互关联。

了解 Angular 应用程序生命周期

询问你的候选人他们对Angular 组件生命周期的了解。 他们的答案应该包括三个生命周期钩子: ngOnInitngOnChangesngOnDestroy 。 顾名思义,在组件初始化时调用ngOnInit ,在销毁组件时调用ngOnDestroy ,在属性更改时调用ngOnChanges 。 后者可以发生在ngOnInit之前——如果在组件完全初始化之前已经分配了属性,那么ngOnChangesngOnInit之前执行。

如果候选人还知道ngDoCheckngAfterContentInitngAfterContentCheckedngAfterViewInitngAfterViewChecked ,那么他们知道组件的所有变更检测钩子,并且领先一步。

关于任何钩子的一个很好的后续问题:“这种变更检测何时发生?”

左侧出现五个带有向下箭头的框。除了第四个是绿色的之外,它们都是绿色的,它是蓝色的,并且有一个括号扩展成五个向下的盒子,出现在右侧(第一个是白色的,其余的是蓝色的)。左边的方框从上到下依次为:“constructor、ngOnChanges、ngOnInit、ngDoCheck 和 ngOnDestroy”。从“constructor”到“ngOnChanges”的箭头标记为“Component has bound inputs”,还有一个从“constructor”指向“ngOnInit”的箭头,标记为“Component没有绑定输入”。从“ngOnChanges”到“ngOnInit”的箭头标记为“首次运行”,还有一个从“ngOnChange”指向“ngDoCheck”的附加箭头标记为“未首次运行”。一个带有文本“1+ 数据绑定输入属性更改”的白框出现在“ngOnChanges”的左上方并指向它。右侧的方框从上到下依次为:“第一次调用?、ngAfterContentInit、ngAfterContentChecked、ngAfterViewInit 和 ngAfterViewChecked。” “第一次打电话?”中的箭头到“ngAfterContentInit”标记为“是”,并且有一个额外的箭头指向“第一次调用?”标记为“否”的“ngAfterContentChecked”。从“ngAfterContentChecked”到“ngAfterViewInit”的箭头标记为“第一次调用”,另外一个箭头从“ngAfterContentChecked”指向“ngAfterViewChecked”,标记为“不是第一次调用”。
Angular 组件生命周期的概述。

一个鲜为人知的生命周期是提供者生命周期,它只有一个钩子: ngOnDestroy 。 仅当提供程序附加在组件级别时才会调用此方法,在这种情况下,它会与组件一起被销毁。 如果它是在根或模块级别提供的,它将永远不会被破坏。

提供者的构造函数将在第一次使用提供者时执行,因此构造函数可能永远不会被执行。 向你的候选人询问这种可能性——在现实世界的场景中,它可能是一个经常被忽视的错误来源!

反应式编程的扎实知识

在 Angular 应用程序中,反应式编程通常是最难理解的部分。 许多人在开始编写一段代码时以程序化方式思考,假设它更容易理解和使用,就像食谱的步骤一样。

反应式编程涉及对我们无法控制的事情做出反应,并且可能以不可预测的顺序发生。 尽管我们每天都以这种方式对事物做出反应——例如,当我们前面的汽车突然停下时刹车——但许多开发人员发现很难采用反应式编程方法。

但是,Angular 应用程序中发生的一切都是基于反应式编程的。 例如,Angular 购物应用程序中的一些反应性示例可能包括:

  • 当用户登录时,购物车图标上的数字会更新,并且菜单项会更改为更具体的选项。
  • 当用户导航到某个类别时,产品会根据所选类别进行更新。
  • 当用户将产品添加到他们的购物车时,购物车图标会随着产品数量而更新。
  • 当商品缺货时(通过从后端监控当前库存数量的监听器注册),页面 UI 会更新。

请注意,这些事情会自动发生,不需要页面刷新即可出现。 在面试中,要求应聘者描述他们如何在他们开发的应用程序中应用反应式编程。 如果候选人描述了涉及刷新页面或手动调用ChangeDetectorRef.detectChanges()来刷新组件的解决方案,则认为这是一个黄色标志。

Angular 中 Observables 的陷阱

经验不足的开发人员有时可能会发现他们在 Angular 应用程序中编写的代码没有被执行。 经验丰富的 Angular 开发人员可以确定一个常见原因:没有订阅Observable ,这是响应式编程中的主要对象类型。 只有订阅才会执行后端调用或其他反应。

创建订阅有两种方法:开发者可以使用async管道或subscribe方法。 但有一点需要注意:如果开发人员手动订阅(使用subscribe方法),则需要手动销毁Observable (尽管默认情况下会发生一些极端情况)。 开发人员可以通过多种方式销毁Observables

  • 尽可能使用async管道(这会在不再需要组件时破坏Observable )。
  • 在组件的生命周期结束时( ngOnDestroy )使用Observable上的unsubscribe方法手动取消订阅。
  • pipe操作符中使用takeUntil操作符,并使用主题(即类似destroy$的名称)以更具声明性的方式。 在这种情况下,主体在组件的生命周期结束时发出destroy$.next() ( ngOnDestroy )。 在接收到 destroy 事件后, takeUntil操作符将不再接受它所绑定的 Observable 的事件,因此它的订阅者逻辑将不再被触发。 例如,请参阅第 2 节中的 takeUntil 运算符。使用taketakeWhile运算符可以公开类似的功能。
  • 由于 Angular 应用程序切换到 Ivy 编译器,我们也可以使用注解。 until-destroy库或其他第三方库(如 SubSink)可用于在组件被销毁后平滑地取消订阅 observables。

反应式编程的另一个潜在痛点来自内存泄漏和对后端的多次调用。 询问候选人是否知道这些问题,以及他们通常会如何解决这些问题。 如上所述,未能取消订阅Observable可能会导致内存泄漏。 可以通过共享Observable来解决由于后端调用上的多个订阅而导致的多个后端调用。

了解状态以及如何使用它

所有的单页应用程序都有一个状态,这个状态在前端的某个地方是可用的。 但是,究竟什么是状态? 它包含特定于当前用户体验的所有变量。 例如,经过身份验证的用户详细信息(如姓名和个人资料图像 URL)、所选的特定菜单项或屏幕列表(如购物车项目列表)。

在 Angular 应用程序中,需要考虑三种主要类型的前端状态:

状态范围
应用整个应用程序可用的一般信息,例如经过身份验证的用户、用户角色、菜单项或用户的购物篮。 在此状态下发生的任何变化都会在整个应用程序中发生变化。
模块对使用服务的整个模块可用的信息。 每次开发人员使用提供者重用模块时,它都会为每个提供者创建一个新实例。 状态永远不会被破坏,只会在第一次使用给定的提供者时创建。
零件特定组件可用的信息。 组件是应用程序的最小部分。 Angular 应用程序可以有多个组件状态,但它们只能通过每个组件访问。 状态会在组件被创建时创建,在组件被销毁时被销毁。

很好地理解什么是状态,以及何时应该加载或重新加载,是招聘 Angular 开发人员时要寻找的关键技能之一。 如果您的团队有机会审查候选人编写的一些示例代码,这是探索的主要领域。 如果申请人正在使用库进行状态管理:

  • 寻找使用 NgRx、Akita、NgXs 或类似的特定于状态管理的库。
  • 然后查看相关代码中是否有effectsactionreducerstoreselector的通知。

我们以 NgRx(与 Akita 等库类似)中应用程序状态的大致流程为例:

左上角的白色“选择器”框向下指向左下角的绿色“组件”框,该框向右指向白色的分层“动作”框。 “Action”框指向一个白色的分层“Reducer”框,右侧(带有虚线箭头)指向一个白色的分层“Effects”框。 “Reducer”框指向一个蓝色的“Store”框,它向左指向“Selector”框。在右下角,“效果”框向左(带有虚线箭头)指向“操作”框,然后指向绿色的“服务”框。 “服务”框向下指向“效果”框,向上指向绿色圆柱体堆栈。绿色圆柱体堆栈指向“服务”框。

如果开发人员使用服务创建自己的状态,他们在状态管理方面的能力可能更难识别:

  • 搜索对单词stateeffect的引用。
  • 查看代码是否对某些操作做出反应,例如,如果用户按下按钮 A,则屏幕 B 上的文本应更改。

面试官要问的关于国家的问题

通过调查申请人的代码,您并不总能找到您需要知道的所有内容。 将这些查询添加到您的问题列表中,以调查潜在的 Angular 开发人员对状态的理解程度:

  • 你在哪里使用过state ——以及如何使用? 这是了解他们的状态体验的坚实起点; 不要害怕探究细节。
  • 你如何决定是否使用图书馆? 如果他们知道在应用程序中包含状态库并不总是有用,这是一个好兆头。
  • 你会在 state 里面放什么,你会把它放在哪里,以及你如何使用 state 管理系统? 如果他们说,“我把所有东西都放到了我的全局应用程序状态中”,这是一个明确的迹象,表明开发人员没有意识到这样的系统会给应用程序带来的负面影响。

了解各种状态类型的开发人员将避免这些副作用:

  • 仅适用于一个组件的状态可能会被其他组件修改或破坏。
  • 数据嵌套在存储中,因此很难跟踪数据,并且数据变得不可读(出于调试、数据交换等目的)。
  • 在表单中编辑数据已经将其发送到应用程序的其余部分,而它应该只在保存数据时被推送到存储区——换句话说,应用程序的其余部分可能正在使用无效数据。

用不了多久,全局存储就会变得杂乱无章,而且不清楚每个部分的混乱来源,使得调试和维护变得更加困难。

了解自动化测试的重要性

对于任何 Angular Web 应用程序,自动化测试都应该被视为与代码质量一样重要。 程序员编写测试的主要原因之一是记录他们的代码:如果新开发人员加入公司,业务逻辑和某些 UI 流程应该根据测试套件的期望明确。 此外,自动化测试会在开发早期发现错误。

问你潜在的 Angular 开发者三个测试问题:

  • 你对测试有什么看法? 任何不关心自动化测试的候选人都应该停止考虑。 即使他们不喜欢使用测试驱动开发 (TDD),如果开发人员看不到自动化测试的价值,也会花费您公司的手动测试时间,更糟糕的是,当对应用程序进行更改时出现回归时最终用户停机时间随着时间的推移。
  • 测试时你关注什么? 一个优秀的 Angular 开发人员应该专注于测试核心业务逻辑,而不是测试能够为字段分配值或争取特定的测试覆盖率指标(即 85% 的覆盖率)等基本给定条件。
  • 通常有更多的 E2E 测试还是更多的单元测试? 为什么? 作为前端应用程序,Angular 应用程序可以利用两种主要的自动化测试:单元测试和端到端(E2E)测试。 通常,一个测试套件将包含许多单元测试和较少的 E2E 测试。 单元测试很小,因此可以快速编写和执行。 E2E 测试更大更慢。 公平警告:并非所有开发人员都对单元测试和端到端测试的正确比例保持一致。 实际上,这取决于被测试应用程序的复杂性,即便如此,答案在某种程度上还是值得商榷的。

流程图从左上角开始,带有一个分开的浅蓝色和绿色框。浅蓝色部分有文字“你对测试有什么想法?”绿色部分的文字是“候选人是否关心自动化测试?”从绿色部分,一个“否”箭头指向一个深蓝色的框,上面写着“候选人没有合适的测试技能”,一个“是”箭头指向另一个拆分框。第二个框的浅蓝色部分有文字“你在测试时关注什么?”绿色部分的文字是“候选人是否专注于测试关键业务逻辑(超出代码覆盖率)?”从绿色部分,一个“否”箭头指向一个深蓝色的框,上面写着“候选人可能没有合适的测试技能”,一个“是”箭头指向另一个拆分框。第三个框的浅蓝色部分有文字“通常有更多的 E2E 测试还是更多的单元测试?为什么?”绿色部分的文字是“候选人是否理解单元测试和端到端测试的重要性和目的?”从绿色部分开始,一个“否”箭头指向右上方的深蓝色框,上面写着“候选人可能没有合适的测试技能”,一个“是”箭头指向右上方的深蓝色框,上面写着“候选人有合适的测试技能”技能。”
为 Angular 开发人员测试面试问题的指南。

角度测试框架

Angular 开发人员在自动化测试框架方面有很多选择。 可以通过 Jest 或 Jasmine 和 Karma 执行单元测试。 每个 Angular 开发人员都应该熟悉 Jasmine 和 Karma。 Jest 也很常见——它通常更快,并且具有更高级的测试选项。

Angular 应用程序的 E2E 测试标准是 Protractor,这是 Angular CLI 生成的默认工具。 另一种选择是 Cypress,它是一个有很多选择的有前途的 E2E 测试框架。

确保候选人对至少一种单元测试框架和一种端到端测试框架有深入的了解。

随时了解最新的 Angular 版本

伟大的 Angular 开发人员可能由于各种原因并不总是在开发中使用最新版本,但他们应该知道 Angular 的发布时间表,以便他们能够及时了解变化并准备好切换。 评估这一点的一种方法是询问候选人是否熟悉 Angular 的发布策略。 Angular 的目标是每六个月发布一次主要版本,通常在二月和五月左右。 Angular 版本在发布日期后的前六个月内处于“积极支持”状态,并在发布日期后的 12 个月内处于“长期支持”状态。 与其他一些技术相比,这是一个相当紧迫的时间表,因此保持最新状态尤为重要。

你也可以对 Angular 的最新版本进行一些研究,并向你的候选人询问这些新功能的好处。 例如,大约在 Angular 14 发布的时候,你可能问过候选人:

  • 独立组件,减少了对 Angular 模块的需求。 独立组件没有在任何现有的NgModule中声明,它们直接管理自己的依赖项。 因此,可以直接依赖它们而无需中间NgModule
  • 类型化表单,Angular 14 中的另一个重大更新,它将严格类型设置为 Angular 反应式表单的默认设置。 类型化的表单确保FormControlsFormGroupsFormArrays中的值在整个 API 表面上都是类型安全的。 这可以实现更安全的表单,尤其是对于深度嵌套的复杂案例。

您的前端团队的下一个伟大的 Angular 开发人员

每个 Web 开发项目和团队都是不同的,并且会对 Angular 开发人员的技能和知识的各个方面给予不同的重视。 但是了解我们在此介绍的基本主题将使招聘经理能够有意义地参与招聘——即使是技术性更强的评估。

Toptal 工程博客感谢 Ramazan Yildiz 审阅了本文中介绍的技术概念和图表。