欢迎您,请 登录 或 立即注册

流行源码论坛

热搜: 插件 源码 discuz
流行源码论坛 门户 互联网 建站 查看内容

架构漫谈系列后续

2016-6-3 11:29| 发布者: Lewis| 查看: 373| 评论: 1|原作者: 王概凯 |来自: 博客园

摘要: 六、软件架构到底是要解决什么问题?前一篇文章简述了什么是软件。那么什么是软件架构呢?按照惯例,我们来看看是什么问题,是谁的问题。  要解决谁的问题?  如前所述,软件实际上就是把现实生活模拟到计算机中 ...
六、软件架构到底是要解决什么问题?

前一篇文章简述了什么是软件。那么什么是软件架构呢?按照惯例,我们来看看是什么问题,是谁的问题。

  要解决谁的问题?

  如前所述,软件实际上就是把现实生活模拟到计算机中,并且软件是需要在计算机的硬件中运行起来的。要做到这一点需要解决两个问题:

  一、业务问题

  具体的现实生活状态下,没有软件的时候,所解决的问题的主体是谁,解决的是什么问题,是如何解决,如何运作的?

  二、计算机问题

  1. 如何把现实生活用软件来模拟?
  2. 模拟出来的软件,需要哪些硬件设施才能够满足要求? 并且当访问量越来越大的时候,软件能否支持硬件慢慢长大,性能线性扩展?
  3. 因为硬件是可能会失效的,软件如何在硬件失效的情况下,仍然能够保证可用性,让用户能够不中断的访问软件提供的服务?
  4. 怎么收集软件产生的数据,为下一阶段的工作提供依据?

  分别是谁的问题呢?

  1. 业务的owner需要提升业务的效率,降低业务的成本,这是动机。这个实际上就是业务的问题,所以一般软件开发的出发点就在这里。

  2. 是软件工程师的问题,要解决业务owner把业务虚拟化的问题,并且要解决软件开发和运营的生命周期的问题。

  分别有什么问题?

  1. 业务问题的本质,是业务所服务的对象的利益问题,明白了这个,就很容易搞清业务的概念和组织方式。再次强调一下,有了软件,可以降低业务的成本,没有软件的情况下,业务是一样跑的。如果只是为了跟风要用软件,说不定反而提高了成本,这个是采用软件之前首先要先搞清楚的。我们经常说软件和技术是业务的enabler,实际就是把原来成本很高的降到到了很低的程度而已,并不是有了什么新的业务。另外,软件也不是降低业务成本的唯一方式。

  2. 为了能够让软件很好的跑起来,软件工程师必须理解业务所服务的对象,他们的利益所在,即业务问题。业务面对这些问题是如何分拆解决的? 涉及到了哪些概念? 这些概念分别解决了哪些哪些问题? 我们不能自己按照自己的理解,用自己的一套概念体系来表述。如果这么做的话,会导致两个问题:
    1)业务无法和我们交流,因为他们无法明白我们所自己创建的概念,所以他们无法确认我们的理解是否正确。
    2)我们所表述的东西,并没有在实际生活中实践过,我们也不知道这些概念是否能够解决业务的问题。

  3. 软件工程师还必须要考虑,用什么样的硬件把软件跑起来,怎样跑得好,跑得快,并且可以随着业务的流量逐渐的长大?

  分析问题

  对于2,在有限的时间下,软件工程师毫无疑问无法一个人去完成这么多事情,那么我们需要把所做的事情列出来,进行分析。

  一、虚拟化业务需要完成这些事情:

  1. 学习业务知识,认识业务所涉及的stakeholders的核心利益述求,以及业务是如何分拆满足这些利益诉求,并通过怎样的组织架构完成整个组织的核心利益的,以及业务运作的流程,涉及到哪些概念,有哪些权利和责任等。

  2. 通过对业务知识的学习,针对这些概念所对应的权利和责任以及组织架构,对业务进行建模,并把建模的结果用编程语言实现。这是业务的模型,通常是现实生活中利益斗争的结果,是非常稳定的。

  3. 学习业务所参与的stakeholder是如何和业务打交道,并完成每个人的权利和义务的,并通过编程语言,结合业务模型实现这些打交道的沟通通道。这部分是变化最频繁的,属于组合关系。明白了这一点,对后续的实现非常有帮助。

  4. 如何把业务运行的结果持久化,并通过合适的手段把持久化后的数据,在合适的时间合适的地点加载出来。这部分和基础设施有关,变化可能也会比较频繁。

  二、代码如何运营,需要完成这些事情:

  1. 需要多少硬件设备来满足访问的需求?
  2. 代码要分成多少个组件部署到哪些硬件设备上?
  3. 这些代码如何通过硬件设备互相连接在一起?
  4. 当业务流量增大到超过一台机器的容量时,软件能否支持通过部署到新增机器上的方式,扩大对业务的支撑?
  5. 当某台或某些硬件设备失效时,软件是否仍然能够不影响用户的访问。
  6. 软件运行产生的数据,能否支持提取出来并加以分析,为下一轮的业务决策提供依据。

  三、如果分成不同的角色来完成这些事情,就需要一个组织架构来组织代码的编写和运营,需要做哪些事情:

  1. 完成一和二所列的这些事情,需要哪些角色参与?
  2. 这些事情基本都需要顺序的发生,如何保证信息在不同角色的传递过程中不会有损失? 或者说即使有损失,也能快速纠正?
  3. 这些角色之间是如何协调,才能共同完成虚拟化业务的需求?

  会生成哪些架构

  如果业务足够简单,用户流量够小,时间要求也不急迫,那么一个人,一台机器就够了,这个时候一般不会去讨论架构的问题。当访问的流量越来越大,机器就会越来越多,代码的部署单元就会拆分的越来越多。

  同样就会需要越来越多的人来完成拆分出来的越来越多的部署单元,甚至同一个部署单元也需要分拆为多人合作完成。但是我们需要注意到一点,整个的概念体系,或者说业务的建模不会有任何的变化,还是完成同样的这些事情。唯一的区别就是量越来越大,超过了单个人和单个机器的容量,不断地增长。这样就会导致以下的架构:

  1. 当流量越来越大,我们就会发现,软件所部属的机器就会开始按照树状的结构开始分拆,就会形成硬件的部属架构。这就是为什么会形成部署的分层。

  2. 为了把业务在软件中实现并落地,需要前端人员、业务代码人员、存储层等不同技巧的人同时工作,需要切分成代码的架构。这就是为什么会形成代码的分层,形成代码的架构。当然,当这些角色由一个人来完成的时候,不一定会有代码架构,往往会比较乱。

  3. 当参与的人员越来越多,就会形成开发体系的组织架构。因为代码开发的过程是一个连续的过程,会用流程来把不同的角色串联起来,这就是软件工程。

  4. 为了完成业务的工作,需要识别出来业务架构和支撑业务的组织架构,以及业务运作的流程。这是被虚拟化的业务架构和组织架构,也需要体现在代码中,保持和现实生活中一致。

  什么是软件架构

  这就是软件比较复杂的地方,涉及到软件本身的业务体系,和所虚拟的业务体系。根据以上的分析,所生成的架构,究竟那些算是软件架构呢?

  1. 软件因为流量增大而分拆成不同的运行单元,在不同的机器上部署所形成的架构,属于软件架构。

  2. 每个运行单元为了让不同角色的人,比如前端,业务,数据存储等能够并行工作,所分成的代码架构,也属于软件架构。

  所以当我们说软件架构的时候,我们一定要讲清楚,究竟说的是部署的架构,还是代码的架构。软件架构的落地,需要软件的组织架构和流程来保障,离开了这个,软件架构是一句空话。

  另外很多人讲,架构是进化出来的。架构实际上是在量不断的增大,超过了单台服务器的容量,逐渐的分拆,同时导致超过单个人员的能力,工作人员不断的增多,工作内容不断的分拆形成的。这本身就是架构的意义所在。不管怎么分拆,所达到的目标没有任何变化,就是完成业务在计算机中的虚拟化。

