本文翻译自:Why Software Architecture Matters
(https://www.imaginarycloud.com/blog/why-software-architecture-matters/)
抛开某项特定的技术或某个特定的项目不说,这篇文章我想讲讲关于犯错这个话题。
谈论和赞扬成功也许很轻松,但是我发现犯错仍是个很有意思的话题。主要是因为它们在学习的过程中颇有用处。
一开始我将讲一些背景知识,然后阐述一下我对软件架构的看法。 后者是我认为在软件开发过程中最重要的一部分,并且谈下如何避免陷入常见的开发陷阱。
预热阶段
当任何一个程序员被问到:
“哪种方式你更为热衷:从零开始一个项目,或者维护一个已存在的项目?”
他们通常回答:
“从零开始一个项目”
答案是显而易见的,因为成就感给人带来的感觉更棒。我们可以这样说:“这是我做的(至少是其中相当的一部分内容)。之前并不存在,而现在,看!就在眼前。”
但其中的意义往往不止于此。人类的大脑是喜欢有秩序的,它喜欢从一些混乱和看似随机的信息中寻找规律(模式),在软件开发中,这点也一样。
但是在一个已存在的项目中会发生什么?很可能这个项目已经掺杂一定程度的混乱,并且它的混乱程度显然比一个不存在的项目严重多了。
因此,最直接的回应(做法)是从头开始一个项目,这样的话你就可以完全通过你的经验来把控它的混乱度。
当然,在软件的乌托邦,我们永远不会因为疏忽大意而(给项目)造成混乱的局面。遗憾的是,我们并不是生活在那个世界,但是我们可以用工具和原则来指导我们。
优秀的架构省时省力
我们所拥有的用来处理回归复原、修复BUG等令人厌恶的任务的最好方式就是提前做规划。一个优秀的架构是我们的朋友。
一个优秀的设计解决方案顶得上数千个小时的时间,毕竟在未来它真的帮我们省掉了很多时间。
我们大多数都看过一些书,我们知道要做什么。我们同样应该认真地进行(软件)测试和应用设计模式。“让我们真正专注并贯彻于MVC(译注:一种将业务逻辑、数据和界面显示分离的软件设计模式);让我们为此采用BDD模式(译注:行为驱动开发,敏捷开发技术的一种);让我们在写生产代码前先设计特性测试。”
有时候,我们忘记了第一步该做什么的重要性,甚至在那之前。
架构
当然,在你写功能性代码前,是的,请写下你的第一个测试案例。
但在你写下第一个测试案例之前,设计团队有可能已经收集了所有的需求,已经与客户和其他利益相关方达成了协议,他们甚至可能已经出来了多个版本的产品设计方案并进行了多加验证,所以你可能会认为你应该立即进行代码的编写。
你应该做的
整个团队应该坐下来讨论关于他们将要开发的产品。他们应该拿出一张纸或者到白板面前,然后开始列举未来产品将要有的特性。
清晰地确定出所有的技术要求和提议方案的可行性。考虑在实施不同的实现方案中每一步所面临的挑战并为此想出解决措施,可能是(采用)不同的框架,甚至是不同的编程语言。
兜底地说,(在软件开发中)没有其他事情能值得你花的时间与花在架构一样多。
从错误中学习
对于我来说,最好的学习方式之一就是犯错。
尽管犯错会让人感到困窘和沮丧,但当我们真犯了错,我们就会投入精力去弄明白究竟发生了什么,会努力地寻找解决方案,找到不再犯同样错误的最好办法。
这就等同于经验。
经验就是错误的别称。
—— 奥斯卡·王尔德
最近我在做一个非常复杂的IOS项目。在项目刚开始的时候,有几件事情是没做好的。需求并没有百分百确定,先决条件并没有百分之百满足,APIs(应用程序接口)还没准备好……
但最重要的可能是:我们没有像我们应该做的那样定义出项目的架构。
当然,我是在出现损失时才意识到这点的。我们(当时)做了大量的还原、改写的工作,有几次我一直追问自己说:“为什么我没有采用正确的方式?”
一个陷阱是:没有使用测试框架。归根到底,测试和验证是通过用户测试和代码检视来完成的。然后当一个测试框架真正地被引进项目时,这已经太晚了。
一个热门的被众人所认可的IOS开发框架并不是都能适用于所有的复杂情况的,也并不一定适用于各种开发语言和弥补在设计产品架构时(从技术的角度来看)所作出的糟糕决策。
更好的方法:一些经验法则
敲黑板。你接到一个新项目,可能你在需求收集阶段就已经开始参与了。抛开脑海中已有的针对这项目的整体技术解决方案的想法,我会建议:
写下所有的东西。制作图表,画组件图、类图、流程图,写下所有你觉得有助于你和团队快速了解问题全貌的东西。
平时常拿出来进行反复思考,在写下第一行代码前可能会对其做多次的更改修正。
当所有的组件/模块已经定义好了,尝试为其找一些现有的可靠的解决方案。开源框架是一个很好的方向,因为它们已经被很多人测试过和使用过,因此也会比你自己实现的方案少很多的BUG。
当选择一个外部或第三方的框架时,确保它们与其他框架“合得来”。尽量找出足够的证据证明你将使用到的框架之间都能够很好地进行兼容。
在开发过程中你不得不更换某些框架,因为你发现某些部分在其他框架中运行时并没有像预期那样进行工作,不管怎样这都会迫使你耗费时间去另寻解决方案,同时这也会耗费你更多时间去做那些并不想做的回归工作。
选择一个好的测试框架。跟上一条相似,确保测试框架无需耗费你额外的精力就能与其他框架一起工作。
一个测试框架的好坏取决于它针对项目所能覆盖的测试范围。如果它对你将使用到的特定的技术和模块不是很合适或者不能完全进行覆盖,那就不要依赖它。
八个盖子十个锅并不是一个好的主意
对于下一个我将会参与到的项目,我会竭尽全力遵循这些原则并且在有必要的时候进行更新。也许这里的假定有一个或多个会有所改动或者被改善。
对于开始实施一个新项目时首先应该做什么这事,如果你的经历告诉你有不同的观点,你可以自由地分享你的观点和建议。