Developing scalable systems must comply with the 11 principles of software design

01 Simple

◆ hide the complexity and construct abstract

With the development of the system, you will find more and more complicated, may not understand all of the entire system, the limited processing power of each person's brain, it is impossible to know every detail of the system.


Therefore, to maintain a simple software can help you better understand the system. With the gradual expansion of the system, we can do is to keep the local simply can not maintain the overall simplicity.


When developing a system service, to create exposure to a higher level of abstraction, abstract achieve the promised features to hide its complexity.


◆ Avoid over-design

Our engineers generally prefer the challenges of difficult problems that may one simple question will make it complicated, making it possible to develop a code difficult to maintain. Early can build a reasonable level of abstraction, you can add new features to future iterations, so than the beginning of the design and development of complex systems more beneficial.


To develop a simple system easy to understand and can prove that the future is scalable is the real problem.


◆ try test-driven development TDD

TDD: Test Drive Develop. The first to write test cases, and then programming function.


Look at the problem from the user's point of view, help to develop a clearer and simpler interface.


◆ learn from the examples of software designed to simplify

Learning from the knowledge of the system or software, such as: Grails (details of the design is simple and easy to expand), Hadoop (hide a complex implementation, provide a very simple programming API), Google Maps API (Simple API, to ensure sufficient flexibility when solving complex problems) etc. .


Learning from good design and mode of software.


02 low coupling


We generally seek systems are high cohesion and low coupling. It is a measure of association and coupling dependence between the two systems. The higher the degree of coupling is represented by Laiyue Jiang.
High and low coupling system for coupling Effect :

① high coupling, the other part of the system may need to check the presence of the problem when you change the code;

② low coupling can be ensured complex regional, that is reflected in the complexity inside the module only, does not affect the whole system.

③ decoupled into different sub-system, parts of the system may require more CPU or IO more throughput capacity, or more memory applications. Different hardware configuration to achieve better scalability characteristics for different applications.


◆ promote low coupling

The most important practice to promote low coupling is careful to manage your dependent . For example:, between the modules, the dependencies between applications between classes.


◆ avoid unnecessary coupling

Examples of the coupling to avoid unnecessary:

① For Java developers, public setter getter exposed private member variables are more common, sometimes no need to expose the member variables (IDE may often will get used to all the member variables to automatically generate all the setter and getter exposed member variable);

② module or client endpoint method invocation code must be in a specific order. Sometimes this is reasonable, but most of the time because of the poor design of API, relies not only affect the method signature, but also affect the method call dependent manner, increases the coupling.


Upon exposure requires access to the domain or is likely to occur is called unnecessary couples.


◆ loosely coupled paradigm

Low coupling can learn to understand other people's code gets excellent experience.
For example: UNIX command line usage and programming pipeline, exposes a simple API; SLF4J logging framework; excellent open-source software, and so on.
Learning good software source code or design. To maintain low coupling system is essential for the health and scalable system. Low coupling is one of the most basic principles of software development elasticity.



03 DRY- Do not repeat yourself


Repeat One thing is very boring, worthless thing. The same thing repeated again and again, is simply a waste of life.


In software engineering life cycle, often encounter duplicate things, from the repeated application code, the code prior to release to repeat the test every time, and so on.


Doing repetitive things of reasons :

① using inefficient process

在软件开发的过程中,设计、交付、开会等,持续对这些进行改进可以获得很好的收益,获得反馈、持续改进、然后重复这个过程。团队意识到很多都是在浪费时间并无可奈何。当你经常听到“本来就是这么干的”或“一直是这么干的”,那么往往说明这里有低效的过程并且有改进的机会。


②缺乏自动化

我们在开发的项目的过程中经常要做的事:手工部署、编译、测试、打包、配置等等。有时候你会发现你一整天的时间都消耗在了这些过程,但是你的新任务却没有开始,然后只能加班加点的完成新功能的开发了。如果有一套自动化的工具帮你做这些事,那就可以很好的完成工作了,而无需浪费时间在这些重复过程之上。


③重复造轮子

已有现有的功能代码,却非要自己重新来写一个,并且写的还没有别人好,bug贼多。比如:排序、b树、MVC框架或数据库抽象层。这完全就是在浪费时间,已有的类库和工具就可以方便和快速的帮助我们了。