七、不要空设架构师这个职位,给他实权

什么是架构师

  在之前的几篇文章中,经常会提到架构师这个词。我们已经定义了什么叫架构,那怎么定义架构师呢,是不是做架构的就叫架构师了? 没有这么简单,本篇尝试讨论一下这个问题。

  架构师的前提条件

  如果一个人在工作中,只是致力于完成自己的工作,以做好自己的工作为主要目标,那么最多只能成为一个工匠,无法成为一个架构师。因为这个过程解决的还是自己的问题,并没有时间的压力,可以随意什么时候做完都可以。

  当我们所做的工作是处于社会的分工的一环,需要帮助别人解决问题,并且按时解决别人的问题成为我们自己的问题的时候,我们就有了时间压力,潜意识里会自然而然的有一种对时间的恐惧。这个恐惧在潜意识里面会想方设法推动我们采用各种手段,以便及时的完成工作,换取报酬。甚至会加班加点,不择手段。

  如果我们还生活在这个恐惧下面,是不可能成为架构师的。要成为架构师,必须要超越这个恐惧才能够看清楚,我们要解决的是别人的问题,不是自己完成工作的问题。因为仅仅是完成了自己的工作,也并不一定就解决了别人的问题。如果别人的问题没有解决——即使我们认为自己的工作完成了——我们的工作实际也没完成,因为我们工作是否完成,是别人说了算的,不是我们自己。

  为什么会有这个对时间的恐惧和压力呢?这是因为我们把完成自己的工作当成了我们的最大利益。如果别人的问题没有真正的解决,必然会觉得付出的报酬不值得,我们的利益实际上是受损失了。这和我们所以为的恰恰相反,因为我们所能得到的工作只会越来越少,别人会越来越不愿意依赖于我们。

  另一方面也说明,我们对自己所从事的工作,还没有足够的自信,我们解决自己的问题还有困难,才会这么在意,并恐惧。如果我们把完成别人工作当成自己的最大利益,这个对时间的恐惧自然就会消失,这个时候就自然而然的开窍了,就知道怎么去发现问题了。只有做到这一点,才能在自己所服务的领域建立起自信,成为一个合格的架构师。

  其实刚开始一般是硬着头皮去克服对时间的恐惧和压力的,一点自信都没有。但只要做成功了一次(只要真的舍得这么去做了,想不成功也很难!),自信就开始慢慢建立起来了,这个时候就是我们开始慢慢变成架构师的时候。大家就当着上当一回,试试看。

  如何发现“是谁的问题”

  当我们真正专注于别人的问题的时候,我们自己的理想,抱负,对技术的追求都不算什么了。这些理想,抱负,对技术的最求,不就是要达到自己的利益吗? 只有帮助别人解决了问题,这些理想,抱负,对技术的追求才可能实现,否则这些理想,抱负,对技术的追求有什么意义,能得到什么利益?

  这个时候就会真正的开始思考,别人究竟有什么问题。其实也很简单,和我们自己面临的问题一样,别人的问题也都是如何获取更好更多的利益。我们自己想明白了这一点,自然也就能想明白别人的问题。这个时候就能够问出正确的问题:如果问题不解决,究竟谁会有利益的损失? 如果问题解决了,究竟谁会有收益,谁的收益最大? 回答了这两个问题就找到了问题的主体。只回答一个是没有用的,因为很多时候这个世界的事情,权责是不对等的。明白了这两个问题,我们只要让事情权责对等起来,让每个人为自己的权利产生的结果负有义务,大部分时候我们自己根本就不需要做什么,问题就都解决了。这就是最高明的架构师。

  架构师的权利和义务

  架构师是要去平衡别人的利益,甚至会调整别人的利益的。一旦架构师是全心全意的为别人的利益服务,自然而然的架构师就拥有了强有力的影响力,肯定会是一个leader。但是只是民意上的leader是没有用的,不能完全发挥架构师的能量。

  架构师必须是一个组织的领导人,有权利调动这个组织的架构,才能够更好的发挥架构师的作用,更好的把利益的调整落到实处。所以很多公司设了很多架构师的职位,但是并不具备调动组织架构的权利,那么这个架构师的职位一定是形同虚设。架构师只能够通过建立某些流程来行使架构师的权利,比如强制架构review,反而会造成很多内部不必要的冲突,最终都会导致这些流程流于形式,得不偿失。相信很多人都已经经历过这些,但似乎很少有人回去探讨这是为什么。

  反过来,具备架构师能力的组织领导人,一定是一个很好的领导,这个组织一定是很健康向上的,因为每个人的权利和义务就是比较均等的。并且这类领导对于组织成员权利和义务的对等状况会非常的敏感,会及时的调整组织架构,在问题发生之前就解决了。这样这个组织就会具备更好的抗压能力,能够更好的为这个组织的客户服务,这个组织的成员内心一定都是比较平衡的,每个人的能力都能够得到比较好的发展。当然读者可能又会说,这不是管理学的东西吗? 是的,但也是架构的问题。所有架构的核心就是组织架构。或者也可以这样说,一个合格的组织领导人,一定必须是一个合格的架构师。

  架构师的义务似乎不用说了,大家提的要求可能比我提的都高 —— 当然是发现问题并且解决问题。架构师必须能够超越对时间的恐惧 —— 也就是说必须具备了一定程度的自信,哪怕是装的,去真正的发现问题的主体,识别真正的问题,并把这个行为变成为自己面对问题的第一反应。架构师还必须要明白,所给出的解决方案 —— 架构的分拆、合并方案,只有让问题的主体的权责对等,才能够真正的解决别人的问题。一般明白了问题的主体,以及主体的利益所在,做到这一点也没有问题。

  架构师和技术

  很多人会问,特别是做软件行业的,架构师是不是需要学习技术,甚至是学习语言? 如果一个架构师还有这个困扰——就如问这个问题的人,说明目前还不具备做架构师的能力,或者说还不具备对自己领域——哪怕是技术领域——的自信,更别谈业务领域了。

  因为技术和语言,都是用来识别和解决所服务的主体的权责,保护并提升所服务的主体的权利的。特别对于软件领域来说,必须明白软件本身是怎么回事,解决什么问题,还要解决软件所服务的对象的领域本身是怎么回事,解决什么问题,这就要求更高了。语言和技术应该是随手拈来才对,对于架构师这些都是工具。学习技术和语言,如果明白了这些技术和语言要解决的是谁的问题,什么问题,学起来是非常快,非常容易的。

  同样,采用哪个技术或者语言,只要某个技术或语言所解决的问题的主体,以及所解决的问题,和自己所面对的问题的主体和这个主体要解决的问题,这两者是匹配的,那么这个方案的成本是最低的,所采用的技术或者语言就是靠谱的。没有趁手的工具或语言的情况下,自己设计一个也不难,因为很清楚自己要什么。要不要自己做,无非是一个成本问题,也就是利益问题。并且从这个思路下去,选择的工具和语言肯定都是最简单的,成本是最低的。因为架构毕竟解决的还是人的利益问题,成本越低越好,这个成本当然是长期总体成本,不是眼前的短期成本。

