软件架构设计的30条原则

Srinath,是一位科学家,软件架构师,也是一名在分布式系统上工作的程序员。他是 Apache Axis2 项目的联合创始人,也是 Apache Software 基金会的成员。他是 WSO2 流处理器的联席架构师。

架构师的角色应该由开发团队本身去扮演,而不是专门有个架构师团队或部门。而不是专门有个架构师团队或部门。Srinath 认为架构师应该扮演的角色是一个引导者,讨论发起者,花草修建者,而不是定义者和构建者。Srinath 为了解决团队内部的架构纷争和抉择,制定了以下 30 条原则,这些原则被成员们广泛认可,也成为了新手架构师的学习途径。

一、基本原则(Basic)

1、原则1

原则 1:KISS(Keep it simple, sutpid)保持每件事情都尽可能的简单。用最简单的解决方案来解决问题。

Principle 1: KISS (Keep it simple, stupid) and “Everything should be made as simple as possible, but not simpler.” The idea is to use the simplest solution that does the job.

点评:简单即是复杂!拿你的代码来说,你想要写的简单且容易理解的话,你就需要花更多的时间去思考。

2、原则2

原则 2:YAGNI(You aren’t gonna need it)不要去搞一些不需要的东西,需要的时候再搞吧。

Principle 2: YAGNI (You aren’t gonna need it) — do not build it until it is needed.

点评:这一点我被 diss 过好几次,之前的时候,我总是臆想觉得某个功能以后可能会用到,然后就顺手把它实现了,实际到了后面并没用上,反而造成了代码冗余。

3、原则3

原则 3: 爬,走,跑。换句话说就是先保证跑通,然后再优化变得更好,然后继续优化让其变得伟大。迭代着去做事情,敏捷开发的思路。对于每个功能点,创建里程碑(最大两周),然后去迭代。

Principle 3: Crawl, walk, run. In other words, make it work, make it better, make it great. Do Iterative Development — do agile, iterative development. For every feature, create milestones (2 weeks maximum) and iterate.

4、原则4

原则 4:创建稳定、高质量的产品的唯一方法就是自动化测试。所有的都可以自动化,当你设计时,不妨想想这一点。

Principle 4: The only way to build stable, high-quality products is via automated tests. Be creative with automated tests; everything can be automated! Think about this when you design.

点评:单侧还是很有必要的,但是没有一个恒定的标准说你应该怎么去做。

5、原则5

原则 5: 时刻要想投入产出比(ROI)。就是划得来不。

Principle 5: Always think Return for Investment (ROI) and invest most attention on making the most impact.

6、原则6

原则 6: 了解你的用户,然后基于此来平衡你需要做哪些事情。不要花了几个月时间做了一个 devops 用户界面,最后你发现那些人只喜欢命令行。此原则是原则 5 的一个具体表现。

Principle 6: Know your users and balance your efforts accordingly. For most products, there will be thousands of end users, 20 developers that extend the product, and 100 DevOp personals who set it up. For example, do not spend months building a UI forDevOp who is unlikely use it anyway ( they like scripts! instead). This is a special case of Principle 5.

点评:是否有站在用户的角度思考问题呢?是否是为了用新技术而用新技术?

7、原则7

原则 7:设计和测试一个功能,尽可能的独立。当你做设计时,应该想想这一条。从长远来看这能给你解决很多问题,否则你的功能只能等待系统其他所有的功能都就绪了才能测试,这显然很不好。有了这个原则, 你的版本将会更加的顺畅。

Principle 7: Design and test features as independently as possible. Think about this when you design. It will save a lot of trouble in the long run, as otherwise, you can’t test the system until everything is built. Also, with this principle, your releases will be smoother.

8、原则8

原则 8: 不要搞花哨的。我们都喜欢高端炫酷的设计。最后我们搞了很多功能和解决方案到我们的架构中,然后这些东西根本不会被用到。

Principle 8: Look out for “Google envy.” We all like shiny designs. It is easy to bring features and solutions into your architecture that you will never need.

点评:简单点!说话的方式简单点!

二、功能选择(Choosing Features)

1、原则9

原则 9: 不可能预测到用户将会如何使用我们的产品。所以要拥抱 MVP(Minimal Viable Product),最小可运行版本。这个观点主要思想就是你挑几个很少的使用场景,然后把它搞出来,然后发布上线让用户使用,然后基于体验和用户反馈再决定下一步要做什么。

Principle 9: It is impossible to fully think through how users will use our product. So embrace the MVP (Minimal Viable Product). The idea is to figure out few use cases, only do features that support those, ship the product, and shape the future product based on feedback and experience.

