架构设计--仅是软件开发之第二大影响力?!

SDWest2006(译注1)对我来说是个有趣的大会。我除了星期三之外(当时我正飞往费城参加一个客户会议 == 因此错过了Jolt颁奖部分)每天都在演讲。我也参加了一些谈话和会议;其中最引人关注的是Mike Cohn的计划与估算的谈话。我的两个谈话都是半天的关于Ood原则的导引。这些谈话都参与的非常好,现场反映也很热烈。
这里是我谈话的几份演讲稿:

  • 类设计之高级原则    在OO设计中,掌控类间组合或是关联关系的原则到底是什么?
  • 组件设计之高级原则  在大型OO设计中,你该如何掌控组件的组合或关联关系?
  • 首要导向因素        专业与否的最低界限是什么?

在星期二我主导了一个关于“敏捷与架构设计”的圆桌会议。很多人是挤着进入会议现场的,而且一直参与到会议结束。配合着讨论要点的导航图,我们将这些要点一一讨论过。我的好朋友John Kern也在那儿,还帮助解答了很多提问。你可以从这里了解更多有关这个会议的。

会议的一些关键要点如下:

  1. 架构设计的主要目标是灵活性,可维护性和可扩展性。
  2. 但我们认识到,由测试驱动开发原则指导产生的单元测试和验收测试(译注2)要比灵活性,可维护性和可扩展性来得更重要。
  3. 因而测试才是首要的影响力,而架构设计只是第二位的。

在此次会议前,我从未想到过这点。这里就有一群架构师和设计师,他们激烈的争辩着架构设计的角色和位置,可是我们辛苦争论出的一致结论是灵活性,可维护性和可扩展性是处于次要的影响作用的,是编写测试(测试优先于产品代码)起着最主要的效用。

这好像是吞下了苦黄莲,而且很多架构设计师们搞不好立即就会拒绝。然而,没人认为架构师不重要,或者认为应该丢掉它转而去青睐测试。正相反,是测试让我们无所顾虑的改进系统的设计。不是测试胜于架构设计;而应该说是测试成全了它!

自动化测试给了我们一个可靠的方式去了解系统是否运行良好。因此我们不必再惧怕一个设计的改变会破坏它。这让实施那些能够改进系统的设计变得更容易。因此测试的粉末登台意味着在持续改进系统的结构、设计和架构时遇到的阻碍会来得更少。

失去测试,架构设计就是天方夜谭,因为一但重大的开发启动后设计将很难改变。而自动化测试给设计留下了空间。设计改变所带来的风险如此之大的被削减,以至于我们可以在肆无忌惮中就让系统进化。

 

译注:

1,SDWest,全称Software Development West,即西部开发者大会,是全美颇受瞩目的开发者大会,著名的Jolt大奖就在每年一度的大会上颁发。

2,验收测试,原文acceptance test,又成为容忍测试,敏捷方法认为,如果一个构建(build)通过了验收测试,基本上这个构建就可被“接受了”。

 

 (原文链接网址:http://www.butunclebob.com/ArticleS.UncleBob.ArchitectureIsaSecondaryEffect; Robert C. Martin的英文blog网址: http://www.butunclebob.com/ArticleS.UncleBob 

译者注:Robert C. Martin是Object Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版)(《敏捷软件开发》(英文影印版))的作者,还是畅销书Designing Object-Oriented C++ Applications Using the Booch Method的作者。Martin是Pattern Languages of Program Design 3和More C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的编辑。



