软件架构设计的几点理解_birduncle的博客-程序员宅基地

技术标签: 软件架构设计  软件架构  

 

1.软件架构的基本介绍

架构架构师:软件体系结构是构建计算机软件实践的基础。与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础。从和目的、主题、材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟。一个软件架构师需要有广泛的软件理论知识和相应的经验来实施和管理软件产品的高级设计。软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。

软件架构:软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口来实现。

软件架构设计:软件架构设计就是从宏观上说明一套软件系统的组成与特性,是一系列有层次的决策。

2.软件结构设计的目的

  • 可重用:为大规模开发提供基础和规范,并提供可重用的资产,软件系统的大规模开发,必须要有一定的基础和遵循一定的规范,这既是软件工程本身的要求,也是客户的要求。架构设计的过程中可以将一些公共部分抽象提取出来,形成公共类和公共接口,其他功能模块所需相关功能即可调用,以达到重用的目的。
  • 缩短周期:一定程度上缩短项目的周期,利用软件架构提供的框架或重用组件,缩短项目开发的周期。
  • 降低开发和维护的成本:大量的重用和抽象,可以提取出一些开发人员不用关心的公共部分,这样便可以使开发人员仅仅关注于业务逻辑的实现,从而减少了很多工作量,提高了开发效率。
  • 提高产品的质量:好的软件架构设计是产品质量的保证,特别是对于客户常常提出的非功能性需求的满足。

3.软件架构的基本设计原则

  • 满足功能性需求和非功能需求:这是一个软件系统最基本的要求,也是架构设计时应该遵循的最基本的原则。
  • 实用性原则:就像每一个软件系统交付给用户使用时必须实用,能解决用户的问题一样,架构设计也必须实用,否则就会“高来高去”或“过度设计”。
  • 接口复用:公共部分可设计成接口,减少冗余,最大程度的提高开发人员的工作效率。
  • 低耦合:耦合是描述模块之间的依赖程度,如果一个模块的修改,都有另一个模块会受到影响,则两模块之间是相互依赖耦合的。(依赖具有传递性,耦合的两个模块可能间接依赖),低耦合是我们的设计目的,但不是不可以存在耦合不存依赖,依赖是必须的,因为模块之间是必须要通信交互。设计依赖应该依赖于不变或者不易变的接口,无需了解模块的具体实现,即为面向对象的封装性。
  • 高内聚:高内聚是指某个特定模块包括程序、类型都应完成一系列相关功能,描述了不同程序和类型中方法,方法中不同操作描述的逻辑之间的距离相近。高内聚意味可维护性,可重塑性,因为模块对外部的依赖少(功能的完备性)。如果两个模块之间的修改,互不影响各个模块的业务,这说明模块之间是高内聚的。模块的内聚和其担当的职责成反比,即模块的职责越多,模块的内聚性越低,这也是模块的单一原则(SRP),SRP提倡每个类型都最好只承担单一的职责,只有单一的改变因素。

4.软件架构设计的基本视图