④复制黏贴Ctrl C、Ctrl V

我们在开发过程中,或者看到别人写的代码也容易发现,在同一个项目里(或项目组系统内)会存在大量拷贝其它地方的代码,这种重复性的代码想必你一定不陌生,并且有的IDE工具也有这些提示重复代码的功能。虽然有时拷贝是最方便快捷的事,但是一旦出现需要变更、维护等,其不足就表现出来了:维护多份代码、遗漏修改,造成bug再次出现等等。

⑤持有凑合态度——代码不会再用第二次了

有时候我们开发时,容易出现认为这份代码目前只是拿来简单用用,然后就随便写写。并没有文档、单元测试、很好的设计、很难用。这样的代码可能会存在很多漏洞,也可能给其它人复制粘贴,同样会给别人造成巨大的“灾难”。


04基于约定的编程

基于约定编程,也就是基于接口编程。将客户端代码和功能提供者代码进行解耦合。
在设计代码的时候,尽可能创建明确的约定,也尽可能的依赖约定(而不是实现)进行开发。


现实技术领域中,基于约定编程的比较常见的便是HTTP协议,客户端Web浏览器:Firefox、Chrome、HTTP服务提供者:Apache、Tomcat等,都按照约定进行编程设计与开发,这样就能很好发挥HTTP的实现弹性和提供者透明的可替代性。


05画架构图

一图胜千言!
通过架构图可以将系统设计文档化、跟他人分享信息、帮助自己更好的了解自己的设计。


很多时候,我们接到需求就直接拿起编辑器进行功能开发,并没有做前期的分析和设计,特别是目前很多工程师在追求敏捷开发更加容易造成这样的处境。


有时我们开发好功能了,到最后可能发现自己写的代码是有问题,比如跟需求要求不一致、逻辑漏洞很多,因为糟糕的设计(基本没有设计),你最后可能也得重头再来,这个是很常见的开发风险问题,我们应该重视它。


常见的架构图:用例图、类图、模块图。

用例图:定义系统的用户是谁,可以执行哪些操作。

类图:类的信息、类与类之间的关系。

模块图:描述结构和依赖关系。抽象层次更高。

架构图是你对于功能系统的设计表现,可以从多个角度审视自己的设计,可以降低开发风险。


06单一职责

单一职责原则,你的类应该只有一个职责而不是更多。

作用:降低代码复杂度,降低耦合、增加简单性、易于重构、代码复用、单元测试。


改善单一职责的一般最佳实践:

①一个类的代码少于2-4屏;

②确保一个类依赖不超过5个接口或类;

③确保类有明确的目标;

④用一句话总结一个类的职责。


进一步掌握单一职责办法可以研究这些设计模式:策略、迭代器、代理、适配器等模式。


07开闭原则


开闭原则,当需求变更或者增加新功能时,无需修改现有代码。


向扩展开放,向修改关闭。


开闭原则常见优秀例子:排序算法-Comparator接口(只要继承此接口,实现具体的算法逻辑),MVC框架(扩展各种组件,无需修改原有代码)。


08依赖注入

依赖注入是一种降低耦合改善开闭特性的简单技术。依赖注入对类需要依赖的对象提供一个引用实例,无须类自己创建依赖对象。


依赖注入的思想:知道的越少越好。尽可能让类不需要知道如何去创建需要的依赖,以及依赖来自哪里,如何实现。


依赖注入一般不需要new实例,而是由依赖的对象实例提供。
使用得当的话依赖注入可以有效降低局部复杂度,使其更简单。不用知道实例从何而来,不用知道谁来提供依赖的实例,这样就可以更好的聚焦自己的职责。


推荐学习依赖注入的优秀框架:Spring、Grails等框架。


09控制反转

控制反转IOC是一种从类中移除职责的方法,从而使类更简单,与系统其它部分更少耦合,其核心就是不必知道是谁、怎样、何时创建和使用对象,尽可能简单易于理解,对于软件设计而言,各部分互相知道得越少越好。
学过Spring的都知道,依赖注入、控制反转是其主要核心思想。


好的IOC框架应该包含

①可以为框架开发插件。

②插件的独立的,可以随时插入移除。

③框架可以自动检测到插件,或者通过配置文件加载。