八、从架构的角度看如何写好代码

 在第六篇文章中,我们得出一个结论,软件架构实际上包括了:代码架构,以及承载代码运行的硬件部署架构。实际上,硬件部署架构最终还是由代码的架构来决定。因为代码架构不合理,是无法把一个运行单元分拆出多个来的,那么硬件架构能分拆的就非常的有限,整个系统最终很难长的更大。

  所以我们经常会听说,重写代码,推翻原有架构,重新设计等等说法,来说明架构的进化。这实际上就是当初为了完成任务,没有充分思考所带来的后果。这也并不是架构进化的事情,而是个人对问题领域的逐渐深入理解的过程。所以有必要再讨论一下,代码的架构应该是怎样的。

  本文会在之前几篇文章的基础上,进一步探讨如何把架构的思考进行落地,细化到我们代码的实践当中,尽量不要让代码成为系统长大的瓶颈,降低架构分拆的成本。

  在前面我们提到,软件实际上是对现实生活的模拟,虚拟化。这是一个非常重要的前提,直接决定了我们的代码应该分为几部分。结合每个部署单元所承担的责任,可以明确的拆分为两个不同的责任:

  1. 表达业务逻辑的代码。很多人把这部分叫做Domain Logic,或者叫Domain Model。这部分实际是来源于生活的,必须保持和现实生活中的切分一致,并非人为的抽象而成。

  2. 对用户提供访问并保存业务逻辑运行结果的代码。计算机的状态保存有一个缺陷,本机保留业务运行结果有很大的问题,一般都在外存储设备上保存,也便于扩展。

  所以单个部署单元的代码可以分为两个部分,如下图所示:

  从这个图中可以看出,软件代码的相关利益人为运行时的访问人员和存储设备。而service的代码是最复杂的,需要服务于三方,代码人员的负担是最重的。为了把这三方的变化对service的影响降到最低,对于service还必须进一步的分拆为三个部分,让每一个部分都能够独立的变化,这样这三方的变化就不会产生连锁响应,降低成本。如下图所示:

  这样,就划分成了几个责任:

  1. Service就专注于user的需求,并组合Glue Code提供的服务完成需求。

  2. Glue Code专注于组合business的调用,管理Business里面对象的生命周期,并且通过Repository保存或加载Business的状态

  3. Business专注于实现业务的核心模型。

  4. Repository专注于数据的保存,并和存储设备一一对应。

  大家注意看,还是树形架构。并且左侧的主要需要计算机的相关理论知识,并且要直接面对用户的需求。右侧的更多的需要面对业务的核心。只要这几块的开发人员互相商量好了接口定义,这几个部分的开发就可以并行的进行,极大的提升开发的效率,缩短开发的时间。要做好这几部分,还需要注意,逻辑只允许存在于Business中,Service、Glue Code、Repository都不允许存在业务逻辑。为什么呢?首先我们来看看什么叫业务逻辑。

  什么叫业务逻辑?

  首先这个定义的前提是指软件代码中的逻辑,不是现实生活中的逻辑。在软件代码中,不需缩进和计算的顺序调用,包括缩进的代码目的是catch exception的,都不算逻辑,除此以外都是逻辑。以下用严格的顺序调用来指代这种代码。因为顺序调用是计算机的特性,由编译器来决定的,当然最本质的是因为我们计算的基础都是图灵机。在现实生活中,顺序调用也是逻辑,大家不要和我们这里说的业务逻辑相混淆。

  为什么说除了Business代码中有逻辑以外,其他地方不能有逻辑呢? 我们每个部分分别分析:

  1. 如果service里面不是严格的顺序调用,有很多分支,那么说明这个service做了两件或者两件以上的事情。必须把这个service分拆,确保每个service只做一件事情。因为如果不这么分拆的话,一旦这个service中的某各部分发生变动,其他的部分的执行必定会受影响。而确定到底有哪些影响的沟通成本非常高,其他相关利益方没有动力去配合,我们往往不会投入精力仔细评估。最后上线会出很多不可预料的问题,最终会导致损失用户的利益,并且肯定会导致返工,损坏自己的利益。如果是有计算的逻辑的话,比如受益计算,订单金额计算等,那么这部分应该是Business代码需要完成的,不能交给service代码来实现。

  2. Glue Code里面如果不是严格的顺序调用,同理会和service一样遇到同样的问题。

  3. Repository里面如果不是严格的顺序调用,包括存储访问的代码里面(比如SQL),会导致逻辑进入到存储设备中。存储设备的主要目的是拿来存储的,一旦变成了逻辑计算的主体,就会导致存储设备无法通过增加机器的方式横向扩展长大。这个时候就没有架构了,只能换性能更好的机器,这个叫scale up。只有scale out才能算架构。

  以上都会导致架构无法快速的横向扩展和分拆,并且增加了修改的成本,这些是不符合开发人员以及业务的利益的。

  这么做的好处有哪些呢?

  1. Service、Glue Code、Repository里面的代码是严格的顺序调用,那么这些代码只要做连通性测试即可,不需要单元测试。因为这些代码都需要和很多上下文打交道,很难做单元测试。这样才算是真正的组合。

  2. Business不访问任何上下文,不访问任何具体的设备,所以这部分代码是非常容易写单元测试的,并且单元测试必须100%覆盖。因为其他地方没有业务逻辑,所以一旦有问题,就可以断定是Model的问题,单元测试肯定可以发现。如果单元测试没有发现问题,那么单元测试一定有问题。线上问题的模拟也就变得非常的简单,单元测试也能够得到进一步的补充。

  3. Repository很容易按照存储设备本身的最小访问粒度来完成工作,比如DB,完全可以做到单表访问。因为这个时候存储设备只关心存取数据,完全和业务没有关系。做表的分拆也是非常容易的事情,存储设备通过增加机器就可以横向扩展长大。很多人会担心说,没有了join,访问DB的次数是不是更多了,会导致性能下降? 按照现在网络的条件,网络访问和Disk IO访问的差距已经不大了,合理的设计下,多访问几次DB并不会导致这个问题。另外如果多台DB的话,还能通过并行加速访问。

  4. 由于Service、Glue Code、Repository代码简单了,才可以让我们的开发人员投入更多的时间研究业务,毕竟这部分才是软件所真正服务的对象。

  我们再来看一个实际的例子,如下图所示:

  Manager类实际就是Glue Code。有几个注意点需要说明一下:

  1. 不能把Business Model当做数据对象来处理,Model关心的实际上是业务行为,数据只是是这些行为的结果。所以Glue Code需要把Model转换为Entity,Entity和存储设备里面的存储粒度一一对应。比如在DB中,每个Entity对应一张表,并且跟着表的变化而变化,这样就保证存储的变更不会影响Model。同样Service和用户之间的数据交互,也是不会和Model之间相关的,确保用户的需求变化,不会影响到Model。因为用户的需求变化是最频繁的,没有逻辑,可以让我快速的满足业务的需求。

  2. 在Service这里,最好不要考虑代码重用。因为当多个不同的角色访问同一个接口,一旦某个角色的需求发生了变化,就会要求开发人员去修改。而这个修改往往会影响到其他的角色,需要这些角色一起配合来确定是否受影响,但是这些角色因为没有需求,往往不会配合。这样就给开发人员造成了很多不必要的沟通,成本是非常高的。最终都会导致线上Bug,影响最终的用户。所以尽量给不同的角色不同的Service,避免重用,降低沟通成本。很多人会说这样Service不就太多了吗? 这样Service注册,查找等管理需求就出现了,Service治理中心就是来解决这个问题的。因为Service里面没有逻辑,所以开发和管理非常的简单,可以快速应对业务的变化。我们只有更快地变,更容易的变,才能更好地应对变。

  3. Business Model是必须要重用的,一旦发现重用出现问题,那么说明Business Model的识别出现了问题,这是一个我们要重新思考Model的信号。Business Model必须是一个完美的树状,如果不是,也说明Model的识别出了问题。

  在实际操作中,Service、Glue Code、Repository不能有逻辑,实际上和很多人的观念是冲突的,认为这个根本做不到。做到这一点需要很多的学习成本,但是一定可以做得到。当发现做不到的时候,可以断定是业务的分析出了问题。比如不该合并的合并了,不该计算的计算了。这个问题一定有办法解决的,做不到都是理由,无非是想早点把自己的工作结束罢了。虽然刚开始会比较困难,一旦把这个观念变成自觉,开发的质量和效率马上就能高好几个级别。

  我的游泳教练曾和我说过这些话,我至今记忆犹新:“业余选手,越想从水里浮起来,就越想把头抬起来,身体反而沉下去。只有克服恐惧,把头往水里压下去,身体才能够从水里浮起来。真正专业的习惯往往是和我们日常的行为相反的”。

  我们真正想快速的完成代码工作,就要克服自己对时间的恐惧,真正的去研究业务的问题,相关stakeholder的利益,把这个变成我们的习惯。写代码的时候让该出现逻辑的地方出现逻辑,让不该出现的地方不能出现。一旦不该出现的地方出现了逻辑,那么要马上意识到,这个地方是一个坑,这个问题一定和业务的分析不透彻有关系。

  很多人可能会把这个做法和Martin Fowler曾经提出过充血模型和贫血模型来比较,和Domain Driven Design来比较,其实没有必要。这个分拆完全是从软件所解决的问题,根据软件架构推导出来的,很多地方和两位前辈的观点是一致的,但是并不完全等同。

  以上只是针对单一的Service部署单元的分析,扩展开去,对于其他的部署单元也是类似的。每个单元的下一级都可以认为是Repository,每个单元的上一级都可以认为是User。这些实践在我自己的项目中都有用到,非常的有效,迭代的速度非常的快。很多人担心Business Model建不好,其实没关系,刚开始可以粗糙一点,后续可以慢慢的完善。这个架构已经隔离好了每个部分的变化对其他部分的影响,变化成本都在可控的范围之内。

