聊聊架构(4)详解架构师

单元测试

要认识单元测试,首先要明白什么是单元(Unit)。所谓单元指的是代码调用的最小单位,实际上指的是一个功能块(Function)或者方法(Method)。单元测试是一种白盒测试,必须要对单元的代码细节很清楚才能做的测试。所以单元测试都是由软件工程师来做的。服务代码、管理者代码和存储代码都是不需要写单元测试的,因为这些代码是简单的顺序执行,而且通常有上下文,而单元测试的代码都是简单的顺序执行,并没有逻辑,如果单元测试写得很复杂,比如还有判断,计算等,那么单元测试的代码本身就需要测试,这就不能叫单元测试了。

如何做单元测试

通过提供预期的输入和预期的结果,与单元的实际运行结果进行对比。已测试一个目标方法为例,基本上分为三个步骤:

  • 构建输入参数,并预测该输入产生的输出
  • 调用要测试的目标方法,获取输出
  • 检测目标方法的输出是否和预期的输出一致

业务逻辑代码的单元测试覆盖率应该要达到100%。

软件架构与面向对象

任何事物都有其生命周期,生命周期按时间推进的特性形成了面向过程。生命周期还有另一个特性,即在事物生命周期推进的过程中,生命周期活动的主体是不变的。面向对象的方式表达了事物的内聚,但是面向对象不能离开面向过程的基础,也就是顺序执行。
一个生命周期的拆分,会形成多个子生命周期。也就是说,一个对象拆分之后,会形成多个对象,每个对象都具备自己生命周期的所有活动。用户对象拆分成订单、账户对象之后,就成为用户、账户、订单3个不同的对象,形成了三个不同的生命周期,形成了三个不同的生命周期,而用户是核心生命周期,账户和订单是非核心生命周期。
拆分之后的合并,则是通过面向过程的代码来串联,形成访问流程,也就是访问生命周期。最终还是完整的完成了原有用户的所有生命周期活动。
大部分时候,业务的变化都是流程的变化,并且都是和用户打交道的部分,也就是用户访问生命周期,所以这一部分的变动最频繁。因此这部分代码要尽可能地采用组合,本身不要有业务逻辑。

软件架构与设计模式

模式是人类认识自然界和人类社会的一个重要手段,现实生活中虽然有重复,但往往每个重复总有其差异的地方。要想得到模式,往往要结合抽象的思维。通过分析不同事物的共性,去掉差异,提取共同点,从而得到类似的规律,可以更好地认识规律。
而设计模式,无一例外的都是把原来对象的访问生命周期拉长,增加了环节,在不修改原有对象的基础上之上,添加新的能力或者获得新的自由度。比如命令模式(可以参考我另一篇博文js命令模式)整合了Action和参数,策略模式组合了不同的策略来做切换(可以参考我另一篇博文 js策略模式)等等。站在原有对象的角度来看,设计模式基本都是通过组合现有对象的能力,通过对原有对象访问生命周期进行架构拆分,形成一个新的解决方案来解决特定的问题。因此,设计模式要解决的问题和原有对象所要解决的问题并不相同,设计模式更多地为了提高代码的复用性。
一个设计模式是有一个很清晰的内部对象的分工的,这个分工完全取决于现实生活,与现实生活相对应,这和业务领域代码的组织非常相似。而在服务部分,服务很多时候就是代理(Proxy);存储基本就上就是适配器;黏合代码是为了给业务对象加上状态,这时就可以用装饰器(Decorator)。
设计模式不是银弹,模式只是关注到了共性,而真正解决问题是要发现问题的个性。重用并不总带来好处,比如不同角色重用一个服务,就会导致两个角色不必要的相互干扰,反而增加了新的问题。

软件架构和软件框架

要把业务呈现给用户,并让用户能够独立访问,会遇到几个问题:

  • 提供给用户什么样的访问界面
  • 用户访问时,如何和用户进行交互
  • 用什么方式组织业务逻辑并对外提供访问
  • 业务逻辑的状态如何从存储(Repository)中存取

比如基于MVC模式的解决方案,其核心是为了方便用户对内部业务逻辑进行访问,提供给用户视图来做交互,并分别对视图和模型的变化提供支持。很多人把MVC中的模型理解为业务模型,模型更多的是对视图的数据支持,而业务模型关心的是业务生命周期及其行为。
再如典型的ORM(Object-Relational Mapping)框架Hibernate。在面向对象开发时,会遇到一个问题:关系型数据库存储是关系型的,和面向对象不一致。这就需要把对象的状态转换成数据库的存储,或者把数据库的存储恢复成对象的状态。这两者的适配自然就需要一个转换。
那么什么是框架?框架基本上都是根据业务模型,或者设计模式等,把模型中稳定的部分进行封装,形成一个大的边界,但是具体内容仍留有余地。由于业务模型或者设计模式也是架构拆分的结果,因此框架同时也属于业务架构的具体实现。

软件运维

软件的启动、停止、版本更新等运行生命周期活动,需要由独立的工程师来进行维护,这就是运维工程师。为了维护好软件运行生命周期,运维工程师需要安置相应的传感器来搜集软件生命活动的健康状况,运维监控软件也需要由软件工程师进行开发。运维工程师独立出来后,运维监控的生命周期就从软件的运行生命周期中拆分了出来
对于一个软件系统来说,软件运行在硬件上,硬件又依赖于电力和网络。软件、硬件、电力和网络任何一个变化,都会导致软件不稳定。同时用户访问量的变化也会导致软件的不稳定。当第三方的软件或云服务没出现之前,软件运维是核心生命周期,必须自己来实现。第三方的软件和云服务出现之后,一部分运维的生命周期作为非核心生命周期被分拆出去了。运维的生命周期是从软件部署开始的,要做好变化的控制,首先要做的是隔离:在软件周围设置隔离区,避免软件出现在不安全的地方。通过隔离区可以控制所有对软件的改变,对软件所依赖的硬件、网络和电力也是同样的,只有设立隔离区才能保证软件安全。要避免办公环境对生产的影响,必须划出独立的机房给生产环境使用,这个独立的机房要有独立电源、网络、空调、排风等。
生产环境一旦建立,那么生产环境就有了自己的生命周期,其内部就会开始持续不断地发生变化。生产环境的变更可以分为两类:一是被动发生的变更,一种是企业内部主动发起的变更。比如机器的主板、硬盘的损坏,用户访问量的突然猛增,都是被动发生的变更。生产环境上的问题无法完全避免,因此必须要拥抱变化。减少损失的方法,要么提前预防问题,要么缩短问题所影响的时间,两者都要求运维要具备快速发现并定位问题的能力。监控的主要目的是收集实时数据并展示出来,但是过量的数据和没有数据是一样的效果。所以这就需要我们去理解数据,监控一个软件,就要知道这个软件本身的生命周期是怎样的,它对应的业务生命周期是怎样的。什么样的指标说明业务是正常运作的?理解了这些数据和指标,监控人员就可以对超出正常范围的数据进行报警
主导变更的策略主要就是让变更逐步地发生,一般称为灰度发布,其核心思想就是尽可能减少变更所影响的范围。首次发布一般都选择可发布的最小单位,也就是一台机器,往往在发布50%之后,经历一次业务高峰后再发布剩余的机器。因为即使该变更有问题,还有剩下50%的机器能够支撑业务运作。这就意味着在建立集群的时候,必须要留有50%的冗余容量来做缓冲。
一般我们会模拟一个和生产环境一样架构的测试环境,生产环境的每个集群在该环境一般有只1到2台机器,因为测试环境流量很低,同时也为了节省成本。这个环境一般称为回归(Regression)测试环境。为解决回归测试环境争抢的问题,就必须以回归测试环境为基线,建立多个功能测试环境,供测试人员做不同版本的新功能测试。所以软件在这几个环境中发布的推进管道(Pipeling):开发测试环境-功能测试环境-回归测试环境-生产环境。

软件访问生命周期

当用户量越来越大的时候,一台机器势必会造成访问的拥堵,而另一个问题是,只有一台机器的时候,万一机器出现故障,那么软件运行生命周期就停止了,这也被叫做单点故障(Single Point of Failure)。纵向扩展可以增强访问能力,但是无法解决单点问题,而横向扩展既能增加访问能力,又能解决单点问题,这就出现了集群。什么是集群呢?集群就是装有相同软件,具备相同功能的一组计算机,应用集群之后,所有的用户不再只访问一台机器,编程了用户分散访问不同的机器,但还是访问同一个软件。只要在用户访问到达集群之前做一个路由,把用户的请求按照预设的规则转发到集群中的某台服务器。因此集群路由主要考虑的因素是集群内机器的负载均衡问题,为了实现对集群内机器负载的感知,路由必须定时检查集群内机器的健康和剩余访问容量。集群出现之后,用户的访问路径又做了一次架构分拆。
那么什么是数据中心呢(Date Center)呢?数据中心可以看做集群的集群,数据中心前置路由的策略和集群的路由策略略有不同之处,集群的路由策略保障的是集群内机器访问的均衡,而数据中心前置路由的路由策略则是把数据中心所覆盖地区的用户访问归属到相同的数据中心。

软件架构与大数据

在大数据提出之前,对于大量数据的处理已经有很多现成的技术,比如数据仓库(Data Warehouse)和数据挖掘(Data Mining)等。可以注意到,这些技术的基石都是关系型数据库。因此从大数据这个概念产生的缘由来看,原因之一可能是因为数据量已经超过了关系型数据库的处理能力,另一个原因是可能原有技术对数据的处理时效太长。要做好大数据,重点在于数据本身。要理解数据,首先要知道数据只是行为的状态和行为的结果。而要理解行为,则先要理解产生行为的业务,而要理解业务,首先要理解业务的目标,要理解业务的目标,先要理解业务的主体,理解了业务的主体,就可以知道业务的生命周期。没有软件的时候,现实生活中要收集这些业务数据是非常困难的。因为生活很难留下行为的痕迹,只会留下当前的结果。
访问日志(Access Log)可以被用作业务数据分析和软件本身的业务分析,所有的服务器都带有访问日志,不需要额外的开发成本。

交易

我们再来聊一聊交易。交易就是人们各自拿自己多余的物品,从其他人手上换取自己必须的物品,从而双方都获得利益的过程。所以交易也是有生命周期的,从一方开始发出交易的邀约开始,到最后双方物品交换成功结束。传统的物物交易有很多问题,当信用机制出现之后,物物交易的买和卖又发生了拆分,变成了卖家卖出自己多余的物品,换成信用物;买家通过付出信用物,获得所需要的物品。软件出现之后,交易突破了空间的限制。交易虚拟化之后,由于人本身的生命周期活动还无法被虚拟化,所以购买的物品在物理上还是要被自己使用,买卖双方在达成交易之后,卖家再通过物流把物品传输给卖家。由于物流的出现,卖家付款之后无法及时收到货物,所以第三方支付担保(Escrow)出现了,买家把钱付给第三方支付担保公司,由第三方支付担保公司通知卖家发货;卖方的信任问题解除,发货给买家。买家收到货之后,通知第三方支付担保公司把钱真正支付给卖方,买卖双方的信任问题解决了。
人们需要交易,实际上是为了获得物品,软件出现后,为了获得真正的物品,在访问到真正的物品之前,先要访问到软件来获得对软件访问的权力,促使用户访问软件的动力,就在于软件的虚拟化极大减少了人们获得物品的难度,所能获取的信息量更大。
因此要评价一个软件的价值,它的访问量是一个重要的衡量标准。企业的运作模式也发生了变化,一批企业不再直接和用户发生金钱的交易,而是通过流量的分析以广告的方式变现。对于一个提供搜索的企业,用户的每一次搜索都是一个交易,对于提供网络营销的企业,用户对广告的每一次观看、点击都是一个交易,所以为什么会有PPC(Pay Per Click)和CPC(Cost Per Click)等付费方式就可以很容易理解了。为什么没有发生货币的转移,也定义为交易呢? 因为交易的背后实际上是人们互相之间时间的交换,而不是货币。货币只是对时间的定价,方便交易的一个工具。

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/6921.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论