**[Keep It Simple, Stupid(KISS)](http://en.wikipedia.org/wiki/KISS_principle)** ,KISS原则在设计上可能最被推崇,在家装设计、界面设计和操作设计上,复杂的东西越来越被众人所鄙视了,而简单的东西越来越被人所认可。宜家(IKEA)简约、高效的家居设计和生产思路;微软(Microsoft)“所见即所得”的理念;谷歌(Google)简约、直接的商业风格,无一例外地遵循了“KISS”原则。也正是“KISS”原则,成就了这些看似神奇的商业经典。而苹果公司的iPhone和iPad将这个原则实践到了极至。
**Program to an interface, not an implementation**,这是设计模式中最根本的哲学,注重接口,而不是实现,依赖接口,而不是实现。接口是抽象是稳定的,实现则是多种多样的。在面向对象的S.O.L.I.D原则中会提到我们的依赖倒置原则,就是这个原则的另一种样子。还有一条原则叫 Composition over inheritance(喜欢组合而不是继承),这两条是那23个经典设计模式中的设计原则。
**[You Ain’t Gonna Need It (YAGNI)](http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It)** ,这个原则简而言之为——只考虑和设计必须的功能,避免过度设计。只实现目前需要的功能,在以后你需要更多功能时,可以再进行添加。如无必要,勿增复杂性。软件开发是一场trade-off的博弈。
**[Law of Demeter](http://en.wikipedia.org/wiki/Principle_of_Least_Knowledge)**,迪米特法则(Law of Demeter),又称“最少知识原则”(Principle of Least Knowledge),其来源于1987年荷兰大学的一个叫做Demeter的项目。克雷格·拉尔曼(Craig Larman)把Law of Demeter又称作“不要和陌生人说话”。在《程序员修炼之道》中讲LoD的那一章将其叫作“解耦合与迪米特法则”。
关于迪米特法则有一些很形象的比喻:1) 如果你想让你的狗跑的话,你会对狗狗说还是对四条狗腿说?2) 如果你去店里买东西,你会把钱交给店员,还是会把钱包交给店员让他自己拿?和狗的四肢说话?让店员自己从钱包里拿钱?这听起来有点儿荒唐,不过在我们的代码里这几乎是见怪不怪的事情了。对于LoD,正式的表述如下:
对于对象 ‘O’ 中一个方法’M’,M应该只能够访问以下对象中的方法:
- 对象O;
- 与O直接相关的Component Object;
- 由方法M创建或者实例化的对象;
- 作为方法M的参数的对象。
**LSP(Liskov substitution principle)- 里氏代换原则**。软件工程大师罗伯特·马丁(Robert C. Martin)把里氏代换原则最终简化为一句话:“Subtypes must be substitutable for their base types”。也就是,子类必须能够替换成它们的基类。即子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。另外,不应该在代码中出现if/else之类对子类类型进行判断的条件。里氏替换原则LSP是使代码符合开闭原则的一个重要保证。正是由于子类型的可替换性才使得父类型的模块在无需修改的情况下就可以扩展。
《[UNIX编程艺术](https://book.douban.com/subject/1467587/)》 ,这本书主要介绍了Unix系统领域中的设计和开发哲学、思想文化体系、原则与经验,由公认的Unix编程大师、开源运动领袖人物之一埃里克·雷蒙德(Eric S. Raymond)倾力多年写作而成。包括Unix设计者在内的多位领域专家也为本书贡献了宝贵的内容。本书内容涉及社群文化、软件开发设计与实现,覆盖面广、内容深邃,完全展现了作者极其深厚的经验积累和领域智慧。
[Avoid Over Engineering](https://medium.com/@rdsubhas/10-modern-software-engineering-mistakes-bc67fbef4fc8) ,有时候,我们会过渡设计我们的系统,过度设计会把我们带到另外一个复杂度上,所以,我们需要一些工程上的平衡。这篇文章是一篇非常不错地告诉你什么是过度设计的文章。
[Instagram Engineering’s 3 rules to a scalable cloud application architecture](https://medium.com/@DataStax/instagram-engineerings-3-rules-to-a-scalable-cloud-application-architecture-c44afed31406) ,Instagram 工程的三个黄金法则:1)使用稳定可靠的技术(迎接新的技术);2)不要重新发明轮子;3)Keep it very simple。我觉得这三条很不错。其实,Amazon也有两条工程法则,一个是自动化,一个是简化。
[How To Design A Good API and Why it Matters - Joshua Bloch](https://www.infoq.com/presentations/effective-api-design) ,Google的一个分享,关于如何设计好一个API。
关于Restful API的设计,你可以学习并借鉴一下下面这些文章。
- [Best Practices for Designing a Pragmatic RESTful API](https://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api)
- [Ideal REST API design](https://betimdrenica.wordpress.com/2015/03/09/ideal-rest-api-design/)
- [HTTP API Design Guide](https://github.com/interagent/http-api-design)
- [Microsoft REST API Guidelines](https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md)
- [IBM Watson REST API Guidelines](https://github.com/watson-developer-cloud/api-guidelines)
- [Zalando RESTful API and Event Scheme Guidelines](https://opensource.zalando.com/restful-api-guidelines/)
[The Problem With Logging](https://blog.codinghorror.com/the-problem-with-logging/) ,一篇关于程序打日志的短文,可以让你知道一些可能以往不知道的打日志需要注意的问题。
[Concurrent Programming for Scalable Web Architectures](http://berb.github.io/diploma-thesis/community/index.html) ,这是一本在线的免费书,教你如何架构一个可扩展的高性能的网站。其中谈到了一些不错的设计方法和知识。
# 小结
好了,总结一下今天分享的内容。我认为,“品位”不同,是各层次程序员之间最大的区别,这也决定了他们所做出来的软件的质量和价值。因此,我特意撰写了软件设计这一篇章,帮助那些想成长为软件工程师、设计师或架构师的程序员,提高软件设计的品位,进而实现自己的目标。
虽然很多程序员都忽略了对编程范式的学习,但我觉得学习编程范式其实是非常非常重要的事,能够明白编程的本质和各种语言的编程方式。为此,我推荐了好几份学习资料,帮助你系统化地学习和理解。随后我介绍了DRY-避免重复原则、KISS-简单原则、迪米特法则(又称“最少知识原则”)、 面向对象的S.O.L.I.D原则等多个经典的软件设计原则。
最后,我精选并推荐了软件设计方面的学习资料,如《领域驱动设计》、《UNIX编程艺术》和《Clean Architecture》等必读好书,以及如何构建SaaS,如何避免过度设计,如何设计API,如何用程序打日志等方面的资料。
希望这些内容对你有帮助。从下一篇文章开始,我们将进入《程序员练级攻略》的第五个篇章——高手成长篇。敬请期待。
下面是《程序员练级攻略》系列文章的目录。
- [开篇词](https://time.geekbang.org/column/article/8136)