2、原则10

原则 10: 尽可能的做较少的功能。当有疑问的时候,就不要去做,甚至干掉。很多功能从来不会被使用。最多留个扩展点就够了。

Principle 10: Do as few features as possible; when in doubt, leave it out. Many features are never used; maybe you leave an extension point instead.

3、原则11

原则 11: 等到有人提出再说(除非是影响核心流程,否则就等到需要的时候再去做)。

Principle 11: Wait for someone to ask for it (e.g. for features that are not deal-breakers, wait until it is needed).

4、原则12

原则 12:有时候你要有勇气和客户说不。这时候你需要找到一个更好的解决方案来去解决。记住亨利福特曾经说过的 :”如果我问人们他们需要什么,他们会说我需要一匹速度更快的马”。记住:你是那个专家,你要去引导和领导。要去做正确的事情,而不是流行的事情。最终用户会感谢你为他们提供了汽车。

Principle 12: Have the courage to fight the customer if features he asks for mess up the big picture. Find out the bigger picture and try to find another way to handle the problem. Remember Henry Ford’s quote: “If I had asked people what they wanted, they would have said ‘faster horses.’” Also, remember you are the expert. You are supposed to lead. It is the leader’s job to do what is right, not what is popular. Users will thank you later.

三、服务端设计和并发(Server Design and Concurrency)

1、原则13

原则 13:要知道一个 server 是如何运行的,从硬件到操作系统,直到编程语言。优化 IO 调用的数量是你通往最好架构的首选之路。

Principle 13: Know how a server works, from the hardware to the operating system, up to your programming language. Optimizing the number of IO calls is the first guiding lights towards the best architecture.

2、原则14

原则 14: 要了解 Amdhal 同步定律。在线程之间共享可变数据会让你的程序变慢。只在必要的时候才去使用并发的数据结构,只在必须使用同步(synchronization)的时候才去使用同步。如果要用锁,也要确保尽可能少的时间去 hold 住锁。如果要在加锁后做一些事情,要确保自己在锁内会做哪些事情。

Principle 14: Know Amdhal’s law about synchronization. Mutable data shared between threads slows your program. Use concurrent data structures if you can, and use synchronization only if you must. Try to hold the locks for as little time as possible. If you plan to block while holding a lock, make sure you know what you are doing. If it can break, it will.

3、原则15

原则 15:如果你的设计是一个无阻塞且事件驱动的架构,那么千万不要阻塞线程或者在这些线程中做一些 IO 操作,如果你做了,你的系统会慢的像骡子一样。

Principle 15: If your design is a none-blocking, event-driven architecture, never block threads or do IO from those threads. If you do, the system will be as slow as a mule.

四、分布式系统(Distributed Systems)

1、原则16

原则 16:无状态的系统的是可扩展的和直接的。任何时候都要考虑这一点,不要搞个不可扩展的,有状态的东东出来,这是起码的。

Principle 16: Stateless systems are scalable and straightforward. Know and use Shared Nothing Architecture whenever possible.

2、原则17

原则 17:保证消息只被传递一次,不管失败,这很难,除非你要在客户端和服务端都做控制。试着让你的系统更轻便(使用原则 18)。你要知道大部分的承诺 exactly-once-delivery 的系统都是做了精简的。

Principle 17: Exactly once message delivery, regardless of failures, is hard unless you control code in both the client and server. Try to design your systems to need less (use Principle 18). Know that most systems that promise exactly-once-delivery cut corners somewhere.

3、原则18

原则 18:实现一个操作尽可能的幂等。这样的话就比较好恢复,而且你还处于至少一次传递(at least once delivery)的状态。

Principle 18: Implement operations as idempotent operations whenever possible. Then it is easy to recover, and you can live with at least once delivery.

4、原则19

原则 19: 知道 CAP 理论。可扩展的事务(分布式事务)是很难的。如果可能的的话,尽可能的使用补偿机制。RDBMS 事务是无法扩展的。

Principle 19: Know the CAP Theorem. Scaling transactions is hard. Use compensation when possible. RDBMS-based transactions do not scale.

5、原则20

原则 20: 分布式一致性无法扩展,也无法进行组通信,也无法进行集群范围内的可靠通信。理想情况下最大的节点限制为 8 个节点。

Principle 20: Distributed Consensus does not scale, nor do group communication, nor cluster-wide reliable messaging. Maximum node limit for either is about eight nodes in a good day.

6、原则21

原则 21: 在分布式系统中,你永远无法避免延迟和失败。