由于软件系统的不同的角色会站在不同的角度上提出的问题,我们就得从不同的视角来看待软件架构设计这项工作:

  • 逻辑架构视角:从系统用户的角度考虑问题,设计出来的软件架构能够满足业务逻辑的需求,能够处理现在越来越复杂的业务逻辑需求。
  • 开发架构视角:从系统开发人员的角度来考虑问题,设计的架构要易于理解,易于开发,易于单元测试,最好做到让开发人员可以用最少的代码行数完成功能的开发。
  • 运行架构视角:从系统运行时的质量需求考虑问题,特别关注于系统的非功能需求,客户常常都会要求我们系统的功能画面的最长响应时间不超过4秒,能满足2000个用户同时在线使用,基于角色的系统资源的安全控制等。
  • 物理架构视角:关注系统安装和部署在什么样的环境上,例如现在最流行的企业应用服务解决方案IBM Http Server + WebSphere Application Server + DB2,WebLogic + Oracle等。
  • 数据架构视角:如今我们开发的各类系统,如管理信息系统(Management Information System,MIS)、ERP(企业资源计划),SAP,基本上都是对各类数据的操作,把一堆不太好懂的数据展现成用户容易看懂的数据,自动处理各类数据的运算等,所以数据的持久化是十分重要的一件事情。

    1、分析需求和理解业务模型(或领域建模)

    软件的需求,可以分为从用户视角和开发人员视角来看,从用户的角度看,又可以分为功能性和非功能性需求,我们必须从不同的视角和级别去全面的认识需求并分析需求,理解业务模型。实践表明,常常被我们忽视的非功能性需求常常会导致整个项目失败。而理解业务需求最好的方式莫过于进行领域建模,领域建模与需求分析往往是交替穿叉进行的,领域建模主要有以下三个方面的作用:

  • 探索复杂问题,弄清领域知识。Martin Fowler曾经说过,他采用面向对象方法最大的好处就是它有助于解决更为复杂的问题。领域建模本身作为辅助思维的工具,帮助我们将注意力始终保持在最为重要的业务概念及其关系上,使我们能够不断深入地,系统的对需求进行分析和认识。领域建模往往是一个从模糊到清晰,从零散到系统的过程。
  • 决定功能范围,影响可扩展性。任何模型都是对现实世界某种程序的抽象,这种抽象就会忽略某一些东西,例如忽略对象的属性和对象间的关系,而这些忽略往往都是带有一定的目的性的,这种忽略就决定了功能的范围。模型揭示了各种功能背后的结构,如果说定义功能相当于“拍照片”的话,那么领域建模就相当于“做透视”,更加关注问题领域的内在结构,相当于对问题领域进行了一定的抽象,良好的领域模型不仅能很好的支持现有的功能,而且还可以在一定程度上支持未来可能出现的新需求,体现良好的可扩展性。
  • 提供交流基础,促进有效沟通。领域建模通常会使用UML图作为呈现的方式,这样为我们的沟通提供了方便。当然,有时候文字在描述某些特定领域的问题时可能更适合,可以灵活运用。

      2、从各个视角来全面的考虑软件架构

    软件的架构设计必须考虑到各方面,根据前期工作确立的领域模型,关键需求,系统约束等进行设计,必须从用户、开发、运维等人员的角度去分析并解决问题。比如说,如果我们的运行架构采用Cluster方式时,就必须小心Cache和Session等的使用;如果我们的业务逻辑要求我们要操作多个数据库时,就要考虑采用支持二阶段事务提交的方式。

    只有将这些方方面面的问题都考虑到了,这样的架构设计才是完整的。至于每一个视图中,我们应该设计到什么细节这一问题,实际上与整个项目的过程定义有关。例如,如果我们有专门安排数据库概要设计的活动,那我们在架构设计的过程中就可以只需要关注更高层次的数据库特性及数据库之间的关系,而每一张表的数据字典可以在后续的相关活动中进行设计,但如果没有这样的活动,那我们就要细化到每一张表的每一个栏位,以及表之间的关系。

    3、解决技术面的重点问题和难题

    在软件架构设计的过程中,我们往往会需要攻克一些技术面的重点问题和难题,这完全是一项极其需要扎实的理论知识和丰富的实践经验支撑的工作。例如,我们如何提高整个系统的性能?如何能很好的导出极其复杂的“中国式报表”(一般比西方国家产出的报表要复杂很多,而且很多开源的BI类的框架并不能完全解决问题)?

    当遇到确实是很困难的问题,可以去求助度娘或Google,可以想尽办法一切可行的方式去解决,但是千万不要让问题停留在原地。

    4、召开架构设计评审会议进行同行评审

    架构设计评审是极其重要的一环,我曾将其形容为“七种武器”中的离别钩,就是因为在会议上,同行们可能会提很多问题或意见,而且很多意见很尖锐,所以一定要虚心接受,并做好记录,正所谓“良药苦口利于病,忠言逆耳利于行”。

    在评审会议之前,我们要完成很多准备工作,最好是能准备一份简明扼要的电子简报,把最重要的问题列出来,这样在进行评审会议时,就不会漫无目的,在会议前就将这些资料发给与会人员,请他们抽空先了解一下,在会议进行时,要学会控制会议的进度,提高会议的效率。

    5、针对关键Use Case在设计的架构上实现功能来验证架构。

    对于架构设计的验证也是一项十分重要的工作,其验证技术有很多种,在我们公司通常会采用Sample的形式,即XP中所说的迭代0,RUP中所说的切片。这样做的好处是既可以从实际的产品角度出发来有效的验证架构是否满足要求,又可以比抛弃型原型验证技术节省成本。

    这个Sample绝不是我们在解决架构设计中的问题时拿来做实验的一些代码的拼凑,而是完整的实现某一关键Use Case的符合架构设计和一系列规范的可交付的代码及相关文档。同时,这个Sample可以作为你在给大家讲解或培训架构时的教材,也可以作为开发人员使用此架构进行开发的蓝本,甚至是只需要复制粘贴,加上简单的修改即可。

    6、交付给客户Review。

    这一环节,在很多公司可能并不存在,因为他们的软件架构并不一定需要客户Review,但像我们这种做服务的公司,最重要的就是客尊,落实到软件架构设计这一活动,就是让客户理解并接受你的架构设计方案,同时,客户也会起到帮你验证架构的作用。通常,我们的架构得到客户的认可后,便可进入大规模的开发。

