原文链接: Clean Frontend Architecture - 原文作者: Robert Maier-Silldorff
本文采用的是意译的方式
这个话题将涉及到很多的原则:
SOLID, KISS(Keep It Short and Simple), DRY(Don't Repeat Yourself), DDD(Domain-Driven-Design) 等等
我们为什么需要前端架构?
功能性和非功能性需求不仅需要应用到后端,也需要应用于前端。因此,前端架构能够满足商业的需求。而且,我们可以更好理解项目的复杂性,从而减少项目的风险、时间和成本。然而,在我看来,前端架构最有价值的原因是任何项目的可维护性和可扩展性。
前端架构应该是什么样子的?
根据我的经验,大多数情况下,Layered Architecture(分层架构)
被使用到。然而,我必须承认我也遇到过一些应用了 Hexagonal Architecture(六边形架构)
的项目。
下图,是一个简单的旅行社项目为例子说明。
哪层被用到?
- API :通过
Open-API
生成器生成DTOs
和Services
- Service :包含
Mappers
(DTO
和 前端模型相互转换),使用REST
对API
进行通信服务 - Store :存储从
Service
层获取的数据 - Booking :包括模型
Models
和组件Components
的区域。
DTO - Data Transfer Object,即数据传输对象
这种架构会出现哪些问题?
嗯~如果没有定义规则,那么开发者可能会在他们的组件直接使用 DTOs
或者与服务层进行通信而不使用存储层。或者说糟糕的是,组件直接与服务层通信,这是多愚蠢。
我们怎么预防这些错误呢?
预防这事情的发生,我们简单定义一些规则。其中最常见的方法之一是在项目中引入 Bit
或者 Nx
。那么,Bit
是什么?Nx
又是什么?
所以,Bit
和 Nx
二选其一应用。因此,在使用错误的层时,开发者会被提示错误。
那是很有效的方法,但是我们怎么确保领域 Domain
自身(例如上面订阅领域)保持可维护呢?
我们可以应用一些 DDD(Domain Driven Design)
概念到我们的 Booking Domain
。因此,我们将 Booking Domain
切分为多个子领域 Sub-Domains
。每个子领域有自己的边界上下文和共享语言。正如下图所示。
每一个子领域都是用分层架构,然后通过子领域的 APIs
相互通信。特性 Feature
包括智能的组件和服务,UI
包括亚组件, Domain
包括模型,而 Util
包括这个边界上下文中使用的实用函数。
现在,一定程度上我们有了清晰的架构,不是吗?我们已经很接近(成功了),但是还是没到那里。拥有一个架构不够,底层组件和和业务逻辑必须使用 Clean Code principle
干净代码原则。因此,让我们深入探讨 Feature
和 UI
层。
哪些原则应该被使用到组件上?
首先,也是最重要的该属 SOLID
原则。每个组件必须是单一原则(Single Responsibility Principle
)。使用组合而非继承,开放封闭原则(Open-Closed Principle
)。不要强制组件实现不适合它的接口,意思是并非所有的方法都有意义,接口隔离原则(Interface Segregation
)。还有要记住的是,组件不应该直接依赖低级别的服务,依赖反转(Dependency inversion
)。
SOLID
中还有一个原则 -> 里氏替换原则(Liskov Substitution Principle
):子类应该能够替换掉父类而不导致程序的错误行为。
第二,当将业务逻辑应用到组件 Component
,服务 Service
或者工具 Util
时,我们应该记住 KISS (Keep it short and simple)
原则。为什么我们要这么做?因为越简单的代码越好维护。
第三,尽量避免重复的代码(DRY, 即 Don't repeat yourself 原则
)。将公共的业务逻辑移动到 Utils
或者 Services
中。
💡笔记:这些原则可以通过使用 Bit 很容易实现。在 Bit Workspace 中,我们可以独立构建,测试,版本控制和文档化重用的组件(函数、
UI
元素或者数据模型),然后将它们发布到Bit
的 component-sharing platform,在那你或者他人能够轻松导入多个项目。
这听起来很合理。然而,一个人如何知道哪些是应该避免的呢?简而言之,什么是反模式(Anti-Patterns
)。
Anti-Patterns
曾经,我也犯了一些同样的错误。有哪些同样的事情呢?
- 引入不必要的库,使得构建包膨胀
- 使用嵌套订阅
nested subscriptions
- 在模版文件
template
中添加了业务逻辑 - 没对业务逻辑进行测试
这些就是反模式 Anti-Patterns
。但是一个人如何确保代码可维护性呢?因为众所周知,业务逻辑随着时间的推移而增长。简而言之,我经常听到下面说法。
代码在历史中逐渐增长。起初,它是干净的,现在,我们有了一些代码,不像以前那么容易维护了。
是的,这是个通病。然而,下面这些简单的规则可能帮到某人去很好维护代码。
- 定义
eslint
规则 - 使用
stylelint
- 测试
Buisness-Logic
- 构建可复用且小巧的组件
- 使用
ES6
和Typescript-Features
总结
我通过举例介绍了 Clean Architecture
,并且介绍了使用到的一些原则。此外,我已经将领域驱动设计(DDD
)应用于前端架构中。最后,但是同样重要的是,我还阐述了有关创建组件和添加业务逻辑的规则,以便代码能够保持可维护性。
然而,开发团队在 Code-Reviews
和添加 new Features
时候应该有更高的标准,否则 Clean Architecture
可能无法保持可维护性。
希望本文能帮到你构建一个清晰的前端架构(cleaner Frontend Architectures
)。