架构设计之性能设计经验

    性能(performance)设计非常重要,对于服务器端实时交易系统来说系统性能的重要性不言而喻,对客户端软件来说性能好的软件也会获得良好的用户体验,从而给用户留下高质量软件的良好印象。因此在进行架构设计中性能设计非常重要。

    但架构设计实际是一个平衡设计,在可用性、可扩展性、可维护性、可靠性、高性能等之间做个妥协选择。这些非功能性的需求再加上复杂的功能性需求,同时还要考虑到项目管理上tight schedule, low cost, perfect effect的三角难题约束,有时需求还不是很明确,vision不是很清楚,这种情况下系统架构设计真是一门艺术。

    单就性能设计来说,在架构设计初期就一定要把系统性能考虑在内,否则等开发完成以后测试发现性能不好就比较难办,通常要花费较长的时间来诊断性能瓶颈,找到提升的办法,甚至要改变架构,伤筋动骨,往往造成项目延期。所以性能设计首先要有明确的性能目标,根据用户和软件本身的性能要求来设计,合适的就是最好的。其次,要有适当的度量标准和量化的性能指标。最后,要有相应的设计策略,具体的测试方法。

    根据我的经验,影响系统性能主要瓶颈在I/O,包括数据库,socket,网络通信,文件等,例如频繁查询数据库并返回大量结果集,频繁操作大文件等,这些昂贵的操作会占用大量的CPU时间。拿系统响应和服务一个事务来说,有几个Round trip,要通过哪几层I/O,如何合理的分配这些I/O的调用,降低不必要的I/O,都是进行系统性能设计要考虑的。而有些性能问题在初期并不会表现出来,但当拿到实际上线环境下,存在多用户并发、大数据量的情况下就会暴露出严重的问题。所以性能设计时一定要考虑到I/O,同步,并发,资源争用,以及大数据量等因素。通常,I/O操作、网络响应、差的算法、数据库、以及其他的低效的资源使用都会导致低劣的性能。

    具体可用的设计策略有:

    - 缓存以及缓存层(caching layer)

    在数据层和应用层之间增加数据缓存层,提供全局数据服务。可以大大减少数据库往返次数。与读取数据库和读取大文件(如XML文件)比,读取内存的速度无疑要快的多。所以对经常要访问的数据进行缓存是非常好的实践方法。因为现在系统往往内存很大,可以充分利用大内存,而共享内存更能实现数据并发访问。

    - 多线程(multi-threading)

    现在基本上大部分软件实现多线程或多进程,多线程对单CPU系统还只是顺序利用CPU时间和改善用户体验,多CPU系统才是真正的并行。要注意的是多线程不要争抢访问同一资源而导致部分串行操作,要做到真正的并行操作多线程并不容易。另外,在多线程间同步一个庞大的资源,过多创建线程又没有实现线程池也会导致系统性能下降。

    - 负载平衡(load balancing)

    物理上增加地位对等的集群服务器(Cluster),通过负载分配算法分配相应服务器来相应客户端请求。很多系统支持负载均衡,Windows server2003 IIS就支持负载均衡服务,其他如WebLogic, WebSphere也有集群版本支持负载均衡。当然你也可以自己实现负载分配算法。

    - 数据库优化(database optimization)

    如果应用程序使用了数据库,可以采取许多步骤来消除访问和写入数据时的瓶颈:

    - 标识潜在的索引,但不要创建过多的索引。

    - 如果使用 SQL Server,则使用 SQL Server 的事件探查器和索引优化向导。

    - 监视处理器的使用;理想范围是:75-80% 处理器时间。

    - 使用查询分析器分析查询计划以优化查询。

    - 使用存储过程优化性能。

    - 标准化写入的大量数据 —写入较少的数据。

    - 取消标准化读取的大量数据 —读取较少的数据。

    文件系统优化

    有时候系统性能不好,但当你关闭写log的功能,性能一下子提高很多。因为频繁的打开关闭大log文件时I/O开销非常大,同样记录log到数据库也一样。所以,release版尽量减少写log,或干脆移到裸设备上。

    频繁打开关闭文件对系统性能下降程度是惊人的,可以通过一些变通办法来减少文件的频繁操作。

    例如,原来的缓存持久化实现是保存在XML文件,每次要获得一个配置项,都打开XML文件,通过XPath拿到这个配置项的值,这样效率不高,而且容易把这个XML文件lock住;改进的方法是:通过比较XML文件的修改时间(System.IO.File.GetLastWriteTime)判断是否要再次打开文件,大大提高了效率;另一个可以改进的方法是:启动时读取所有配置到一个静态的HashTable,每次要获得一个配置项都从内存HashTable获取,在最后或适当的时候持久化到XML。

    代码性能设计

    在编程实现上,代码性能设计也很重要,一些昂贵的操作会占用大量的资源和CPU时间。例如,字符串相加没用StringBuilder, 频繁创建对象,差劲的排序或递归算法,过多的装箱拆箱,过多的使用反射(Reflection),频繁new HashTable或大的数组,用异常(Catch Exception)用做正常的逻辑,使用复杂的正则表达式,等等。具体可以参考《Effective C++》《Effective C#》等书籍。

    语言的选择

    另外,语言选择也很重要。比如相对于Java, C#, C++, 大多数OLTP系统用C语言效率高的多,因为在所有的高级程序设计语言中,C程序设计语言的运行效率是公认的。再比如我们熟悉的一些框架,框架本身是C#或是Java的,但其核心独立模块是C++封装的,这样可以达到最佳的性能。所以对于一些特定的业务需求目标和数据的具体情况,对于核心的模块或算法,可以用特定的语言来实现以获得更好的效率。

    应用层

    比如应用层和数据库的API,在.Net中就有就有DataReader、DataSet和IList等的选择以及转换等,这个根据具体情况而定;还有就是大家常采用的数据的格式化和压缩,以及采用分页,减少传输的数据量;是否可以把一部分处理逻辑放在客户端呢,减少服务端的工作量。界面端也是有很多针对性能优化的考虑,例如绘图,控件重绘都是非常耗资源的,各控件的数据加载和数据绑定性能也各不相同,尽量采用惰性加载,异步加载;初始化和启动速度等都是需要考虑和优化的。


