文章摘要
在软件系统设计中,应始终采取最简单可行的方案。许多工程师倾向于设计“理想”系统,但正确的方法是深入理解现有系统,然后实施最简单的解决方案。真正的掌握在于学会何时减少而非增加复杂性,这与新手和大师之间的差异类似。
文章总结
标题:做最简单可行的事
在设计软件系统时,始终遵循“做最简单可行的事”这一原则。这一建议的适用范围之广令人惊讶,无论是修复漏洞、维护现有系统,还是构建新系统,都可以采用这一方法。
许多工程师在设计时追求“理想”系统:高度模块化、近乎无限扩展、优雅分布式等。然而,这种思维方式往往是错误的。相反,应该花时间深入理解当前系统,然后做最简单可行的事。
简单可能显得平淡无奇
系统设计涉及多种工具的应用,如应用服务器、代理、数据库、缓存、队列等。随着对这些工具的熟悉,初级工程师自然希望使用它们。构建由多个组件组成的系统很有趣,画框图和箭头也让人感到满足,仿佛在进行真正的工程。
然而,真正的精通往往在于学会何时少做,而不是多做。就像武术电影中的经典场景:新手动作花哨,而大师则静待时机,最终一击制胜。在软件设计中,优秀的设计往往显得平淡无奇,甚至让人感觉“问题原来这么简单”或“原来不需要做任何复杂的事”。
例如,Unicorn 是一个优秀的设计,因为它通过依赖 Unix 原语实现了 Web 服务器最重要的功能(请求隔离、水平扩展、崩溃恢复)。Rails REST API 也是一个优秀的设计,因为它以最直接的方式提供了 CRUD 应用所需的功能。这些设计之所以令人印象深刻,正是因为它们“做了最简单可行的事”。
为什么要做最简单的事?
当然,始终做最简单的事也存在三个主要问题:首先,不预见未来需求可能导致系统僵化或成为“泥球”;其次,“最简单”的定义不明确,可能导致设计混乱;第三,系统应具备扩展性,而不仅仅是当前可用。
泥球问题
一些工程师认为,“做最简单的事”意味着停止工程思维。如果最简单的事通常是快速修补,这是否意味着最终会导致系统混乱?我们见过许多由层层修补组成的代码库,它们显然不是好的设计。
然而,修补真的简单吗?实际上并非如此。修补的问题在于它增加了复杂性,而不是简化了系统。找到正确的解决方案需要深入理解整个代码库,而正确的解决方案往往比修补更简单。
什么是简单?
工程师们对“简单代码”的定义存在分歧。如果“最简单”已经意味着“良好的设计”,那么“做最简单的事”是否只是同义反复?例如,Unicorn 是否真的比 Puma 更简单?内存中的速率限制是否比使用 Redis 更简单?简单的系统通常具有较少的“移动部件”和较低的内部连接性。
为什么不需要过度扩展?
某些工程师可能会质疑:“内存中的速率限制无法扩展!”做最简单的事确实无法构建出最具扩展性的系统,但它能构建出在当前规模下运行良好的系统。过度设计以应对未来规模的增长往往会导致不必要的复杂性,而实际上,你无法准确预测系统在更大规模下的表现。
总结
在技术领域工作的时间越长,越难预测系统的未来发展方向。理解系统的现状已经足够困难,而这也是良好设计的主要挑战:准确理解系统的全局。大多数设计缺乏这种理解,因此往往不尽如人意。
软件开发有两种主要方式:一种是预测未来六个月或一年的需求,并设计最佳系统;另一种是根据当前需求设计最佳系统,即做最简单可行的事。
评论总结
评论主要围绕“最简单的解决方案是否总是最佳选择”展开,观点多样且相互补充。以下是总结:
支持简单性: - 简单性带来稳健性:多位评论者认为,简单的系统更易于维护和修改,尤其是在需求不断变化的环境中。例如,jumploops提到:“简单即稳健”,并指出复杂的架构会随着时间的推移变得更加脆弱。 - 避免过度设计:bvirb指出,过度预测未来需求往往浪费时间和精力,而简单的系统更容易修复和迭代。
对简单性的质疑: - 简单性难以定义:多位评论者指出,“简单”和“工作”的定义并不明确。例如,oncallthrow质疑:“什么是‘简单’?‘工作’又意味着什么?” - 简单性不适用于所有场景:0xbadcafebee强调,简单性在某些场景(如核反应堆控制)中并非首要考虑,而在其他场景(如脚本编写)中则无关紧要。 - 简单性可能带来技术债务:ternaryoperator提到,Ward Cunningham和Kent Beck虽然推崇简单性,但也意识到这会带来技术债务。
简单性与复杂性的平衡: - 经验的重要性:GMoromisato指出,简单性原则最适合有经验的开发者,因为他们能够更好地判断什么是“最简单的解决方案”。 - 现代基础设施的影响:spectraldrift认为,现代云基础设施改变了“简单性”的定义,使用托管服务(如DynamoDB)可能是更简单的选择,因为它们处理了分布式状态等复杂问题。
其他观点: - 简单性作为启发式方法:mindcrime建议将简单性视为一种启发式方法,而非铁律,允许根据具体情况进行调整。 - 简单性与市场竞争:0xbadcafebee提到,在某些竞争激烈的市场中,简单性可能成为竞争优势。
总结:虽然简单性在许多情况下是值得追求的目标,但其适用性取决于具体场景和开发者的经验。简单性不应被视为绝对原则,而应作为一种灵活的指导方针,结合实际情况进行权衡。