为什么有些前端开发者能快速交付,有些还在纠结架构设计
最近在code review时发现了个有趣的现象:两个水平差不多的开发者做同一个需求,一个2小时完成,另一个花了两天还在"优化架构"。差别不大,但效率天差地别。
后来我意识到,他们用的其实是两种完全不同的思维方式。
我们大多数人的做法(先想再写)
假设现在要做一个用户资料编辑页面,用户可以切换账户、偏好设置、安全这三个tab。
咱们通常的思路是:
需求分析(15分钟)
整理一下有哪些字段需要编辑
需要什么API接口
技术方案讨论(30-60分钟)
这个状态管理用什么?Redux、Zustand、还是Context API?
要不要分离到多个组件?
文件夹结构怎么组织?
搭建基础架构(1-2小时)
创建各种文件夹
装各种库
写一堆boilerplate code
才开始写业务代码(2小时+)
这个过程本身没啥问题,问题是:我们花在"怎么做"的时间,往往比花在"做"的时间还长。
那些快速交付的人,怎么思考的?
他们其实是这样的:
直接想象UI(5分钟)
就想象一下,一个页面上三个按钮,下面有内容区
点不同按钮,显示不同内容
写最简单能用的版本(30分钟)
export default function UserProfile() {const [tab, setTab] = useState('account');return (<div><button onClick={() => setTab('account')}>账户</button><button onClick={() => setTab('preferences')}>偏好</button><button onClick={() => setTab('security')}>安全</button>{tab === 'account' && <div>账户内容</div>}{tab === 'preferences' && <div>偏好内容</div>}{tab === 'security' && <div>安全内容</div>}</div>); }
就这样。没有Redux,没有复杂的文件结构,就是让它能跑起来。
看着代码,优化一遍(1小时)
发现切换tab时,各个tab的状态需要同时保存
把它们改成一个对象管理,用useReducer
把每个tab拆成独立组件
整理一下代码
搞定
这样算下来,总时间反而更少。而且最关键的是:代码从第30分钟就能跑起来,能看得到。
为什么这个方法有效?
说起来有点矛盾,但确实是这样:当你看到代码跑起来以后,你才知道真正需要什么。
纸上谈兵的时候,你能想象出各种复杂场景:
"这个状态可能会在很多地方共享,用Redux吧"
"功能以后肯定会扩展,要设计好扩展性"
"代码要规范,得遵循最佳实践"
但实际开发时你会发现:
状态其实只在两个组件间传递,useState就够了
一个月过去了,功能一个字都没扩展
你花在"遵循最佳实践"上的时间,比花在"解决真实问题"上的时间还多
所以那些快速交付的人,他们并不是"不讲究",而是先看到问题,再对症下药。
两种方式的真实对比
假设现在有10个类似的需求要做,分别用这两种方式:
方式A:先架构后编码
第1个需求:8小时(架构+编码)
第2-10个需求:各2小时(因为架构已经定了)
总耗时:26小时
方式B:先简单后优化
第1个需求:2小时
第2个需求:2.5小时(优化了一些细节)
第3个需求:2小时
第4个需求:发现一个共同模式,抽象一下,3小时
第5-10个需求:各1.5小时(模式已经沉淀了)
总耗时:15小时
而且方式B还有个好处:前两个小时,代码就跑起来了,产品经理能看到东西。
这不是说"随便乱写"
有个很重要的点要说清楚:这不是鼓励大家写烂代码。
Build-First的意思是:
先写能用的代码
然后看着代码判断需要什么优化
再逐步演进代码结构
不是说不要设计,而是设计的时机不一样。
举个例子,一开始写的时候:
// 有点rough,但能跑 const [account, setAccount] = useState(initialAccount); const [pref, setPref] = useState(initialPref); const [security, setSecurity] = useState(initialSecurity);
跑了一阵子以后,你会发现有一个共同的模式 —— 三个状态的操作逻辑类似。这时候再统一起来:
// 现在才优化 const [profile, dispatch] = useReducer(reducer, initialProfile);// 一个action处理所有更新 dispatch({ type: 'UPDATE_FIELD', tab: 'account', field: 'name', value: '...' });
这个重构是在看到了真实问题以后才做的,而不是在"猜测可能有这个问题"的时候就提前设计。
真正的问题在哪儿?
我觉得很多人被教"坏"了。
上学时,老师教设计模式、教架构思想,这些本身都没错。但问题是,学完以后我们就开始过度应用。
一个三人小项目,也要考虑"未来的扩展性"。一个简单的表单,也要套用MVC模式。两个组件共享一个布尔值,也要上Context API。
时间久了,我们就养成了一个习惯:必须把架构设计好了,才能开始写代码。
但如果你观察那些高效能的开发者,他们的做法恰好相反。他们知道什么时候应该简单,什么时候应该复杂。
如果你想试试看
可以从下一个需求开始试试:
第一步(15分钟)
不要想太多,直接想象UI长什么样
把最简单的版本写出来
第二步(编码中)
当你遇到问题时,解决问题
不要提前预测问题
第三步(review时)
看着代码,问自己:这个结构对吗?
如果发现了问题,就改
没有就leave as is
第四步(下次做类似需求时)
你就会自然而然地用上次的经验
不是生硬地套用架构,而是有根据地做出决策
这样坚持下去,你会逐渐发展出一套自己的"经验库"。新需求来时,你能快速判断:"这个需要简单方案"或者"这个需要上状态管理"。
这个直觉,就是那些快速交付开发者的秘密。
再说一遍核心点
我们都想写高质量代码,但有时候我们把"高质量"理解错了。
"高质量"不是提前考虑所有可能,而是能快速响应真实需求。
不是最完美的架构,而是最合适当前场景的设计。
下次再听到"这个功能架构还没定呢"的时候,可以反问一下:真的需要提前定吗?还是能先跑起来再说?
很多时候,答案会让你惊讶。