5.软件架构设计的常见误区和解决方案

  1. 架构设计的常常会“高来高去”。所谓高来高去,实际上就是我们的架构设计仅停留在模型阶段,但也绝不是产生第一支样例程式。
  2. 架构设计时常常会在某些方面过度设计(Over engineering)。为了一些根本不会发生的变化而进行一系列复杂的设计,这样的设计就叫过度设计,往往会带来资源的浪费并且会增加开发的工作量或难度。虽然我们必须考虑到系统的扩展性,可维护性等,但切忌过度设计。有时候或许你并不能判断出哪些设计是过度设计,此时你可以请教你的PM,让他站在整个项目的高度来帮你决策一下。
  3. 架构(Architecture)不是框架(Framework),也不是简单的将几种框架或技术的组合,框架本身也是有架构的。框架一般是针对于某一方面或领域的重用性和可扩展性非常好的半成品,我们可以用一句较为经典的话来总结:框架是软件,架构不是软件,框架是一种特殊的软件。我们在工作中通过将许多方面的可重用的工具类,公共类,基础类等抽象出来,即可形成一些可重用的框架。
  4. 架构设计绝不是新技术展示平台,合适的技术才是对于项目有利的技术,必须考虑到开发人员的能力和维护人员的能力。作为一名架构设计师应该更多的考虑如何平衡业务需求,织织运作(主要指团队中的协作)和技术三者的关系,而不仅仅是去关注那些技术细节。
  5. 架构设计的成功与否决定着系统品质的好坏,因为架构设计不好而导致交付的系统Bug过多,无法满足客户非功能性需求等问题,从而导致项目取消的案例时有发生。架构设计不是架构设计师一个人的事情,也不是几天就能完成的一项工作,必须是架构设计师付出大量辛勤劳动后的成果,其成败往往与组织、主管、项目经理的支持有着密切的关系。

6.软件架构设计的通用技巧

  • 分层(Layer)规则:这里的层是指逻辑上的层次(Layer),并非指物理上的层次(Tier)。目前的绝大多数的企业级应用系统中都分为三层,即表现层,领域层和数据层。在对各层次进行划分时,主要可以从以下几个方面来考虑:A、每一层是一个相对独立的部分,可以作为一个整体,无需对其它层了解;B、将层次间的依赖性降到最低,即降低耦合;C、可以从某种程度上替换掉某一层,而对其它层不会产生过多的影响;D,层次并不能封闭所有的东西,假如用户界面上增加了一个栏位,那么领域层就要增加一个数据域,数据层就要增加一个相应的字段。同时,过多的分层可能会对性能造成一定的影响。
  • 包(package)之间不要产生循环依赖:通常包的划分会先按不同的逻辑层来划分,在层的包下面再按功能来划分。避免包间的循环依赖是一个比较通用的规则,这样的规则一定有其存在的价值和道理,之所以这样主要是出于以下原因:A、循环依赖会使分层失去意义;B、循环依赖会带来许多潜在的风险,如可能会产生嵌套事务(nested transaction,JavaEE标准中并不支持这种事务)的现象,我就曾遇到过这样的问题,在一个项目中,事务放在业务逻辑层统一控制,但由于开发人员忽视了架构中这样的原则,在持久层调用了展现层的公用类,形成了回圈的现象,导致了嵌套事务的发生。
  • 设计模式的应用:在很多人的观念里,提供设计模式就等同于GOF的设计模式,其实设计模式是个广泛的概念,比如需求模式、领域模式、反模式等都属于设计模式。模式其实是一门工具,是人们对于过去解决某一类问题的经验总结,所以我们可以在设计活动中应用各种设计模式,但是在应用这些模式之前一定要先分析清楚问题,否则就可能出现“牛头不对马嘴”的现象。

7.写在最后

本文是题主转载与几位博主的文章,再次题主将其再次写出来为了便于查看,另外一方面也会在后来做该方面工作的时候可以继续去补充,希望能和大家共勉,一起去贡献出更精彩的博客!

注:文章转载列表:

1.架构师必看:谈软件架构师如何做好架构设计

2.软件架构设计总结

3.对软件架构设计的一些总结和理解


题主只是一个入门的小学生,希望大家多多指教!如果该帖子确实能解决您的问题,望多多留言,谢谢!


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/birduncle/article/details/82823305

智能推荐

最详细、最完整的相机标定讲解_传统相机标定法_Dr.视觉小新的博客-程序员宅基地

相机标定详解最近做项目要用到标定,因为是小白,很多东西都不懂,于是查了一堆的博客,但没有一个博客能让我完全能看明白整个过程,绝大多数都讲的不全面,因此自己总结了一篇博客,给自己理一下思路,也能够帮助大家。(张正友标定的详细求解还未完全搞明白,后面再加)参考博客:相机标定(Camera calibration)原理、步骤(http://blog.csdn.net/lql0716/artic..._传统相机标定法

PHP错误 Warning: Unknown: failed to open stream: Permission denied in Unknown on line 0 Fatal error:_php warning: unknown: failed to open stream: opera_Rudon滨海渔村的博客-程序员宅基地

前言项目移植到新的VPS后访问不了,错误信息:Warning: Unknown: failed to open stream: Permission denied inUnknownon line0Fatal error: Unknown: Failed opening required '/var/www/project/index.php' (include_path='.:/usr..._php warning: unknown: failed to open stream: operation not permitted in unkn

json格式化_json 格式化_蜜獾云的博客-程序员宅基地

JSON格式化工具大萨达下载地址https://pan.baidu.com/s/1ghhKuSe25VcEb4jW-TlSWw_json 格式化

spring cloud feign实现_spring cloud feign 实现类_方二华的博客-程序员宅基地

feign的底层实现为io.github.openfeignspringcloud整合了底层实现,同时整合的还有ribbon与hystrix本文描述了springcloud如何对openfeign进行整合的一、原生的openfeign不用springcloud-openfeign,直接使用openfeign的方式根据官方示例:public interface GitHub { @RequestLine("GET /repos/{owner}/{repo}/contributors") _spring cloud feign 实现类

Cesium实现UnrealBloom泛光效果_cesium unrealbloom_三维网格的博客-程序员宅基地

泛光(Bloom)是一种常用的后期处理特效,游戏中更是随处可见,这里直接上我们的效果图。图1.UnrealBloom泛光效果Cesium内置的bloom后期处理,是对全屏进行处理,还不能只针对选中的特定对象添加泛光效果,通过修改shader代码也可以实现。不过今天我们不做改进,而是引进three.js的UnrealBloomPass,在Cesium中实现一个新的泛光效果。从UnrealBloomPass这个名字看,大概是说从Unreal Engine那里学来的吧,另外也是在名称上区别于辉.._cesium unrealbloom

随便推点

斗米面试--实习软件测试工程师_大连斗米科技测试面试_迷惘的提莫酱的博客-程序员宅基地

一、自我介绍我叫蒋银山,目前是本科软件工程专业在读,明年六月份毕业,对软件开发和软件测试都有浓厚兴趣,熟悉java、html、css,js、ajax、mysql数据库、GIt工具,了解http和TCP/IP协议,了解spring框架,主修课程《数据结构与算法》《数据库原理》《java程序设计》《web前端设计与开发》《软件项目管理》《计算机网络》《Linux操作系统》等二、职业规划三、软件测..._大连斗米科技测试面试

Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu_onnx export failure: expected all tensors to be on_La belle360的博客-程序员宅基地

device = torch.device('cuda')torch.rand(8,1).to(device)原因在于torch函数生成的tensor需要转到GPU上_onnx export failure: expected all tensors to be on the same device, but foun

PyTorch学习(基础)—— Tensor & autograd_loveliuzz的博客-程序员宅基地

几乎所有的深度学习框架背后的设计核心都是:张量和计算图。一、Tensor 在pytorch中,Tensor(一般可译作“张量”)是重要的数据结构,torch.Tensor是存储和变换数据的主要工具,可认为是一个高维数组,它可以是一个数(标量)、一维张量(向量)、二维张量(矩阵)或更高维的张量。Tensor和numpy中的多维数组ndarray很类似,但Tensor可以使用GP...

一种粒子连线动画的实现方式_Dragon_Kai_L的博客-程序员宅基地

一种粒子连线动画的实现方式<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <title></title> <!-- jQuery Version 1.11.0 --> <script src="ht...

左侧菜单的设计_yuhui66666688gfbfdy的博客-程序员宅基地

左侧菜单的设计: 1, A:在主页面中include左侧的菜单页面(这个页面中在操作div) &lt;table width="100%" border="0" cellspacing="0" cellpadding="0" class="warp tc bc mt10"&gt; &lt;tr&gt; &lt;td width=&qu_左侧菜单设计

pyqt5的下载进度条 实现模板_pyqt实现下载模板_一心狮的博客-程序员宅基地

说明QProgressBar,进度条控件,使用很简单。但如何结合下载功能,实现下载进度条呢?本文主要参考了《PyQt5实现下载进度条》这篇文章,感谢作者的分享。其中的下载线程,基本原封不动的照搬了,这个下载线程正是技术要点所在。下载线程这个下载线程,其实包含了不少知识点,可以多多借鉴参考哦。1.pyqt5的线程 QThread2.requests 流下载模式3.自定义信号和槽函数..._pyqt实现下载模板

推荐文章

热门文章

相关标签