④框架为每种插件类型定义接口,而不会与其具体插件耦合。


10为伸缩而设计


每种伸缩和对应的方案实践之间都要仔细权衡,不要为了那些永远用不着的伸缩性需求进行过度设计,要认真评估系统最可能的实际伸缩性需求进行相应的设计。


在创业公司中,很多都没有做到任何系统可伸缩就倒闭了,所以我们应该在追求可伸缩性系统的同时也要实事求是根据业务发展情况进行调整,不能一味的追求完美的伸缩系统,而是要有大局观进行技术的规划和各项权衡等等。


讨论各种设计原则都是为了解决系统的耦合性和复杂性,这些原则大部分有助于我们改善系统的伸缩性。


伸缩系统设计方案主要是下面这三个基本的设计方法


◆增加副本

同一组件或者系统服务部署到多台机器上(集群)。


在Web层而言,增加副本是最容易、成本最低的伸缩方案,主要的挑战是对于有状态的服务难以使用这种方式,需要同步状态来实现副本任意可交换(正是如此,我们设计系统时一定要设计实现无状态的系统)。

◆功能分割

根据功能将系统拆分成粒度更细的子系统(特别是当前的微服务架构)。基础设施架构,服务器服务器进行分离部署:对象缓存服务器、消息队列服务器、Web服务器、数据存储服务器、负载均衡器等等。

功能分割更先进的方式:将系统分割成自给自足的应用。主要适用于Web服务层,是面向服务架构SOA的一种主要实践。

功能分割会带来很多好处也有缺点,分割后,最开始就会带来很多管理方面的问题还有相应的成本也会很高,我们也不可能无限制的进行分割,达到“适可而止”即可。这一方面可以了解下当前微服务架构技术。


◆数据分片

每台机器存储一部分数据(数据库分库分表等)。

数据分片+增加备份(副本),可以实现几乎是无限的伸缩性,只要能正确的切分,就能增加更多的用户,处理更多的并发连接,收集更多的数据,将系统部署在更多的机器上。

但是,数据分片是最复杂、代价最昂贵的技术。数据分片最大的调整是,数据在访问前,就得找到需要存储数据的所在分区的服务器,如果一个查询涉及到多个数据分区,实现起来就变得异常低效和困难了。

举个例子,比如现在的分布式数据库,或者分布式中间件(ShardingSphere),有很多框架或者系统在这方面都会存在问题或者实现起来麻烦,关键也会对性能上有很大的影响,所以有时就得权衡或者妥协各种问题。

为伸缩而设计,主要是要在这三个基本的设计方法:增加副本、功能分割、数据分片。
虽然有各种技术方法帮助或指导我们,但是实际上还会存在各种各样的问题需要我们去处理或者去权衡。


11自愈设计

一个系统高可用,是以用户的角度来看能够达到预期的运行,即使系统出现部分异常或者部分设备宕机,只要不影响用户使用。


我们都认为整个系统是可用的。


我们的系统越大,相应的失效概率就会更高。进行伸扩容时,失效也会变得更加频繁。设计一个伸缩性架构必须把各种失效状态当作常态,而不是特殊情况对待。


想要设计一个高可用系统,必须做最坏的准备才能得到最好的期待,要不停的假想哪里会报错出异常,然后是要怎么处理它。


我们应该如何识别失效单点问题?


一个简单的方法就是画出系统架构图,每个设备(路由器、服务器、交换机等网络基础设施)等要画上去,然后询问自己, 如果某个设备宕机时会发生什么,某个子系统挂了怎么办等。


当识别出实效单点后,就要和业务团队和基础技术团队开讨论如何做才能达到高可用,是否需要做哪些冗余(冗余在成本和是否复杂等方面需要仔细权衡)来做备份等等。


确保系统高可用的主要手段是消除失效单点的风险和优雅地进行失效转移。


推荐可以学习或了解相关技术:混沌技术(比如Netflix开发的Chaos Monkey、阿里开源混沌工程工具 ChaosBlade)、开源数据库Cassandra(很好的自愈处理能力),这些都极其优秀,值得一学。


设计软件一定要考虑高可用和系统自愈能力。

Guess you like

Origin www.cnblogs.com/yaoyinglong/p/11857854.html