架构设计的三个维度

架构设计是一个非常大的话题,不管写几篇文章,接触到的始终只是冰山一角,更多的是实践中去体会。

这篇文章主要介绍的是面向对象OO,面向方面AOP,面向服务SOA这三个要素在架构设计中的位置与作用。

一、架构设计三个维度

架构设计有三个维度,或者说是我们在考虑架构时需要思考的三个方向。分别为:面向对象、面向方面、面向服务。这三个维度可以看作是正交的,但不同维度会互相印证,互相支撑。

整个架构的示意图如下所示:


二、面向对象

面向对象技术最初是从面向对象的程序设计开始的,它的出现以60年代simula语言为标志,并在Smalltalk语言的完善和标准化过程中得到更多的扩展和对以前的思想的重新注解。80年代中后期,面向对象程序设计逐渐成熟,被计算机界理解和接受,人们又开始进一步考虑面向对象的开发问题。直到现在,面向对象已经成为一种非常流行的编程方式,以及软件设计的架构。

面向对象提出有三个主要目标:重用性、灵活性和扩展性,强调对象的“抽象”、“封装”、“继承”、“多态”。它能让人们以更加接近于现实世界的方式来思考程序,这点可以说是面向对象最大的进步。

在OO思想的运用上,业界出现了很多好的经验与技巧,从而涌现出大量的设计模式。可以说面向对象是系统分析与设计时的一个很重要的方面。

三、面向方面

面向方面最初来源于hook技术,本质上就是满足扩展的需求,可以在程序中自由扩展功能。

面向方面不仅仅是一门编程技术,同样也是一种架构设计的思路。如果说OO是纵向地分析、切割整个系统,那么可以认为AOP是横向地对系统作切片。简单地理解,OO与AOP分别从两个不同的角度给我们提供了分析系统的思路。面向方面可以弥补面向对象的缺陷,两种方式有机的结合在一起可以更加有效地分析系统。

我们认为OO是接近于人类认识自然的思维方式,但对于东方来说却并不是这样。当西方人看到一个复杂系统的时候,只会有一种思路,就是“分解”——将系统分解成一块一块,然后每个部分作研究。当东方人看到一个复杂系统的时候,更多地会关注系统中存在的关系,将系统作为一个有机的整体进行研究。

这两种思维方式都没有问题,结合起来的话分析问题解决问题会更好。面向对象与面向方面也同样如此,都能对应到人类认识自然的思维方式上。不过中国人理解AOP可能会有不同的感悟——我写的文章《读易[13]·闲谈中医与AOP》有简单的说明。

四、面向服务

面向服务可以说是最近炒得比较火的概念了。包括现在提到的SaaS——Software as a service,软件即服务。准确说来,面向服务不仅仅是软件行业的概念。这个要从社会的产业结构说起。

社会产业总共分为三个,第一产业农业,第二产业工业,第三产业服务业。最早社会的主要产业是第一产业农业,将近有几万年的历史。十八世纪下半叶在英国开始的工业革命,对人们的生活产生了根本性的影响,社会的主要产业成了第二产业工业。

现在仍然属于工业时代,或者有人说的“后工业时代”。而在后工业时代,社会的经济体制必定要向第三产业服务业逐渐转型。面向服务其实是社会经济体制重心的一种迁移。

还是说回到软件行业,社会的主要产业将转变成服务业,自然软件行业也会出现对应的变化,那就是这里提到的面向服务。面向服务今后会影响到软件的交付模式,会对整个软件行业的体制产生影响。

而说到架构层面,面向服务是系统发布功能的一种方式。并且基于这种方式下不同的系统之间能有效地通信、协作。常见的实现技术就是Web Service。

五、软件全局观

软件架构设计的三个维度:面向对象、面向方面、面向服务。

最年长的一个维度就是面向对象,发展了好几十年,也是相对来说比较成熟的一个维度。它解决的问题是系统内部结构的设计。

