不要假设世界永远按照你的计划运行
以前写代码的时候,我有一个习惯。
刚开始工作的时候,写一个功能,总是假设:
用户会按照设计操作。
参数一定正确。
接口一定正常。
数据一定存在。
网络一定稳定。
依赖服务一定可用。
所以代码经常是:
user.getName();
直接调用。
因为我默认:
user 一定存在。
name 一定存在。
数据一定完整。
但是随着经验增加,我慢慢发现:
真正线上稳定运行的系统,很少建立在“理想情况”之上。
成熟工程师写代码时,会提前考虑:
如果用户传了空值怎么办?
如果接口超时怎么办?
如果数据库没有数据怎么办?
如果第三方服务挂了怎么办?
如果有人恶意输入怎么办?
于是代码开始变成:
if(user != null){
return user.getName();
}else{
return defaultName;
}
这就是:
防御性编程。
它不是因为程序员悲观。
而是因为:
现实世界一定会出现异常。
后来我发现:
人生其实也是一样。
一、过去的我,总是假设人生运行在“理想环境”
年轻的时候,我们很容易这样设计人生:
毕业
↓
找到稳定工作
↓
不断成长
↓
升职加薪
↓
收入增加
↓
生活越来越好
这套路径没有错。
但它隐藏了一个假设:
世界会持续稳定。
可是现实不是这样。
行业会变化。
技术会变化。
公司战略会变化。
组织结构会变化。
身体状态会变化。
家庭阶段会变化。
甚至你自己,也会变化。
以前喜欢的东西,可能后来不喜欢。
以前擅长的能力,可能后来价值下降。
以前认为重要的目标,可能后来发现不是自己真正想要的。
所以很多时候,人生遇到的问题不是:
“我不够努力。”
而是:
我的人生系统,没有考虑异常情况。
二、没有防御机制的人生,容易出现单点故障
在软件系统里面,一个非常危险的问题叫:
Single Point of Failure(单点故障)。
意思是:
整个系统依赖一个节点。
这个节点一旦失败,整个系统瘫痪。
比如:
一个数据库。
一台服务器。
一个核心服务。
如果没有备用方案:
它就是系统最大的风险。
人生里也有大量类似问题。
比如:
收入单点故障
收入
↓
唯一工资来源
↓
公司
↓
岗位
如果这个节点出现变化:
整个系统受到影响。
能力单点故障
职业价值
↓
某项技术
↓
某个平台
如果技术环境变化:
能力价值下降。
价值感单点故障
自我认可
↓
工作评价
↓
领导反馈
如果工作环境变化:
容易产生巨大心理波动。
社交单点故障
人际关系
↓
公司同事
离开组织以后:
连接突然减少。
很多时候,人真正焦虑的原因不是变化本身。
而是:
系统没有备用路径。
三、防御性编程的第一原则:不要相信输入
程序员都知道:
外部输入永远不可信。
用户输入。
网络请求。
第三方接口。
文件内容。
都需要验证。
为什么?
因为你无法控制外部环境。
人生也是一样。
很多痛苦来自于:
把外部世界当成确定条件。
比如:
“公司会一直需要我的能力。”
这是一个未经验证的输入。
“我的行业十年后还会这样。”
这是一个未经验证的输入。
“现在的收入水平会一直保持。”
这是一个未经验证的输入。
“孩子未来一定按照我的规划成长。”
也是一个未经验证的输入。
不是说这些一定会错。
而是:
它们不应该被当成系统基础假设。
更成熟的方式是:
给这些输入增加验证机制。
四、给人生增加“参数校验”
代码里面:
收到输入
↓
检查是否合法
↓
通过
↓
执行逻辑
人生也一样。
比如:
有人告诉你:
“这个行业已经没有机会了。”
以前可能直接焦虑。
现在可以增加一个验证流程:
信息来源?
↓
数据是什么?
↓
时间范围?
↓
适用于什么场景?
↓
和我的情况有什么关系?
再比如:
有人告诉你:
“40岁以后程序员没有价值。”
这个输入需要校验。
问题不是:
相信或者不相信。
而是:
拆开来看。
哪些岗位受到影响?
哪些能力仍然有价值?
哪些能力需要升级?
哪些路径需要调整?
这就是:
人生参数校验。
五、防御性编程不是害怕失败,而是降低失败成本
很多人听到“防御”,容易想到:
保守。
不冒险。
不要尝试。
但工程里的防御性设计,并不是这样。
好的系统不是:
永远不出错。
而是:
出了错,也不会造成灾难。
比如:
银行系统。
它不是假设:
“用户永远不会输错密码。”
而是设计:
密码错误怎么办?
账户锁定怎么办?
异常登录怎么办?
风险交易怎么办?
它接受:
错误一定存在。
然后设计:
错误发生后的影响范围。
人生也是一样。
真正的问题不是:
“我要不要尝试?”
而是:
“如果尝试失败,我有没有恢复能力?”
六、给人生设计“降级方案”
软件系统经常有:
Fallback。
备用方案。
当主路径失败:
切换备用路径。
比如:
支付系统。
如果微信支付不可用。
可能切支付宝。
如果支付宝不可用。
可能使用银行卡。
系统不会因为一个服务异常就停止。
人生也应该如此。
例如:
职业系统
主路径:
当前工作
备用路径:
行业能力
+
个人品牌
+
人脉网络
+
副项目
财务系统
主路径:
工资收入
备用路径:
储蓄
+
投资
+
额外收入
+
技能变现
能力系统
主路径:
当前技术能力
备用路径:
业务理解
+
系统设计
+
沟通能力
+
内容输出
+
AI工具能力
防御性设计的核心:
不是准备逃跑。
而是:
让自己拥有更多选择。
七、不要把所有资源投入同一个方向
这是投资里面常说的:
不要把所有鸡蛋放在一个篮子里。
软件架构里叫:
避免高度耦合。
人生也是。
很多人年轻时没有问题。
因为单一路径增长很快。
但是到了某个阶段:
风险开始集中。
比如:
所有时间投入工作。
所有学习围绕岗位。
所有关系来自公司。
所有收入来自工资。
所有身份来自职业。
这个系统效率很高。
但是:
抗风险能力很低。
因为:
任何一个变化,都可能影响全部。
所以我越来越重视:
资源隔离。
八、给自己建立几个“隔离层”
软件系统里,会通过隔离减少故障传播。
人生也需要。
我现在越来越倾向于建立几个隔离层:
第一层:现金流隔离
目标:
不要让一次职业变化影响基本生活。
例如:
建立安全储备。
降低固定支出。
增加收入来源。
第二层:能力隔离
目标:
不要让一个技术方向决定全部价值。
例如:
从:
“会某个技术的人”
升级到:
“能够解决复杂问题的人”。
第三层:身份隔离
目标:
不要把全部自我价值绑定一个角色。
不是:
“我是一个程序员,所以……”
而是:
“我是一个持续学习、创造价值的人。”
程序员只是当前版本。
第四层:情绪隔离
目标:
不要让一个事件影响整个系统。
比如:
工作受挫。
不要自动推导:
人生失败。
这是典型的:
异常传播。
九、给重大决策增加“异常处理”
代码里:
关键流程都会有:
try-catch。
不是因为期待错误。
而是:
提前定义错误处理方式。
人生重大选择也一样。
比如:
换工作。
创业。
转型。
搬家。
投资。
都可以问:
如果结果不好怎么办?
如果收入下降怎么办?
如果方向错误怎么办?
如果半年没有结果怎么办?
如果重新开始怎么办?
很多人不愿意问这些问题。
因为感觉像是在给自己泼冷水。
但实际上:
这是在提高系统稳定性。
十、防御性编程的最高境界:允许变化
以前我以为:
稳定意味着:
不要变化。
后来发现:
真正稳定的系统,恰恰允许变化。
比如:
互联网系统。
每天都有新请求。
新的用户。
新的数据。
新的问题。
但是系统依然稳定。
为什么?
因为它具备:
弹性。
扩展能力。
容错能力。
恢复能力。
人生也是。
真正的稳定不是:
我的工作永远不会变化。
我的收入永远不会下降。
我的计划永远不会调整。
真正的稳定是:
即使变化发生,
我依然能够重新组织资源。
十一、我开始给自己写“人生异常处理规则”
以前遇到问题,我靠临场反应。
现在我希望提前设计一些规则。
比如:
异常:
工作环境发生重大变化
处理:
1. 不立即恐慌
2. 收集真实信息
3. 评估影响范围
4. 检查备用方案
5. 再决定行动
比如:
异常:
长期没有成长感
处理:
1. 检查能力结构
2. 判断行业变化
3. 增加新能力输入
4. 创建小规模实验
比如:
异常:
情绪持续低落
处理:
1. 降低当前负载
2. 检查睡眠和身体
3. 减少刺激输入
4. 寻找支持
5. 必要时寻求专业帮助
这些规则的意义:
不是让人生变得机械。
而是:
减少自己在异常状态下做错误决策。
十二、人生不是写一次代码,而是长期维护系统
工作几年以后,我越来越理解:
真正复杂的软件系统,不是开发完成那一天。
而是上线以后。
因为:
用户会变化。
需求会变化。
环境会变化。
依赖会变化。
所以系统需要:
持续维护。
持续优化。
持续重构。
人生也是。
20岁的时候写了一版。
30岁的时候升级了一版。
40岁的时候发现:
很多代码需要重构。
一些模块需要删除。
一些能力需要重新设计。
一些架构需要调整。
这不是失败。
这是:
正常迭代。
写给未来自己的代码注释
// 不要假设世界永远稳定
// 外部输入永远需要验证
input = receive();
if (!validate(input)) {
handleException();
}
// 不要让单点故障决定人生
if (dependency.count == 1) {
addBackup();
}
// 不要追求没有失败
// 而是降低失败影响
try {
experiment();
}
catch(Exception e) {
recover();
learn();
iterate();
}
// 系统真正的稳定性
// 来自弹性,而不是静止
while(life.running){
monitor();
adjust();
improve();
}
写在最后
以前我一直觉得:
人生最大的能力,是努力。
后来我发现:
努力当然重要。
但对于一个已经运行几十年的系统来说,
还有一种能力同样重要:
抗变化能力。
因为未来一定会出现:
没有预料到的问题。
没有计划中的变化。
没有准备好的挑战。
我们无法提前写完人生所有异常处理代码。
就像程序员无法预测所有线上问题。
但是我们可以做一件事情:
让自己的系统拥有更好的容错能力。
拥有多个收入来源。
拥有可以迁移的能力。
拥有持续学习的能力。
拥有健康的身体。
拥有稳定的关系。
拥有面对变化时重新调整的能力。
这些东西,就是人生里的:
防御性编程。
它不是让你活得更谨慎。
而是让你拥有更多选择。
因为真正强大的系统,
不是永远不会出错。
而是:
即使错误发生,也不会轻易崩溃。
我是语霖。
执笔为语,心落成霖。
希望用文字和声音,记录一个40岁程序员重新设计人生系统的过程。
我们下期接着聊。