Chromium 如何实现控制反转
2025-03-04
控制反转(Inversion of control)是一种设计模式(Design pattern)。
按照维基百科的解释,
依赖反转原则是指一种特定的解耦形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。
有点抽象。
举个例子。
你去餐厅吃饭,你要求厨师给你做一个汉堡,厨师做好后怎么取餐,取决于厨师的操作,服务员给你端上来,或者自己去吧台取。
你不需要关心厨师怎么处理这件事。只需要知道,汉堡做好,你会通过某种方式得到它。
此时,控制发生了反转。
Chromium 是一个复杂的工程项目,代码行数超过 3200 万🔗,除了 base
库,更是有着大量第三方库。如果没有适度的抽象和解耦,如此庞大的代码仓库将会迅速腐烂,变得难以维护。
控制反转,便是 Chromium 采取的一种应对之道。
1. 概念
控制反转有两个核心原则:
- 高层模块不应依赖低层模块的实现
- 抽象不应依赖细节
这两个原则,说的其实是一件事:解耦。
这是面向对象编程里经常提及的概念。
耦合过重的组件,通常难以维护,而且不便于扩展。
如果一项改动,牵一发而动全身,那么基本上没有人敢轻举妄动。更谈不上敏捷开发了。
好的解耦应该保证,若有改动,影响范围够小。
这需要清晰的模块划分,明确的接口定义,以及松散耦合的组件交互。
2. Chromium 的设计
Chromium 主要用到了三种手段:
- Callback (回调)
- Observer (观察者)
- Delegate (委托)
举个生活化的例子。
老王喜欢喝茶。
喝茶就要先烧水,可惜老王家的热水壶比较老式,得不停地去看是否烧好。
老王有点不耐烦,心想:我怎么能依赖热水壶的特性呢?
于是发明了一个工具:开水报警器。
等水烧开,开水便会触发报警器,通知老王接热水。
老王很满意。
开水报警便是一个 Callback。
老李也喜欢喝茶。
可惜,老王的开水报警器只能通知老王一个人。
如果每个人都放一个开水报警器在热水壶里,热水壶很快就满了。
老王灵机一动,想到一条商机。
在开水报警器旁增加一个二维码,想知道水是否烧开的,扫码注册,水烧开后会通知。
老王、老李都很满意,他们都是 Observer。
有天,老王的热水壶坏掉了,想换一个,发现很不方便:热水壶和开水报警器是绑定在一起的,要换就得一起换。
老王心想,他需要的只是开水,是不是热水壶烧的并不重要,如果有开水公司,也是可以的。
那些能提供开水功能的,在老王这里都是 Delegate。
简单地说,Callback 和 Observer 是等着被动通知,而 Delegate 是主动提供。
3. 启发
对于一个简单系统,解耦与否并没有那么重要。即便耦合重,重构的负担也不大。
对于复杂系统则不然。
在开发中,顶层设计很重要。一定是先接口(Interface),后实现(Implementation),接口通常稳定,而实现易变。
先想清楚去哪里,再决定怎么去。
这是我老板经常对我讲的。
现在各种代码生成的工具层出不穷,GitHub Copilot、Cursor,还有 Trae,实现一个想法变得异常简单。
能提出创意的想法,清楚地表达,越来越重要。
不仅在软件开发领域如此。
作为一名程序员,你的技能,经验,阅历,越通用越好,如果和公司、行业存在较深耦合,就要警惕了。未来某天,行业发展进入下行周期,泥沙俱下,没有一点影响,很难。
之前 文章🔗 文章提到的三点,回过头看,何其然也:
- 可迁移技能
- 有意义的经验
- 持久的关系
4. 总结
控制反转是一种手段,解决的是耦合问题。
本质是为了降低复杂度。
这是软件工程面临的终极问题。毕竟整个宇宙,就是有着熵增的惯性。
人也如此。
年少天真童趣,进入社会,愈发老成,心思越来越深,想法越来越多,胃口越来越大。
目前我能想到的,就是剪枝,放低姿态,减少低质信息摄入,专注某个细分领域。后面有时间展开讲。
(完)
参考
- 本文作者:Plantree
- 本文链接:https://plantree.me/blog/2025/inversion-of-control-in-chromium/
- 版权声明:所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
最后更新于: 2025-03-06T05:01:28+08:00