[架构之路-52]:架构师 - 嵌入式软件常见难查问题与解决办法大总结-1-架构设计不合理问题
Posted 文火冰糖的硅基工坊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[架构之路-52]:架构师 - 嵌入式软件常见难查问题与解决办法大总结-1-架构设计不合理问题相关的知识,希望对你有一定的参考价值。
目录
4.3 采用设计模块来设计软件架构,包括系统架构和模块内部的架构
第1章 问题描述
在工程实际中,有时候为了赶项目进度、赶市场进度,开发目标软件的唯一目标就是以最快的时间,构建一个符合客户需求的软硬件系统,“快”为第一要素,是短期指标,然后像“适应性”、“弹性”、“可复用性”等长期指标比忽略,导致后期,无论是产品的维护、bug的修复、新功能的增加都非常困难,一个小小的业务需求,都会牵一发而动全身,需要大量的时间与精力,甚至一个小小的故障修复,引入更多的问题。整个目标系统变得越来越僵化,包袱越来越沉重。最简单的变更或“很小的”缺陷修复都不知道要花多少时间。管理软件开发周期非常难。客户只要等着实现重要的特征,管理层对开发团队不能满足业务目标感到越来越沮丧。
第2章 问题分析:好的软件架构的特点
2.1 性能:承载力
比如一栋房子,能承载多少人能做多少个房间,是客户比较关注的问题。从软件架构方面来说,一个架构能承载多少个业务系统或功能系统,能承载多少代码行数,在达到规定的代码量时是否能有效正常的运行,是程序员和客户都关注的问题。对于服务器来说,服务器的架构能承载多少人同时访问,能承载的日均访问量是多少,这就是它承载力的体现。对于客户端来说,它能显示多少个UI功能,可以同时渲染多少个模型,分辨率可以达到多少,则是它的承载力体现。
2.2 可用性、易用性
易用性其实很简单,就是你这个产品设计的好不好用,是不是方便使用,这个可能是很多架构师会忽略的一点,因为大部分架构师只是一个程序员。程序员很少会从客户的角度去想问题,所以就会导致设计出来的东西不符合客户的使用习惯。易用性也决定了软件的整体开发效率,因为一个好的架构,会让团队成员容易上手,子系统容易对接,开发效率高,各模块和各系统的编写只需要关注系统的设计和编码工作,其他模块通信方面的事情,架构可以提供很好的兼容。一味地追求最新的、最多功能的软件特性的架构是危险的!!!除了技术炫技之外,对整个团队没有太多的好处,对产品的演进也没有太多的好处。它会让产品陷入不稳定、不确定、让团队不断适应无用的新变动。
2.3 扩展性
如果一栋房子只能住人,不能放其他的东西,那么这个房子的设计用途就太单一了,大的家具不能放、长的家电不能放、特殊的水电不能装,那这个房子肯定没人买。架构就是要适应不同类型的需求,可添加不同类型的系统、不同功能的子系统,是非常有必要的。
软件架构也是这样,要具备更多的功能就要具备更高的扩展性。可扩展性的关键就在于,在添加新系统新功能的时候,会不会影响其他系统,添加这个新系统的代价大不大,会不会导致系统整体性能问题。如果添加一个新系统,导致其他系统使用有问题,那么这个架构的可扩展性就很差。
2.4 伸缩性
什么是伸缩性?其实就是你设计的这个方案或系统是否可以根据需求适配不同数量的功能或子系统,比如一栋房子由于住的人比较多,它的框架是否可以分割成多个房间,当人数变少的时候,能不能根据根据需求把多个房间合并成一个大单间? 这就是可伸缩性,在我们设计的软件系统中,架构的可伸缩性决定了架构的可适配性,比如,当这个系统使用人数较少的时候,是否支持减少一些服务器来支撑服务端的运行,当系统使用的人数较多时,访问量较大时是否支持添加服务器来增强系统的支持。
2.5 可靠性、容错性
房子也会有损坏的时候,同样也会出现某个地方做工不好,导致使用的时候出现各种破损,我们保证不了完全没有问题,但是需要保证它不会因为一点小问题,出现倒塌的情况。软件架构也是这样,如果软件中某个系统出现了一点小BUG导致整个系统使用不了,那这个架构容错性就很差,软件中的一些BUG很常见,我们无法避免,但是我们应尽量保证这个BUG的影响范围最小。同时,若出现系统无法使用的情况,应该有备份方案,比如自动启动或者自动保存数据等功能,也应该能够让开发人员及时知道问题的发生,以及问题所在的位置并记录错误信息。
2.6 安全性、鲁棒性
鲁棒性是Robust的音译,也就是健壮和强壮的意思。它也是在异常和危险情况下系统生存的能力。比如说,计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下,能否不死机、不崩溃,就是该软件的鲁棒性。所谓“鲁棒性”,也是指控制系统在一定(结构,大小)的参数摄动下,维持其它某些性能的特性。根据对性能的不同定义,可分为稳定鲁棒性和性能鲁棒性。
第3章 问题分析:影响软件系统复杂性的因素
系统的架构是从多个维度展现的,影响系统架构复杂性的因素包含:
- 软件的静态分层的数量 (静态)
- 协议包封装的静态数据结构的复杂程度 (静态)
- 软件的功能模块的数量 (静态)
- 软件的进程的数量 (静态)
- 软件的线程的数量 (静态)
- 算法的复杂程度 (过程)
- 源代码的行数(静态)
- 状态机的数量 (动态)
- 状态机中状态的数量 (动态)
- 线程/进程之间的交互路径
- 业务场景的数量 (动态)
- 软件时序的数量 (动态)
- 时序图中消息的数量 (动态)
第4章 如何设计好的软件架构
4.1 架构师必须熟悉业务
软件系统是为业务服务的,业务才是“目的”, 软件系统本身并不是目的,软件系统是为了达成业务系统目标的手段和方法。有很多架构师为了软件架构而软件架构,甚至不考虑自身业务的需求,直接照搬所谓的“最新的“、“成功的”、“业界最优的”软件架构。
- 适应当前的业务需求是基础,不需要过多的考虑未来五年、十年的业务需求。适合的才是最好的。
- 充分考虑和预测未来的业务的扩展:要根据业务的扩展性,来设计软件的扩展性。如果可预见性,未来没有没有扩展重大的新业务的需求,那么相应的软件架构就没有必要采用高扩展的软件架构。比如嵌入式的传感器,就没有必要把“云”计算、“云”原生的软件架构放到嵌入式设备中。当然,这是一个极端的例子,但可以充分的说明,软件架构必须为业务服务的核心思想。因此,软件架构师,必须熟悉业务,不熟悉当前软件业务和未来业务的扩展的架构师是很难设计出好的软件架构的。
4.2 借鉴业内成熟的架构
不照搬,并不意味着不要借鉴。借鉴业内成熟的软、硬件架构是相对稳妥、高效、安全的做法。
无论是软件、还是硬件都可以业内的架构为基础、为蓝本、为基线。然后根据自身业务的特点,进行适配、裁剪和增加新的功能。
熟悉业内常规的、成熟的、最新的软件架构是架构师的一项基本功。
熟悉这些架构,并不是意味着,必须立即在目标系统中实施这些软件架构。
备注:
在移动通信领域,3GPP已经定义整个网络的网络架构的标准,网络设备商以3GPP定义的网络架构来实施。架构师一个重要的职责是理解业务需求,并把业务需求映射到产品的软件架构中。另一方面,3GPP虽然定义设备之间的接口,但并没有定义设备内部模块之间的接口,软件架构师还需要定义设备内部软件的模块以及模块之间的消息接口、消息交互流程等。
4.3 采用设计模块来设计软件架构,包括系统架构和模块内部的架构
设计模式(Design pattern)代表了最佳的实践,设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
用设计模式构建一个新系统、构建一个新的软件模块的时候,短期会让人感觉有多此一举的味道,有脱裤子放屁的感觉,当中长期来看,设计模式能够克服“坏”架构的特征。
设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。
设计模块通常被有经验的面向对象的软件开发人员所采用。
4.4 用UML统一建模语言为系统建立模型
在正式编码前,为系统建立业务模型、软件层次模型、软件状态机模型、软件时序模型,而不是一上来就陷入细节,进行软件的编码与实现。
UML建模语言提供了构建一个软件系统,通用的思想、方法、工具、模型。
UML能够帮助架构师、软件设计师快速构建一个常规的软件系统。
UML2.0一共有13种图形(UML1.5定义了9种,2.0增加了4种)
-
用例图:从用户角度描述系统功能。
-
类图:描述系统中类的静态结构。
-
对象图:系统中的多个对象在某一时刻的状态。
-
状态图:是描述状态到状态控制流,常用于动态特性建模
-
活动图:描述了业务实现用例的工作流程
-
顺序图:对象之间的动态合作关系,强调对象发送消息的顺序,同时显示对象之间的交互
-
协作图:描述对象之间的协助关系
-
构件图:一种特殊的UML图来描述系统的静态实现视图
-
部署图:定义系统中软硬件的物理体系结构
-
包图:对构成系统的模型元素进行分组整理的图
-
组合结构图:表示类或者构建内部结构的图
-
交互概览图:用活动图来表示多个交互之间的控制关系的图
4.5 合理的横向和纵向切分
横向切分:软件分层、数据包的封装、层次关系。
- 如,移动通信:RF/L1/L2/L3
- 如, 数据通信:PHY/MAC/IP/TCP/应用层
纵向切分:
- 根据业务处理流程的环节纵向切分,不同的环节为不同的模块。
- 根据业务的场景纵向切分,不同的业务场景类型,为不同的模块,如,4G/5G L3的功能:移动性管理、无线资源管理、小区建立等,都是按照业务场景进行功能切分。
备注:
软件的功能切分,以适用业务特征为基本原则。
4.6 按照树形结构组织、逐步细化
按照树形的方式组织软件系统,是目前最符合大自然的组织方式。
Linux系统的设备、文件也都是按照树型方式进行组织。
国家、社会的组织架构也都采用树形的方式组织。
[项目管理-25]:高效沟通的利器,结构思考力与树形结构化表达_文火冰糖的硅基工坊的博客-CSDN博客
4.7 降低模块之间的耦合度
耦合性(英语:Coupling,dependency,或称耦合力或耦合度)是一种软件度量,是指一程序中,模块及模块之间信息或参数依赖的程度。
内聚性是一个和耦合性相对的概念,一般而言低耦合性代表高内聚性,反之亦然。
4.8 降低模块与模块之间通信
一个软件系统,模块与模块之间的通信,构成了一个内部的通信网。
避免网络内部的通信采用网状结构。
4.9 不定期根据业务的需求重构和演进架构
软件架构的迭代与演进,属于非功能性需求。
- 架构不能一成不变,架构要随着业务需求的演进而演进,一层不变的架构是危险的,总有一天,架构称为整个产品业务演进的最严重的制约因素。
- 除非是新产品,新软件系统,否则不能采用颠覆性演变,每个软件发布版本,都要根据未来规划的产品特征,进行预先的架构演进,为后续产品的新特征提前打下架构性基础。
以上是关于[架构之路-52]:架构师 - 嵌入式软件常见难查问题与解决办法大总结-1-架构设计不合理问题的主要内容,如果未能解决你的问题,请参考以下文章
[架构之路-55]:架构师 - 嵌入式软件常见难查问题与解决办法大总结-3-按照故障类型分类(调试手段与信息不足指针内存栈溢出性能)
[架构之路-106]:《软件架构设计:程序员向架构师转型必备》-16-常见的十余种软件分层架构
[架构之路-103]:《软件架构设计:程序员向架构师转型必备》-13-软件架构如何分层(四层架构)