面向方面的思想提出来能够弥补面向对象的缺陷。面向对象的方式不能实现横切关注点的分离,而面向方面正是为了解决这个问题。面向方面与面向对象一样都是解决系统内部结构的设计。

面向服务更多的是涉及到系统的外部,简单地说就是发布功能。它并不关注系统内部结构的实现,所以说面向服务与面向对象或者面向方面并不冲突。

这三个维度并不是绝对孤立的,它们之间会互相影响、制约。我们在分析架构的时候需要同时考虑到这三个维度的问题。这样有助于我们设计出更加优秀的架构。


软件架构为谁而设计

(节选自《软件架构设计》书稿) 

……如此看来,架构师应当为项目相关的不同角色而设计(如图5-2所示):

l        架构师要为客户负责,满足他们的业务目标和约束条件;

l        架构师要为用户负责,使他们关心的功能需求和运行期质量属性得以满足;

l        架构师必须顾及处于协作分工“下游”的开发人员,

l        架构师还必须考虑“周边”的管理人员,为他们进行分工管理、协调控制、评估监控等工作提供清晰的基础。

 

 

5-2   软件架构师为谁而设计

 

一言以蔽之,软件架构师必须做到内外兼顾、各层并重(如图5-3所示)。只有这样,软件架构才能和它“包含了关于如何构建软件的一些最重要的设计决策”的“地位”相符。

 

补充三点:

●这个话题我在2006IBM开发者大会的预热课堂上有过演讲,说明了如何运用基于多视图的架构设计方法应对上述问题。

●另外可参考我在IBM DW上发的文章:运用RUP 4+1视图方法进行软件架构设计

●其实,《软件架构设计》一书讲述的具体方法和4+1方法有所不同……例如,明确引入“质量属性分析”活动来为性能、可伸缩性、可重用性、可扩展性等非功能需求制定相应的架构决策。书的第15章专门介绍质量属性分析(例如如何运用“质量-场景-决策”表这种思维工具落实需求、制定设计决策等)。

 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454918.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WiFi密码分享有妙招 不必口头相传

移动互联网的迅速崛起,使得我们可以方便的使用手持移动设备进行上网。尤其是在家庭中,使用智能手机、平板电脑、笔记本电脑等移动设备进行上网和娱乐已经成为主流,台式机上网正日渐式微。在家中时,我们通过无线路由器提供的WiFi网…

javaweb(二十一)——JavaWeb的两种开发模式

一、JSPJavaBean开发模式 1.1、jspjavabean开发模式架构 jspjavabean开发模式的架构图如下图(图1-1)所示 图1-1 在jspjavabean架构中,JSP负责控制逻辑、表现逻辑、业务对象(javabean)的调用。 JSPJavaBean模式适合开发业务逻辑不太复杂的web应…

概率论与数理统计思维导图知识框架_考研概率论与数理统计 综合题型秘籍思维导图① 随机变量1~3章 [21考研上岸之旅]...

Hello World,我的朋友,这里是一颗小白蛋,大千世界,很高兴以这样的方式与你相遇前言在复习过程中发现概率论知识点很少且集中 所以没有分开章节去整理王安式概率论辅导讲义张宇概率论9讲方浩强化班1800题 综合题型秘籍在学习过程中…

php mysql删除失败_php+MySQL实战案例【七】数据编辑、删除

​本节内容中讲解用户管理模块中的修改用户信息和删除用户。修改用户信息:可对选择的用户记录进行编辑,可修改用户名、密码、性别、手机、邮箱和地址信息。删除用户信息:将列表中指定的用户进行删除操作。二、编辑用户信息编辑用户信息&#…

1.three.js世界的4大要素

一、三大组件 在Three.js中,要渲染物体到网页中,我们需要3个组建:场景(scene)、相机(camera)和渲染器(renderer)。有了这三样东西,才能将物体渲染到网页中去。…

架构设计 例子和实践

系统设计说明书(架构、概要、详细)目录结构 虽然这些文档一般来说公司都是有模板的,但我写这些文档以来基本上是每写一次就把目录结构给改一次,应该说这是因为自己对这些文档的理解开始加深,慢慢的越来越明白这些文档的作用和其中需要阐述的东…

activiti 批量 mysql_Activiti6系列(3)- 快速体验

一、部署启动activiti####1、部署,将两个war包拷贝到Tomcat下即可。![](https://img2018.cnblogs.com/blog/1755845/201908/1755845-20190802010532367-2002399291.png)2、启动tomcat,访问http://127.0.0.1:8080/activiti-app默认账号密码:ad…