九、理清技术、业务和架构的关系

某天和朋友吃饭正好聊到这个话题。作为架构师或者做技术的人,在开发软件时,我们基本上就是在扮演上帝的角色:我们不但要创建出一个个的程序,还要让这些程序能够脱离我们在硬件上独立运行,以便为这个程序所服务的群体提供服务。当这个程序出现问题甚至bug的时候,我们还得扮演牧师的角色去修复这些问题。这不正是一个程序的社会吗? 和人类社会的演变何其相似!那么我们自然也能够拿人类演变的历史来指导软件开发工作,以避免再经历一次像人类演变发展那么痛苦的过程了。由此我们也可以看出,架构师和程序员们都在扮演着多么重要的角色,如果还在解决自己的问题,怎么扮演好上帝这个角色?

  在软件设计开发的过程中经常会看到,很多所谓的架构讨论实际上只是在讨论某种技术。在很多人的概念里面,架构和技术实际上是等同的。学会了几种技术,就认为自己是架构师了,甚至是学习的技术越多,就觉得自己的水平越高。这样实际上是对自己很不负责任的。要知道任何技术都是为了解决某种问题而存在的,学会了技术,并不代表自己能够解决问题,这一点非常的重要。学会的技术的多少,所带来的差别只是自己解决问题的手段多了罢了。但是手段多了就一定是好事吗? 很多时候,学习的技术越多,越不知道采用哪种技术好,所谓“乱花渐欲迷人眼"。

  还有另一种很普遍的观点:技术人普遍看不起业务,认为技术更高端,而业务太低端,并且业务往往喜欢给技术挖坑。业务则觉得技术眼光高,但是实际解决不了问题,总是理解有偏差,但是又无可奈何,因为自己不会。

  本篇文章尝试从这里入手,分析一下这三个概念到底有什么关系,我们应该怎么处理业务、技术还有架构的关系

  什么是技术

  当我们一无所有,或者什么都不会的时候,这个时候实际上是没有技术的。就好比人类在最早期,什么都得用自己的双手来干活。一旦我们在日常生活中无意间发现某些规律的时候,我们就可以通过创造条件,让这个规律重复的发生。通过人为创造条件,让指定的规律按照人类的意愿发生,这就是技术。

  比如取火,最早人类只能靠打雷等自然现象产生火。取火其实就是一个业务目标,要解决的是人类自己的问题,这就是业务,实际就是人类的利益。这个时候人类没有生火的技术,只能靠不断的加木材,保持火不熄灭。后来人们发现了钻木取火:只要用一个干的木棍,在另一个干木表面快速的转动,就可以生火。这个办法让人类可以自行创造火源,就产生了钻木取火的技术。

  但是双手快速转动木棍钻木取火,并不是所有人都能够做得到的,需要很多力量和速度,对人的要求太高。为了解决快速转动的问题,就有人采用弓弦来提升木棍转动的速度。

  也就是说:

  1. 业务目标是为了取火,钻木取火这个技术的出现解决了这个问题。

  2. 钻木取火的效率不高,影响了业务(取火)的效率,就有了进一步改进的动机,改进转动木棍的方式,产生了弓弦转动木棍的技术。

  技术与架构,以及与业务之间的关系

  技术总是在人类解决对业务的要求不断提高的情况下产生,目的也是为了获取更大更好的利益。所以:

  1. 技术是为了解决业务的问题而产生的,没有了业务,技术就没有了存在的前提。

  2. 有了更好的技术,效率更差的技术,就会慢慢的被淘汰,消失,一切都遵从人类的利益诉求——也就是业务。有人会问,不用钻木取火了,但是弓弦加速转动木棍还可以用啊? 没错,因为弓弦转动木棍这个技术,不是来生火的,是用来加速木棍转动的,所解决的问题不一样。但是两种不同的技术,合理结合起来,会更好更有效率的解决业务问题。

  所以技术与技术之间,有两种关系:

  1. 在解决同一个业务问题的前提下,更高效,更低成本的技术,会淘汰低效,高成本的技术。这是人类利益诉求所决定的。

  2. 一般刚开始解决根本问题的技术(钻木取火)的效率是比较低的,只是把不可能变成了可能(从这一点上来说,技术才是业务的enabler)。然后就会有提高效率的需求出现,要求改进这个技术。这个技术的低效率部分就会被其他人(或者技术发明人自己)加以改进,这部分就会形成新的技术。

  当关系2发生的时候,这个地方必定会形成一个切分,新技术会通过某种方式和原有的技术连接在一起形成一个整体,让这个新的技术可以和原有技术共同工作,使得原有的技术可以用更高的效率解决问题。因为要解决的主要问题(生火)并没有发生改变,分拆所形成的是一个树状的结构。

  按照前面的架构定义,这个时候其实已经产生了架构。也就是说,一般是先有技术,才会有架构。这些其他技术(弓弦拉动木棍),是从直接解决问题的初始主要技术中分拆出来形成的,并通过树状结构和主要技术(钻木取火)组合在一起。在解决主要问题(生火)之后,再开始逐渐的分拆为更为细粒度的技术(弓弦转木棍)。

  而这个细粒度的技术(弓弦转动木棍)往往不会和业务的主要目标(生火)发生直接的关系。不同的技术,通过树状结构,组合在一起,形成了一个完整的架构解决方案,共同完成业务的目标。这就是技术,业务和架构之间的关系。很多人把这个过程称为架构的进化,我更愿意把这个过程称为技术的进步所导致的新的架构分拆,因为这个过程内在的动力,更多的是来自技术对业务问题的解决。

  技术人员和业务人员的关系

  为什么技术人员总是和业务人员发生冲突呢? 这是因为技术人员很多时候关心的技术,和业务的主要目标往往不是直接对应的,业务也是负责某一部分的业务,也不是和业务的主要目标直接对应的,都是树的分支节点(上文已经解释了为何会发生这种情况)。只有直接解决业务问题的那个技术(或业务)—— 树的根节点 —— 会和业务直接相关。所以一旦产生冲突,一般必须两个根节点(一般都是领导)碰面才能解决问题,就是这个原因——他们都知道业务主要目标。这也是为什么下层无法理解上层,而上层都喜欢下军令状,要求下层执行。人只有尽量去理解上层的问题才能做下层的分拆。

  在软件行业,这个根节点技术就是软件。这也是为什么架构师要认识什么叫软件,软件解决谁的问题,什么问题,软件本身又是怎么分拆的,才能够更好的组合不同的技术,完成业务的目标。而软件里面和业务直接相关的,只有Business Domain这一部分。

  用人来打比方,Business Domain相当于人的大脑,而Service,Repository,Glue Code等部分所采用的技术,全部都是计算机自己领域的技术,都是为了能够让程序跑起来,相当于人的四肢。我们大部分开发人员的工作主要专注于四肢部分。我们真正应该投入的是大脑部分。因为大脑能够决定四肢长什么样,而不是反过来。很多架构师、技术人员主要专注于计算机相关的技术,忽略了业务本身,甚至看不起业务,这也是为什么技术总是和业务冲突的原因。

  架构师应该承担起解决业务问题的这个角色来,专注于Business Domain和软件本身的架构,让技术人员致力于为业务在计算机中跑起来而努力。只有把这两者很好的结合起来,才能更好地完成业务的目标,才会让软件更好地服务于大家。最终一定会得到一个很好的软件架构,令软件开发团队和业务部门都能够很好地开展工作并降低成本。

  重新发明轮子

  当现有已经存在很多技术,而这些技术却和我们所要解决的问题并不是那么直接对应的时候,我们就需要有意识的组织和识别不同的技术,来实现业务的目标。这个时候组织的方式有很多种,其中成本最低的方法就是按照要达成的目的和当前的问题,从上到下进行架构分拆。分拆出来的更细粒度的问题,分解到不同的人来进行解决,就形成了业务架构和组织架构。解决这些问题就需要组合很多不同的技术,那么应该采用哪些技术?还是自己重头实现一个? 自己实现一个——这就是很多人所谓的重新发明轮子。以下试着分析一下:

  1. 当技术所解决的问题和分拆出来要解决的问题,完全匹配的时候,这是最完美的。比如需要提供web要访问的service,很多MVC的framework就可以很好的满足这一点。而这个时候如果非要自己实现一个,很有可能就是重新发明轮子。

  2. 当技术所提供的能力远远超过需要解决的问题时,往往掌握技术和维护技术会成为瓶颈。因为越复杂的技术,成本越高。如果自己实现一个仅仅是解决当前问题的方案,可能成本反而更低。这也是为什么很多大型的互联网公司不断地开源出来自己的技术的原因。而这些技术对于我们来说是否适用?他们原本是用来解决谁的问题的?什么问题?如果不清楚这些,就冒然采用,可能会导致更高的成本。

  3. 当技术所提供的能力和我们所要解决的问题部分匹配时,还是要看成本。比如当我们需要一个锤子的时候,手边正好没有,但是却有一只高跟鞋,勉强也可以替代锤子。但是长期来看,这么用不划算,因为高跟鞋的价格比锤子高很多,耐用性差很多,维护成本也高很多。

  所以,准确识别采用什么技术的能力,也是架构师所要具备的能力之一。考虑的主要因素也是长期的成本和收益。


1

鲜花

握手

雷人

路过

鸡蛋

刚表态过的朋友 (1 人)

发表评论

最新评论

引用 seat 2017-5-6 13:42
架构师是不错的方向

查看全部评论(1)

返回顶部