Principle 21: You can never hide latency and failures in a distributed system (see Fallacies of Distributed Computing Explained).

五、用户体验(User Experience)

1、原则22

原则 22: 要了解你的用户和清楚他们的目标。他们是新手、专家还是偶然的用户?他们了解计算机科学的程度。极客喜欢扩展点,开发者喜欢示例和脚本,而普通人则喜欢 UI。

Principle 22: Know your users and know their goals: is he a novice, expert, or casual user? How much does he know computer science? Geeks love extension points, developers like samples and scripts, normal people like UIs.

2、原则23

原则 23: 最好的产品是不需要产品手册的。

Principle 23: The best products do not need a manual. Its use is self-evident.

点评:这个是说产品易用。很多人觉得敏捷开发下不需要文档,实际上,一个系统即是在敏捷开发的情况下,有些必要的文档比如重大更新记录、相关硬件设施等等还是需要的。

3、原则24

原则 24: 当你无法在两个选择中做决定的时候,请不要直接把这个问题通过提供配置选项的方式传递给用户。这样只能让用户更加的发懵。如果连你这个专家都无法选择的情况下,交给一个比你了解的还少的人这样合适吗?最好的做法的是每次都找到一个可行的选项;次好的做法是自动的给出选项,第三好的做法是增加一个配置参数,然后设置一个合理的默认值。

Principle 24: When you cannot decide between two choices, do not pass on the problem by making it a configuration option. You are making the life hard for users and solution architects. If they know even less about how the system works than you, how can they decide? The best option is finding a choice that works every time; the next best is automatically making the choice, and the third best is adding a configuration parameter and setting a reasonable default.

4、原则25

原则 25: 总是要为配置设置一个合理的默认值。

Principle 25: Always have sensible defaults for configurations.

5、原则26

原则 26:设计不良的配置会造成一些困扰。应该总是为配置提供一些示例值。

Principle 26: Poorly designed configurations can create a lot of confusion. Always document a few example values for the configuration.

6、原则27

原则 27: 配置值必须是用户能够理解和直接填写的。比如:不能让用户填写最大缓存条目的数量,而是应该让用户填写可被用于缓存的最大内存。

Principle 27: Ask configuration values in terms of things the user can answer off his head without making calculations to set the value (e.g., do not ask for the number of max cache entries — instead ask for maximum memory that should be used for cache)

7、原则28

原则 28: 如果输入了未知的配置要抛出错误。永远不要悄悄的忽略。悄悄的忽略配置错误往往是找 bug 花了数小时的罪魁祸首。

Principle 28: Throw an error if you see an unknown configuration. Never ignore it silently. Silent configuration errors are the source of many lost hours while debugging.

六、艰难的问题(Hard Problems)

1、原则29

原则 29: 梦想着新的编程语言就会变得简单和明了,但往往要想真正掌握会很难。不要轻易的去换编程语言。

Principle 29: Dreaming up new languages is easy, but getting them right is very hard. Try not to do it unless the team can spend at least ten person-years on it. If you are still not sure, read Five Questions about Language Design.

2、原则30

原则 30: 复杂的拖拉拽的界面是艰难的,不要去尝试这样的效果,除非你准备好了 10 人年的团队。

Principle 30: Composable drag and drop UIs are hard, do not start one unless the team ready to invest ten person-years into it.

最后,说一个我的感受。在一个理想的世界里,一个平台应该是有多个正交组件组成-每个组件都负责一个方面(比如,security,messaging,registry,mdidation,analytics)。好像一个系统构建成这样才是完美的。

但不幸的是,现实中我们很难达到这样的状态。因为在项目初始状态时,很多事情是不确定的,你无法做到这样的独立性,现在我更倾向于在开始的时候适当的重复是必要的,当你尝试铲除他们的时候,你会发现引入了新的复杂性,分布本身就意味着复杂。有时候治愈的过程要比疾病本身更加的糟糕。

七、总结(Conclusion)

作为一个架构师,应该像园丁一般,更多的是修剪花草,除草而不是去定义和构建,你应该策划而不是指挥,你应该去修剪而不是去定义,应该是讨论而不是贴标签。

虽然在短期内可能会觉得也没什么,但从长远看,指导团队找到自己的方式会带来好处。如果你稍不留神,就很容易让架构成为一个空洞的词汇。比如设计者会说他的架构是错误的,但不知道为什么是错误的。一个避免这种情况的好办法就是有一个原则列表,这个原则列表是被广泛接受的,这个列表是人们讨论问题的锚点,也是新手架构师学习的路径。

原文链接:30 Shared Principles for Discussing Software Architectures

发表评论