代码层:源代码是如何被函数、类、方法和接口逻辑化地组织起来(基于词汇、语法、语义) 组件层:源代码是如果被文件、目录、包和库所架构的 时刻层:代码和组件在一个精确的时间是怎样的 时期层:它们随着时间如何进行变化
代码+时刻:面向词汇的代码,面向语法语义的程序结构(如AST,UML图) 代码+时期:行级代码修改、删除 组件+时刻:代码组织成文件和目录,文件封装为包、组件和子系统,可复用部分以库的形式存在,在程序需要库中某些函数时复制到可执行程序中(静态链接) 组件+时期:软件配置管理SCM与版本控制系统VCS ,为软件的不同状态分配不同的版本名和版本号,不断进行软件演化。
代码层:可执行程序的内存状态是什么样子的,程序单元(对象、函数等)如何相互作用 组件层:软件包是如何部署到物理环境(操作系统、网络、硬件等)且相互作用的 时刻层:程序在一个精确的时间的行为 时期层:它们随着时间如何进行变化
可执行程序: 程序代码转化为本地机器码加载到内存中,CPU执行时直接跳转到程序开始位置并调用对应的系统资源,字节码与机器码类似但需要进行编译。
动态链接: 不同于静态链接,它不会将文件复制进内存,而是标记出程序需要哪些库才能成功运行。动态库是通过链接目标文件构造的磁盘文件。然后将库收集到包中,并安装到目标计算机上。只有这样,它才能载入到机器的内存中。动态链接的库更新不需要修改整个可执行程序。
代码+时刻:Snapshot图重点关注内存中变量的状态变化
内存转储 Memory dump: 当进程因某种内部错误或信号而中止时,硬盘上包含进程内存内容副本的文件。
代码+时期:UML图中的序列图用于表示程序各个单元如何互相影响
执行追踪 Execution tracing:使用日志记录程序的执行信息
组件+时刻:UML图中的部署图
组件+时期:事件日志的每一类事件被分配一个唯一代码标识,并以特定格式输出可读的信息。事件日志相较于执行追踪其事件级别更加高(如程序执行失败而非抛出异常),不需要敏捷反应但应是本机信息。
代码从无到有:编写代码、静态检查 代码到组件:设计、编译、静态链接 编译到运行:安装、部署、debug、测试 时刻到时期:重构、版本控制、加载、动态链接、解释、执行
外部因素:
正确性(权力下放)健壮性(错误处理)可扩展性(信息隐藏)可复用性(模块化编程)兼容性(标准化模块、接口)高效性(可复用组件)可移植性(抽象、信息隐藏)易用性(图形化编程)功能性(可扩展性)及时性(模型、复用)此外还有可验证性、完整性、可修复性、经济性等。
内部因素:
代码层:代码行数、圈复杂度 组件层:聚度、耦合
质量目标间的权衡折中:
有些特性是冲突的,如高效性和可复用性、及时性和可扩展性,但最重要的四个目标是正确性、健壮性、可复用性、可扩展性。
从0到1:计划—>分析—>设计—>实现—>测试/集成—>扩展 从1到n:版本不断更新
两种基本类型:线性过程、迭代过程
现有模型:
瀑布过程: 线性整体推进,无迭代好管理,但无法适应需求变化
增量过程: 多个瀑布穿行,适应需求增加
V字模型: 它是瀑布模型的一个扩展,不同于瀑布模型的线性向下,其过程图呈V字,水平轴和垂直轴分别表示时间或项目完整性(从左到右)和抽象级别(最上层的粗粒度抽象)
原型过程: 在原型上持续不断的迭代(开发出来之后由用户试用/评审,发现问题反馈给开发者,开发者修改原有的实现,继续交给用户评审)发现用户变化的需求。循环往复这个过程,直到用户满意为止。时间代价高,但开发质量也高
螺旋模型: 这是一个很复杂的过程,多轮迭代基本遵循瀑布模式,每轮迭代有明确的目 标,遵循原型过程,进行严格的风险分析,方可进入下一 轮迭代
选择依据: 用户参与度(适应变化的能力) 开发效率/管理复杂度 开发软件的质量
敏捷开发:通过快速迭代和小规模的持续改进,以快速适应变化。(增量+迭代,每次迭代处理一个小规模增量)
极限的用户参与极限的小步骤迭代极限的确认/验证极限编程:一种近螺旋式的开发方法,它将复杂的开发过程分解为一个个相对比较简单的小周期;通过积极的交流、反馈以及其它一系列的方法,开发人员和客户可以非常清楚开发进度、变化、待解决的问题和潜在的困难等,并根据实际情况及时地调整开发过程。
软件配置管理:追踪和控制软件的变化 软件配置项SCI:软件中发生变化的基本单元(例如:文件) 基线:软件持续变化过程中的“稳定时刻”(例如:对外发布的版本) 配置管理数据库CMDB:存储软件的各配置项随时间发生变化的信息 +基线
版本:为软件的任一特定时刻(Moment)的形态指 派一个唯一的编号,作为“身份标识” 有关版本控制的操作:回滚/比较差异/备份历史/获取备份/合并/共享/审计 仓库:即于SCM中的CMDB 工作拷贝:在开发者本地机器上的一份项目拷贝 文件:一个独立的配置项 版本:在某个特定时间点的所有文件的共同状态 变化:即code churn,两个版本之间的差异 HEAD:程序员正在其上工作的版本
VCS:
本地版本控制系统:仓库存储于开发者本地机器无法共享和协作 集中式版本控制系统:仓库存储于独立的服务器,支持多开发者之间的协作 分布式版本控制系统:仓库存储于独立的服务器+每个开发者的本地机器
Git仓库分为三部分: 本地的CMDB 工作目录:本地文件系统 暂存区:隔离工作目录和Git仓库
ObjectGraph:版本之间的演化关系图,一条边A->B表征了“在版本B的基础上作出变化,形成了版本A”,每个commit指向一个父亲,多个commit指向同一个父亲叫做分支,一个commit指向两个父亲叫做合并;commit的本质是一个树形节点,指向具体文件存储的指针,未发生变化的文件无需重复存储。如果文件未发生变化,则后续多个版本始终指向同 一个文件;如果文件发生变化了,存储两份不同的文件,两个版本指向不同的文件
GitHub:基于网络的Git服务器并提供互联网托管服务
Design——Programming/Refactoring——Debugging——Testing——Build——Release
1.Programming
从用途划分: 编程语言/建模语言(UML)/配置语言(XML)/构建语言(XML) 从形态划分: 基于语言学的构造语言/基于数学的形式化构造语言/基于图形的可视化构造语言
集成开发环境IDE:如Eclipse,为程序员提供全面的软件开发环境
建模语言:建模语言是任何一种人工语言,可以用一组一致的规则定义的结构来表达信息、知识或系统,其目标是可视化、推理、验证和交流系统的设计
配置语言:配置文件配置程序的参数和初始设置
2.Review and static code analysis
代码评审:代码评审是对源代码的系统审查(同级评审),正式的代码审查,例如Fagan检查,涉及到一个仔细而详细的过程,有多个参与者和多个阶段
静态代码分析:静态代码分析是在不实际执行程序的情况下执行的计算机软件分析(在执行程序上执行的分析称为动态分析)
3.Dynamic code analysis / profiling
动态分析:要执行程序并观察现象、收集数据、分析不足
Profiling:对代码的运行时状态和性能进行度量,发现代码中的潜在问题
4.Debugging and Testing
测试:软件测试是为了向涉众提供被测试产品或服务的质量信息而进行的调查,测试技术包括执行程序或应用程序的过程,目的是发现软件缺陷(错误或其他缺陷),并验证软件产品适合使用。
调试:调试是找出错误的根本原因并加以改正的过程,它与测试相反,测试是一开始就检测错误的过程,调试是成功测试的结果。与测试一样,调试不是一种提高软件质量的方法,但它是一种诊断缺陷的方法
5.Refactoring
重构:重构是改变软件系统的过程,它既不改变代码的外部行为,又改进了其内部结构
Validate——Compile——Link——Test——Package——Install——Deploy
Build:build-time ->run-time 借助于工具,将软件构造各阶段的活动“自动化” (编译、打包、静态分析、测试、生成文档、部署…) 尽可能脱离“手工作业”,提高构造效率
使用build的典型场景:
用传统编译语言编写的软件的编译用解释语言编写的软件的包装和测试基于web的应用程序的编译和打包编译语言:源文件被编译成目标文件,然后将目标文件链接到代码库或可执行程序中,产生的文件被收集到一个可以安装在目标机器上的发布包中
解释语言:解释后的源代码不会编译成目标代码,因此不需要对象树。源文件本身被收集到一个发布包中,准备安装到目标计算机上
web应用程序:基于web的应用程序的构建系统是编译代码、解释代码和配置或数据文件的混合
构建系统的部件:版本控制工具/源树/对象树/编译工具/发布包和目标机器
build过程:build工具调用每个编译工具来完成任务,这是一个端到端的事件序列
build语言:build工具需要以基于文本的格式编写构建描述,例如,在使用Make时,文件间依赖信息以规则的形式指定,这些规则存储在名为Makefile的文件中,可以手写也可以用IDE生成
build工具: Make, Ant, Maven, Gradle, Eclipse