【启动】Windows上启动图形化软件,报错: 无法启动此程序,因为计算机中丢失api-ms-win-crt-runtime-1-1-0.dll...

今天在安装了jetbrains官网上的ToolBox软件后,没有办法启动起来,报错如下: 无法启动此程序,因为计算机中丢失api-ms-win-crt-runtime-1-1-0.dll 尝试重新安装了并没有什么用,现在来解决方法: 直接找到官方的…

论文: YOLO9000-Better,Faster,Stronger

论文阅读: YOLO9000-Better,Faster,Stronger YOLOv2 是经过改造之后的YOLO Batch Normalization:在所有的conv layer后加了BN之后提高了2% mAP,BN可以帮助regularize模型,这样的话就可以放弃 dropout。 High Resolution Classifi…

怎么ie取消要打开或保存来自_取消认证后,发票抵扣就这么简单!

点击标题下「中财讯集团」可快速关注3月1日起,取消增值税发票认证的纳税人范围扩大至全部一般纳税人。一般纳税人可以自愿使用增值税发票选择确认平台查询、选择用于申报抵扣、出口退税或者代办退税的增值税发票信息。具体如何操作呢?掌握以下步骤&#…

好的软件架构设计

什么是架构 前言:软体设计师中有一些技术水平较高、经验较为丰富的人,他们需要承担软件系统的架构设计,也就是需要设计系统的元件如何划分、元件之间如何发生相互作用,以及系统中逻辑的、物理的、系统的重要决定的作出。在很多公…

python线程状态_Python线程

1. 线程基础1.1. 线程状态线程有5种状态,状态转换的过程如下图所示:1.2. 线程同步(锁)多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。考虑这样一种情况:一个列…

JavaScript中错误正确处理方式,你用对了吗?

JavaScript的事件驱动范式增添了丰富的语言,也是让使用JavaScript编程变得更加多样化。如果将浏览器设想为JavaScript的事件驱动工具,那么当错误发生时,某个事件就会被抛出。理论上可以认为这些发生的错误只是JavaScript中的简单事件。 本文将…

文件分割机

文件分割与合并 要求:实现对大文件的分割与合并。 按指定个数切(如把一个文件切成10份)或按指定大小切(如每份最大不超过10M),这两种方式都能够。 程序说明: 文件分割:把一个文件分割…

mysql pow函数怎么用_pow函数怎么用

PHP pow函数表示指数表达式。pow函数怎么用?php pow()函数 语法作用:pow()函数的作用是将一个数进行n次方计算后返回语法:pow(X,Y);参数:X表示要做处理的数字Y表示指定n次方中的n数值说明:返回X的Y次方幂,如…

【IntelliJ IDEA】添加一个新的tomcat,tomcat启动无法访问欢迎页面,空白页,404

第一部分,添加一个tomcat 1.先把Toolbar 和 Tool Buttons显示出来 2.选择Edit Configurations 3.添加一个新的tomcat server进来 解决no artifacts configured问题,就是没有项目加入里面 先添加一个没有的项目 启动之后找不到 页面 第二部分&#xff0c…

mac eclipse tomcat mysql_mac下使用eclipse+tomcat+mysql开发 j2ee(一)

在这里是使用eclipse+tomcat+mysql的方式。1、软件下载(1) eclipse我使用的是mac,因为本人是苹果客户端开发者,所以目前只有苹果机器了。首先下载eclipse for mac,选择mac 64位,下载eclipse-jee-kepler-SR1…

社交系统ThinkSNS-plus(TS+)V1.0发布!

2019独角兽企业重金招聘Python工程师标准>>> 需要购买源码的同志们,依然随时可以联系我们手机:18108035545(同微信);电话:028-82884828 ;QQ:3298713109; 从决…

.net 读取mysql数据库配置文件_.NETCore添加及读取默认配置文件信息

这里的默认配置文件指的是项目中的appsettings.json文件,我们可以把一些配置信息保存在里面,比如数据库连接信息。来吧,看例子:1、先在appsettings.json文件中写入数据库的连接信息:{"Logging": {"LogL…

h5 img js 点击图片放大_H5实现移动端图片预览:手势缩放, 手势拖动,双击放大......

查看示例效果:一、功能介绍图片预览主要有以下几个功能点组成:监听图片点击事件,进入图片预览模式自定义手势事件, (双指缩放,滑动,双击。。。)监听图片手势事件,通过 transform-matrix 实现图片的各种变换…