第十章 代码
第一节 更少的软件
尽可能让代码保持简洁
你认为两倍的代码量只会让你的软件复杂程度增加两倍。但实际上,每次增加代码量,软件复杂程度都是指数级别增长的。每个轻微的增量,每个改变,每个相关性,每个设置选项都有层叠效应。当你在不经意间草率地增加代码时,你已经造出了一个恐怖的大泥潭。
对抗这种复杂性的方式就是减少软件数量。更少的软件意味着更少的功能,更少的代码,更少的浪费。
关键是把需要大量软件的难题转变为需要更少软件的简单问题。或许你并没有解决相同的问题,但是没关系。用 20% 的工作解决了原始问题的 80%,这是个不小的胜利。原始的问题通常没有这么糟糕,以至于需要五倍的工作时间来解决。
更少的软件意味着你放弃了水晶球。你只专注于解决今日的问题,而不是尝试去预测未来的问题。为什么?你对明日的恐惧通常都不会实现。不要为了解决这些幽灵问题而陷入困境。
从一开始,我们对产品的设计概念就基于更少的软件。我们尽可能把难题分解成容易消化的小问题。用于解决简单问题的方案不仅更容易部署和支持,也更易于理解和使用。这是我们区别于竞争对手的一部分。我们创造功能更专注的产品,而不是大而全的产品。
- 更少的软件易于管理
- 更少的软件能减小代码库
- 更小的代码库能降低维护成本
- 更少的软件能降低改变成本,让你快速应变。
- 无需改变大量代码,带来了更少的 bug
- 更少的软件意味着更少的技术支持
不要害怕对复杂的功能说不。除非功能是必须的,否则将其排除,这可以节省大量的时间、工作量和困惑。
慢慢来。在最初的兴奋消退之后,再来评估一个想法是否可靠。额外深入的思考时间能帮助你找到更简易的解决方案。
鼓励程序员还价
你希望听到:“你所建议的方案需要 12 小时来实现,但是我又一个方法只需要 1 个小时。它不能做这个,但是可以实现另一个功能。”让程序员找到他们认为最佳的实施方案。
寻找绕开编写更多的代码的途径。是否可以建议用户使用一个替代路径,从而无需对软件模型做出修改?例如:是否可以建议客户上传指定尺寸的图片,这样就不用在服务器端进行图像处理了。
对于 app 中的每个功能,问问你自己:是否有另外一个方法,可以不需要这么多代码就实现这个功能?只编写你需要的功能,仅此而已。你的 app 会变得更精益,更健康。
没有什么代码比没有代码更灵活
设计优秀软件的“秘密”不在于添加代码,而是知道应该把哪些内容拿掉。你应该知道在何处留白,而不是过度设计。
—— Brad Appleton, 软件工程师,(from 没有什么代码比没有代码更灵活 )
复杂度与规模不成线性比例
软件工程一个最重要的规则,却也是最不为人所知的:复杂度与规模不成线性比例... 一个 2000 行的程序与 1000 行的程序相比,需要超过 2 倍的时间来开发。
—— The Ganssle Group (from 保持小巧)
第二节 为快乐而优化
寻找能够让团队保持兴奋和动力的工具
快乐的程序员是高效的。这就是为何我们为快乐而优化,你也该如此。不要依据工业标准或性能指标来选择工具。关注一下无形资产:这里是否有激情、荣耀和技艺。在这样的环境下每日工作八小时,你是否开心?
这对于编程语言的选择是特别重要的一点。任何语言都可以完成目标,关键是这个语言是否让过程变得更愉悦。一切都是为了把日常工作中的小细节变得有趣。
快乐有层叠效应。快乐的程序员做正确的事。他们编写简单、易读的代码,他们采取简洁、优雅的方法。他们充满乐趣。
我们在 Ruby 语言中找到了编程的乐趣,并把这种快乐传递给其它使用我们的 Rails 框架的开发者。共享了一个为人类和他们的快乐而优化的使命感。
总之,你的团队应该使用他们喜爱的工具。我们在这里谈论的是编程语言,但这个概念同样适用于应用、平台和其它任何事情。选择让人们兴奋的工具,你会收获一个更好的产品。
你想要的工程师
我选择 Ruby on Rails 来搭建应用的首要原因是,它如此优雅,高效,设计精美。在乎这些品质的工程师会被其所吸引。这些工程师就是你的团队需要的,因为他们能创造出美丽、优雅、高效的产品为你赢下市场。
—— Charles Jolley, Nisus Software 管理总监 (from Signal vs. Noise)
第三节 代码会说话
当代码抗拒时,仔细倾听
倾听你的代码。它会提供建议。它会抗拒。它会告诉你哪里有陷阱。它会建议做事的新方法。它会帮助你坚持精简软件的模式。
一个新功能是否需要数周的时间和几千行的代码?这是你的代码在告诉你或许有个更好的方式。是否有一个简单的方法让写代码的时间减少 90%?再次,这是你的代码在引导你。仔细倾听。
你的代码可以引导你找到廉价而轻便的修正方法。一个简单的方法出现时要多加注意。当然,更容易实现的功能或许和你最初设想的功能有出入,但这有什么关系呢?如果它工作得很好,并且能给你更多的时间处理其它事情,它就值得保留。
仔细倾听
不要担心设计,如果你倾听代码,好的设计就会出现 ... 倾听技术人员的想法。如果他们在抱怨改变的难度,认真对待这些抱怨,给他们进行修复。
—— Martin Fowler, ThoughtWorks 首席科学家 (from 设计死了吗?)
如果付钱让程序员移除代码
如果付钱给程序员移除代码,而不是写新代码,软件会好的多。
—— Nicholas Negroponte, MIT 媒体技术教授 (from (AIGI 会议)剩余的故事)
第四节 管理债务
支付你的代码和设计“账单”
我们通常认为债务就是关于钱的,但它还有其它的形式。你很容易积累代码和设计上的债务。
将一些不好的代码组合起来,虽然具备了功能性,但还是有些杂乱,这样你就产生了债务。用一个凑合的设计代替真正好的设计,你又积累了一些债务。
偶尔发生这种情况是正常的。实际上,这是一个必需的技巧,帮助你应付一些需要尽快完成的工作。但你需要认识到这是一种债务,并在某些时刻进行偿还,无论是清理杂乱的代码或是重新设计那些平庸的页面。
就像你需要定期地支付所得税,你同样需要定期支付代码和设计的债务。如果不这么做,你就要支付利息(修修补补),而不是偿还本金(继续前进)。
第五节 敞开大门
通过 RSS ,API 等方式将数据传出
不要尝试锁定你的客户。让他们在需要时可以获取信息。你要放弃封闭数据的想法,让数据肆意生长。让人们通过 RSS 来获取信息。提供 API 给第三方开发者。这样做,可以让客户的生活变得更方便,也扩张了 app 的可能性。
人们过去认为 RSS 订阅仅仅是一个追踪博客和新网站的工具。但它其实有更强大的功能。它为客户提供了一个无需频繁登录就能使 app 数据保持更新的绝佳方式。通过 Basecamp 订阅,用户可以将 URL 地址导入新闻阅读器,随时追踪项目讯息、待办列表等,无需频繁通过网站来确认。
API 可以让开发者为你的 app 开发附件,这是无价的。例如,Backpack 提供了一个 API ,Chipt Productions 用它开发了一个 Mac OS X 的桌面插件。这个插件让用户可以在桌面上直接添加、编辑提醒事件,列表项目等。用户对这个插件大加赞赏,有人甚至说这是他们使用 Backpack 的关键因素。
公司开发数据从中受益的例子还有:
- 谷歌地图 API 提供了一些有趣的功能,让用户能从其它数据源提取信息,将数据点标注在地图上。
- Linkrolls 提供了一个工具,让用户可以把 del.icio.us 上的最新书签显示在自己的网站上。
- Flickr 运行其它公司使用他们的商业 API ,让客户可以购买相册,海报,DVD和邮票。“我们的目标是完全开放,当你处理自己的照片时,可以有最大程度的选择。”Flickr 的 Stewart Butterfield 如是说。
插件的大作用
当 37signals 发布 Backpack 后,我们的第一印象是 ... 嗯。
就在这时,Chipt Productions 为 Tiger 系统发布了一个 Backpack 插件,它太酷了,让我忍不住尝试,这也给了 Backpack 第二次机会。结果呢?大不相同。
现在,每当我想的什么点子,我打开这个插件,输入,提交,一切搞定。收到一封我想看的邮件?打开插件,输入,提交,一切搞定。我把这个能迅速把想法记录下来的工具装在了我使用的每台 Mac 上。因为一切都是基于网络的,无需任何的版本控制和同步,只需流畅地输入内容,无需担心内容去向何处以及之后如何接收。
—— Todd Dominey, Dominey Design 创始人 (from 试用 Backpack)