BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

系统设计中的简单法则

| 作者 崔康 关注 1 他的粉丝 发布于 2012年5月7日. 估计阅读时间: 6 分钟 | CNUTCon 了解国内外一线大厂50+智能运维最新实践案例。

最近,包云岗在自己的博客中总结了系统设计中的基本法则——简单之美,列举了不少经典观点和案例。

他首先总结了麻省理工方法(MIT Approach)和新泽西方法(New Jersey Approach)的异同:

  • 简单性:两种方法都强调设计必须简单,这既是对实现的要求,也是对接口的要求。但是,MIT方法认为接口的简单要比实现的简单更加重要,而NJ方法认为实现的简单要比接口的简单更加重要。
  • 正确性:设计在任何值得注意的方面都要保证正确。但是,MIT方法认为不正确是绝对不允许的,而NJ方法认为,为了简单性,正确性可以做轻微的让步。
  • 一致性:MIT方法认为,设计必须保持一致兼容。设计可以允许轻微少量的不简单和不完整,来避免不一致。一致性和正确性同等重要。而NJ方法认为,设计不能过度不兼容一致。为了简单,一致性可以在某些方面做些牺牲,但与其允许设计中的这些处理不常见情况的部分去增加实现的复杂性和不一致性,不如丢掉它们。
  • 完整性:设计必须覆盖到实际应用的各种重要场景。所有可预料到的情况都必须覆盖到。MIT方法认为,简单性不能过度的损害完整性。NJ方法则认为,为了保证其它几种特征的品质,完整性可以作出牺牲。事实上,一旦简单性受到危害,完整性必须做出牺牲。一致性可以为实现的完整性作出牺牲;最不重要的是接口上的一致性。

包云岗还引用了一个案例来证明两种方法的差异:

一位MIT的教授一直困恼于Syscall处理时间过长出现中断时如何保护用户进程某些状态,从而让用户进程能继续执行。他问新泽西人,Unix是怎么处理这个问题。新泽西人说,Unix只支持大多数Syscall处理时间较短的情况,如果时间太长出现中断Syscall不能完成,那就会返回一个错误码,让用户重新调用Syscall。但MIT人不喜欢这个解决方案,因为这不是“正确的做法”

对于现在的互联网企业,是否还需要遵从这些法则呢?国外有篇博文《Scalability lessons from Google, YouTube, Twitter, Amazon, eBay, Facebook and Instagram》总结了各大公司的经验教训,其中第一条就是“保持简单”。但是包云岗认为,这和New Jersey Approach的原因和内涵有所不同。不同于Unix时代相对简单的单机系统,互联网时代的大公司的系统往往都是成千上万台机器,在这样的系统上部署、管理服务(软件)是一项非常有挑战的任务。而为大规模用户提供的一项服务往往会涉及到众多模块、若干步骤。此时“简单”就是要求每个阶段、每个步骤、每个子任务尽量采用最简单的解决方案,这是由于大规模系统内在的不确定性导致的复杂性决定的。

无独有偶,包云岗发现硅谷创业之父Paul Graham也推崇简单法则,Paul在《黑客与画家》的“设计者的品味”一章中写到,“好的设计是简单的”、“简单就是美,正如漂亮的数学证明往往是简短而巧妙的那种”。他提到,有些创业者希望第一版就能推出功能齐全的产品,满足所有的用户需求,但这种想法是致命的。在硅谷创业最忌讳的就是“Premature Optimization”。因为一方面用户需求是多样的,不同人群都有不同的需求;另一方面开发者想象的需求往往和真实的用户需求有偏差。所以,Graham推崇那种有用户参与反馈的迭代优化的方式。

包云岗还与普林斯顿大学计算机系的李凯教授有过简单法则的交流和讨论:

李凯老师的做事方式是——只抓住大方向,其他问题尽量简化。但真正要做到KISS原则其实并不容易。我在遇到问题时,往往会从各个方面去考虑问题,其中难免包含了各种细枝末节,这种方式导致问题经常会变得非常复杂。之前讲过这个例子,在移植TCP/IP协议栈到用户态时,我觉得有约10个功能需要考虑。和李老师讨论,他让我把那些功能分成两类:“必须有(Must Have)”和“可以有(Nice-to-Have)”。当我试了这种方法,发现原来Must-Have的功能其实也不过2~3个而已。而最近的例子则是在要设计一个功能让TCP/IP连接的Server在模拟器中、Client在真实机器。我考虑是尽量减少模拟器上OS的开销,所以打算采用自己写一个设备、然后让用户态程序Bypass Kernel直接访问该设备的方案。但李凯老师在了解OS开销以后,认为容忍开销、尽量直接使用模拟器自己带的功能,让开发更简单。

这些教训也让我不断地去思考为什么要用KISS原则。慢慢地我体会到,KISS原则目的其实是——“快速推进、逐步优化”。我们设计一个算法,往往可以在大脑中预先思考好,然后直接编程写出来。但是,我们设计实现一个系统,当系统的复杂度超出我们大脑的工作记忆容量时,就无法在大脑中去“模拟”每一个细节。此时,我们应该用最快的速度去把系统建起了,然后再对各个环节进行优化。

读者朋友对系统设计的简单法则有何看法?欢迎大家发表自己的意见。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

为了追求简单性而放弃正确性将导致系统整体复杂度提高 by 邓 嘉

rt

简单设计和简单操作的平衡 by 王 明军

简单不只体现在代码实现的简单,明晰,还应该体现在用户使用的易用、简单之上,但这之间就是一个需要平衡的地方!

更加认可MIT的方式 by 高 德翔

兼容性与正确性是保证程序可扩展性的前提。

win这样的操作系统都出来了 by 曹 力文

不管怎么做,win这样的操作系统都出来了,几千人的团队都可以协调工作。整个世界也再运转。

特别认同这句话 by wang sheng

“但是,我们设计实现一个系统,当系统的复杂度超出我们大脑的工作记忆容量时,就无法在大脑中去“模拟”每一个细节。此时,我们应该用最快的速度去把系统建起了,然后再对各个环节进行优化。”

架构设计也同样的道理--简单第一 by xuey he

我常常和同事们说的一句话就是“如果你发现自己的代码很复杂,那就要注意你在哪儿犯错了。”这不只是对程序员写代码的一句话,同样也适用到系统设计、架构设计,更可能是需求分析中。

Re: 特别认同这句话 by xuey he

个人观点:其实这时候你要做的事应该是去把复杂的事简单化。一层一层地去把复杂的简单化。如果你快速去建立你的系统后继等你的就是系统的重构之类的活。这时间模型化手段就有用了。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

7 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT