软件构造第一部分——软件构造基础内容梳理

一.软件构造的视图和质量分析

1.软件系统构成的三个维度:

       按阶段划分:构造时/运行时视图;

  按动态性划分:时刻/阶段视图;

  按构造对象的层次划分:代码/构件视图。

2.软件构造多维视图:

  软件构造第一部分——软件构造基础内容梳理

 

  Moment维度关注程序在某一时刻的表现,而Period关注的是程序在一段时间内的表现;Build-time维度关注程序还未被投入运行,编码阶段的表现,而Run-time维度更关注于程序运行时的表现。

  (1)Build-time:构造代码的过程,代码分为逻辑结构和物理结构。

    Moment,code-level view:基于词汇的半结构化源代码,AST(彻底结构化,将源代码变成一棵树,对树的修改等价于对源代码的修改)

    Period,code-level view:代码变化,被定义为在版本迭代中代码内容的的增删改查。

    Moment,component-level view:源文件的组织方式:package(包),library(库),包括别人提供的库和你自己积累的库。

    寻找库的命令:javac -classpath ./lib/*.jar

    静态链接:发生在构造阶段,库被拷贝成代码,执行时无需提供库文件。

    Period,component-level:Version Control System (VCI),版本更新。

  (2)Run-time:运行时,程序被载入内存,开始运行。

         代码层面:逻辑实体在内存中如何实现?

         构建层面:物理实体在物理硬件环境中如何呈现?

    动态链接:库文件不会在build阶段被加入可执行软件,仅仅做出标记;程序运行时,根据标记装载库到内存;发布软件时,记得将程序所依赖的所有库都复制给用户。

         分布式运行程序态:需要多个运行程序,分别部署于计算机的多个物理环境。

    Moment,code-level view:代码快照图:描述程序运行时内存变量层面的状态(debugger)。

    Period,code-level view:执行跟踪:用日志记录程序执行的调用次序。

    Moment,component-level view:硬件部署图。

    Period,component-level:系统层面的事件日志。

3.软件构造:不同视图的转换

  软件构造第一部分——软件构造基础内容梳理

 

  ①从无到写出代码,就进入了Build-time维度,开始只是单个的没有任何联系的代码文件,所以是在moment+Code-level维度;

  ②此时随着时间的推移,代码删删改改,就属于Period+Code-level了,而代码越写越多成为了一个包,甚至形成了一个库,于是就属于moment+Component-level维度了;

  ③但是随着时间的推移,库文件由于需求的变化发生了变化,所以就属于Period+Component-level;

  ④代码写好了,投入运行,进入Run-time维度,观察的如果是某一句代码的执行后结果,那就是moment+Code-level维度,但如果看的是代码执行的轨迹,那就是Period+Code-level维度,而如果看的是一个库文件的连接情况等,那就是moment+Component-level维度了;如果看的是线程或进程的执行过程,也就是通过日志等手段查看一段时间内系统都做了什么事情,那么就是Period+Component-level了。

4.软件系统质量评价标准

       外部质量因素影响用户,内部质量因素影响软件本身和它的开发者。

       外部质量的因素:

  (1)正确性:按照预先定义的规范运行,是最重要的质量指标。

    防御性编程:在写程序的时候就保证正确性。

    形式化方法:通过形式化验证发现问题。

       (2)健壮性:对正确性的补充,出现规约定义之外的事情时,软件要做出恰当的反应。

              Spec范围越大,规约定义越好。

       (3)可扩展性:对软件的规约修改的容易程度。规模越大,扩展起来越不容易。

              简约主义设计和分离主义设计。

       (4)可复用性:一次开发,多次使用;发现共性。

       (5)兼容性:不同的文件是否能够相互容易的集成。

              保持设计的统一性,即制定标准化。

       (6)性能:需要与其他特性进行结合。过度优化可能导致软件不再具有其他特性。

       (7)可移植性:软件可方便的在不同的技术环境之间移植。

       (8)易用性:容易安装,监控的软件。可以给用户提供详细的指南。

       (9)功能性:指系统提供的可能性范围。增加功能需要其他小属性不增加范围。

       (10)及时性以及可验证性,完整性,可修复性和经济性等。

       内部质量的因素:代码的耦合度,内聚度(LOC)

       折中处理:

  (1)正确的软件开发过程中,开发者应该将不同质量因素之间如何做出折中的设计决策和标准明确的写下来;

  (2)当某一项满足的足够好的时候有可能其他项的表现极差,此时需要做权衡,使得各部分的表现都较好,在某些特定要求下也可以放弃优化其他项而做到某一项的极致;

  (3)虽然需要折中,但正确性绝不能与其他质量因素折中。

       最重要的质量因素:

  Correctness and robustness:reliability

  Extendibility and reusability:modularity

  Correctness:封装、去中心化

  Robustness:封装、错误处理

  Extendibility:封装、信息隐藏

  Reusability:模块化、组件、模型、模式

  Compatibility:标准化模块和接口

  Portability:信息隐藏、抽象

5.五个关键的质量指标:

  Elegant and beautiful code:代码要容易理解,通过统一变量/方法的命名标准、代码的风格、注释、包组织结构、必要时重构代码等方式让代码尽可能的容易理解。

  Design for/with reuse:ADT/OOP、接口、继承(Overload、Override)、多态、泛型、框架等技术可用于提高代码的可复用性。

  Low complexity:当复杂度较低的时候,代码就容易被扩展新的功能,所以要高内聚低耦合,遵从SOLID原则、OO设计模式、使用VCS控制代码版。

  Robustness and correctness:使用测试驱动的开发、异常处理、Assertion机制、防御式编程等技术保证程序的健壮性和正确性。

  Performance and efficiency:使用设计模式、并行/多线程等技术提升性能。

二.软件测试和测试优先的编程

  认可“测试”的价值,搞清楚“测试优先”的哲理;

  学会用等价划分和边界值分析方法为模块设计测试用例;

  可用工具度量一组测试用例对代码的覆盖度;

  各种各样的测试都有初步了解。

1.测试:在规定的条件下对程序进行操作,以发现程序错误,衡量软件品质,并对其是否能满足设计要求进行评估的过程。

  (1)没有最好的测试方法,所有测试方法都有缺陷。

       (2)测试跟其他活动的目标相反:破坏、证错、“负能量”,即我们希望发现“错误”。

         测试种类:单元测试,集成测试,系统测试,回归测试(后面测试之后再测一遍前面的测试)等。

         白盒测试:对程序内部代码结构测试。

         黑盒测试:对程序外部表现出来的行为的测试。

2.测试用例 = 输入+执行条件+结果

  最好的测试用例:能发现错误,不冗余,有最佳特性,不复杂也不简单。

3.测试优先的编程

       先写spec,再写符合spec的测试用例,写代码执行测试,有问题再改,再执行直到通过测试用例。

       spec:包含函数参数,其他变量,返回值以及代码中方法的解释

       先写测试会节省大量的时间。需求也可以被转换成特定的测试用例,然后更新软件。

4.单元测试:针对软件的最小单元模型开展测试,隔离各个模块,容易定位错误和调试。

       可以针对单元测试建立驱动(接受测试用例数据并传给组件)和桩(替换组件从属的模块),这样可以对任何单独输入传给测试程序进行测试。

5.集成测试:Junit

       断言方法:AssertEquals,AssertTrue,AssertFalse(AssertThat不好用)

6.黑盒测试:检查代码功能,不关心内部细节。

       用尽可能小的测试尽快运行,并尽可能快的发现错误。

       (1)等价类划分:将被测函数的输入划分为等价类,从等价类中导出测试用例。

              针对每个输入数据需要满足的约束条件划分等价类。

              每个等价类代表对输入约束加以满足/违反的有效/无效数据的集合

              假设:相似的输入将展现相似的行为,所以从每个等价类中选一个测试样例即可。

       (2)边界值分析方法:对等价类划分方法的补充。

              大量错误发生在输入值的边界,可能是边界突变或者边界条件特殊。

              解决方法:把边界值单独作为等价类中的一个类。

              两种覆盖原则:

    笛卡尔积:全覆盖,多个划分维度的多个取值组合起来,每组合至少一个样例。

    只覆盖每个取值:每个组合最少被覆盖一次,最多不超过5个。

    前者完备,但用例数量多,代价高;后者代价低用例少,但覆盖度不一定高

7.白盒测试:考虑实现细节,根据程序执行路径设计测试用例,一般较早执行。

       独立路径测试:对程序所有执行路径进行等价类划分,找出有代表性的最小路径,设计测试用例,保证每个路径至少被覆盖一次

8.代码覆盖度:已有的测试样例有多大程度覆盖了被测程序。

       分为函数覆盖,语句覆盖,分支覆盖,条件覆盖,路径覆盖。

       测试效果以及测试难度:路径覆盖>分支覆盖>语句覆盖。

9.自动测试和回归测试:

  自动测试:自动调用被测函数,自动判定测试结果,自动计算覆盖度。

  回归测试:一旦程序被修改,重新执行之前的所有测试。

  一旦发现bug,写一个可重现此bug的测试用例,并将其加入测试库,达到自动化回归测试的结果。

10.编写你的测试策略:

       测试策略(根据什么设计测试用例)需要在程序中显示记录下来。

       在代码评审过程中,其他人可以理解你的测试,并评价你的测试是否充分。

三.软件构造过程和配置管理

1. Software Development Lifecycle(SDLC):软件发展生命周期

  软件构造第一部分——软件构造基础内容梳理

2. Traditional Software Process Models

       两种基本模式:线性过程,迭代过程。

       模式:瀑布过程,增量过程,V字模型,原型过程,螺旋模型。

       选择模式的依据:用户参与度(适应变化的能力),开发效率/管理复杂度,软件质量。

       (1)瀑布过程:线性推进,阶段划分清楚,整体推进,无迭代,管理简单,无法适应需求增加/变化。

       (2)增量过程:线性推进,增量式(多个瀑布串行执行),无迭代,比较容易适应需求增加。

       (3)V字模型:瀑布过程的扩展,对模型的结果进行验证与确认。

       (4)原型过程:在原型上持续不断的迭代,发现用户变化的需求。

       迭代:开发出来后由用户试用/试评,发现问题反馈给开发者,开发者修改原有的实现,继续交给用户审评。循环往复这个过程直到用户满意为止。时间代价高,但开发质量也高。

       (5)螺旋模型:多轮迭代基本遵循瀑布模式,每轮迭代有明确的目标,遵循原型过程,进行严格的风险分析,方可进行下一轮迭代。

3. Agile Development

  敏捷开发:通过快速迭代和小规模的持续改进,以快速适应变化。

  敏捷开发=增量+迭代,每次迭代处理一个小规模增量。

  极限的用户参与/小步骤迭代/确认与验证。

4. Software Configuration Management (SCM) and Version Control System (VCS)

  SCM:软件配置管理:追踪和控制软件的变化。

  软件配置项:软件中发生变化的基本单元(比如文件)。

  基线:软件持续变化过程中的稳定时刻(比如对外发布的版本)。

  (1)代表多个源代码文件的一组版本。

  (2)代表文档的一个稳定状态。基线提升:文档大修改的更新。

  CMDB:配置管理数据库,存储软件的各配置项随时间发生变化的信息+基线。

  VCS:版本控制系统

  (1)本地VCS:无法共享和协作,存储于开发者本地机器。

  (2)集中式VCS:仓库存储于独立的服务器,支持多开发者之间的协作。

  (3)分布式VCS:仓库存储于独立的服务器+本地的服务器。

5. Git as an example of SCM tool

       组成部分:本地的CMDB,工作目录(本地文件系统),暂存区(隔离工作目录与git仓库)。状态包括已修改,已暂存,已提交。

       对象图:git项目的历史,是一个有向无环图。

  本地库:使用git commit提交;远程库:使用 git push 提交,使用 git pull 下载。

6. General process of software construction

  软件构造第一部分——软件构造基础内容梳理

 

  (1)Programming(coding)

              从用途上划分:编程语言(C,C++,Python,Java),建模语言(UML),配置语言(XML),构建语言(XML)。

              从形态上划分:基于语言学的构造语言,基于数学的形式化构造语言,基于图形的可视化构造语言。

              Integrated development environment (IDE):集成开发环境。

              包含:源代码编辑器,智能代码补全工具,代码重构工具;文件管理;库管理;软件逻辑实体可视化;图形化用户界面构造器;编译器,解释器;自动化build工具;版本控制系统;外部第三方工具等。

       (2)Review and static code analysis(代码分析/评审)

              结对编程,走查,正式评审会议,自动化评审。

  (3)Dynamic code analysis / profiling

       动态分析:要执行程序并观察现象,收集数据,分析不足;对代码的运行时状态和性能进行度量,发现代码中的潜在问题。

  (4)Debugging and Testing

       测试:发现程序是否有错误。调试:定位错误,发现错误根源。

  (5)Refactoring

       重构:在不改变功能的前提下优化代码。

7.build过程:Validate Þ Compile Þ Link Þ Test Þ Package ÞInstall ÞDeploy

  软件构造第一部分——软件构造基础内容梳理

发表评论

相关文章