战略级前端设计
架构并不是从决定哪个 Store 保存哪一份 State,或者哪个 Mapper 应该放在哪个目录开始的。
很多影响更深远的决定,其实发生得更早。
领域边界应该在哪里?哪些部分应该一起演进,哪些部分最好能够保持相对独立?某项职责应该由哪个团队承担?耦合从哪里产生?哪些今天看起来很实际的选择,可能会在几年之后带来更高的协调和维护成本?
这些问题,就是 战略级前端设计 所关注的内容。
为什么叫“战略级”?
Section titled “为什么叫“战略级”?”这个名称有意借鉴了 Domain-Driven Design 中的 Strategic Design。
在 DDD 中,战略设计首先关注的并不是 Entity、Value Object 或 Repository,而是更大的系统结构:领域边界、职责划分、不同 Context 之间的关系,以及哪些部分本来就应该被放在一起思考。
Frontend 也会遇到类似的问题。
一个大型 Frontend 应该继续保持为一个应用,还是适合拆分成可以相对独立发展的部分?一个领域到哪里结束,另一个领域从哪里开始?某个 Shared Service 真的是多个团队共同需要的能力,还是因为责任归属不够清晰,最后所有东西都慢慢放到了这里?
两个团队使用同一个 Model 也不一定总是问题,但它可能意味着双方的变化开始互相影响。
这些决定通常发生在 Component、Store 或具体实现方式之前。
它们决定了后续实现能够在哪些边界内展开。
所以这里所说的战略级前端设计,更关注的是:在讨论代码如何组织之前,先理解系统应该如何被划分。
边界很少只是技术问题
Section titled “边界很少只是技术问题”很多架构问题最初看起来像技术问题。
某个 Module 越来越大,两个团队经常修改同一批文件,一个 Shared Model 出现越来越多特殊情况,Deployment 的协调成本不断上升,或者一个 Shared Package 慢慢知道了整个应用的大部分细节。
但问题的来源并不一定只在代码里。
可能是领域边界还不够清晰。可能两个团队长期共享了本来可以分开的职责。也可能组织结构被直接映射到了软件结构里,但实际业务并不是按照同样的方式划分的。
有些 Integration Model 在项目早期非常方便,但随着系统和团队增长,协调成本也会逐渐增加。
因此,战略级架构不能只从代码和目录结构来理解。
它同时涉及领域、技术、组织方式以及成本。
一个技术上很漂亮的边界,可能对团队协作并不友好。提高 Team Autonomy 的同时,也可能增加基础设施和平台成本。独立 Deployment 可以带来灵活性,也可能引入新的 Integration Complexity。
所以战略级架构并不是寻找一个完美的切分。
更重要的是,在决定做出的时候,就尽可能看清它会带来哪些长期影响。
从两个方向看边界问题
Section titled “从两个方向看边界问题”这个区域目前的两组系列,从两个不同方向讨论同一个核心问题:边界。
Big Ball of Mud
Section titled “Big Ball of Mud”Big Ball of Mud 很少是某个团队有意识设计出来的。
更常见的情况是,它一步一步形成。
职责开始共享,边界逐渐变得模糊,原本临时的 Shortcut 留了下来,越来越多的知识分散到系统各处。
每一个单独的决定,在当时的背景下可能都有合理的原因。
但长期叠加之后,一个很小的修改也可能需要越来越多的人、越来越多的模块和越来越多的协调。
因此,这个系列不仅讨论 Code Structure,也会关注这样的系统为什么会形成,包括团队协作、组织方式和经济因素,以及为什么到了后期再重新建立边界会变得非常困难。
Microfrontends
Section titled “Microfrontends”Microfrontends 则从另一个方向出发。
这里的目标本来就是有意识地建立边界。
团队希望能够更加独立地工作,应用的不同部分可以分开开发,在某些场景下甚至可以独立部署。
但把 Frontend 拆成多个部分,并不会自动解决边界问题。
反而会让边界是否合理变得更加重要。
一个合适的 Microfrontend Boundary 可以带来真正的 Team Autonomy。一个不合适的切分,也可能只是把原来的耦合从一个代码库分散到多个 Application、Repository 和 Deployment 中。
因此,更值得讨论的问题不是:
“Microfrontends 好不好?”
而是:
我们希望保护哪一条边界,又愿意为这份独立性承担什么成本?
战略设计为战术设计创造空间
Section titled “战略设计为战术设计创造空间”战略设计和战术设计并不是两套互相竞争的方法。
它们关注的是不同层次的问题。
战略级前端设计关注系统边界、职责,以及 Frontend Landscape 中较大部分之间的关系。
战术级前端设计 则进一步进入边界内部。当边界本身合理之后,就需要考虑这些责任在代码中应该如何体现。
战略设计更接近于问:
边界应该在哪里?
战术设计则继续问:
这条边界在代码里应该长什么样?
两者缺一不可。
一个设计得很漂亮的 Store 无法修复一个不合适的系统边界。
反过来,即使领域边界本身很清晰,如果边界内部的职责再次混在一起,长期维护仍然会变得困难。
不需要为了架构而架构
Section titled “不需要为了架构而架构”战略级架构听起来很容易变成一个很大的话题。
但并不是每个 Frontend 都需要多个 Deployment、Platform Team 或复杂的 Integration Model。
很多时候,一个边界清晰、结构良好的 Monolith 就已经是非常合适的选择。
目标并不是产生更多 Architecture。
更重要的是有意识地决定:
哪些部分应该一起变化,哪些部分需要保持独立,以及系统长期能够承担多少耦合。
这个区域想讨论的就是这些问题。
重点不是更大的 Diagram,而是那些往往比最初实现它们的代码活得更久的设计决定。