2023-HIT-软件构造4 软件构造知识点归纳(3)

目录

第3讲 软件构造过程和配置管理

*3.1 软件开发模型

3.2 软件配置管理与版本控制系统

3.2.1 SCM和VCS

3.2.2 SCM工具的代表:Git

*3.3 软件构造的总体过程

*3.4 软件的构建过程

第4讲 数据类型和类型检验

4.1 数据类型

4.2 静态类型检查与动态类型检查

4.3 类型的可变性

4.3.1 可变类型和不可变类型

4.3.2 容器和数组

4.3.3 不可变包装器

4.4 快照图


第3讲 软件构造过程和配置管理

*3.1 软件开发模型

不在考试范围内。

3.2 软件配置管理与版本控制系统

3.2.1 SCM和VCS

软件配置管理(SCM)的目标是追踪和控制软件的变化,SCM中发生变化的基本单元称为软件配置项(SCI),在Git中,SCI指的是文件。将各个文件的特定版本串联起来,即软件持续变化过程中的“稳定时刻”,称为基线(例如:对外发布的版本),如下图所示:

配置管理数据库(CMDB)存储软件的各配置项随时间发生变化的信息和基线。版本是软件的任一特定时刻的形态的唯一的编号,作为“身份标识”。

版本控制系统(VCS)可以用于控制软件版本,具有回滚版本、比较差异、备份软件版本历史、获取备份、合并等多种功能。VCS的分类如下:

  • 本地版本控制系统:仓库存储于开发者本地机器,无法共享和协作;
  • 集中式版本控制系统:仓库存储于独立的服务器,支持多开发者之间的协作;
  • 分布式版本控制系统:仓库存储于独立的服务器和每个开发者的本地机器上。

VCS中的术语如下:

  • 仓库:在SCM中的CMDB(配置管理数据库);
  • 工作拷贝:在开发者机器上的项目拷贝;
  • 文件:一个独立的SCI;
  • 版本:在某个特定时间点的所有文件的共同状态;
  • 变化(Code Churn):两个版本之间的差异;
  • HEAD :程序员正在其上工作的版本。

3.2.2 SCM工具的代表:Git

每个Git仓库由以下三部分构成:

  • .git 文件夹:本地的CMDB;
  • 工作目录:本地文件系统;
  • 暂存区:隔离工作目录和Git仓库。

每个文件属于三个状态之一:已修改已暂存已提交。Git仓库的常用命令如下:

对象图是版本之间的演化关系图,一条边A->B 表征了“在版本B的基础上作出变化,形成了版本A。对象图存储了项目中文件的所有版本,以及描述这些更改的所有日志条目。在Git中,对象图保存在.git文件夹内,克隆一个仓库也就是克隆了完整的对象图。下面是对象图的两种表示:

 ​​​​​

在对象图中,较新的版本指向较旧的的版本。如果存在多个节点指向一个节点,则发生了分支,如果存在一个节点指向多个节点,则发生了合并。 

Git中的每个Commit以树形结构存储,存储了文件目录结构、指向具体文件的指针和提交信息。通过这种方式,可以避免存储相同的文件。

在传统的VCS中,存储版本之间的行变化,而Git存储变化的文件

分支可以沿两个方向并行进行修改,可以进行以下操作:

  • git checkout [Name]: 切换到指定分支;
  • git checkout -b [Name]: 以当前分支为起点,创建一个新的分支;
  • git merge [Name]: 将指定分支合并到当前分支。

*3.3 软件构造的总体过程

不在考试范围内。

*3.4 软件的构建过程

不在考试范围内。

第4讲 数据类型和类型检验

4.1 数据类型

数据类型是一组值,以及可以对这些值执行的操作。用特定数据类型定义,可存储满足类型约束的值称为变量。

在Java中,数据类型可分为基本数据类型对象数据类型。两者比较如下:

基本类型对象类型
包含int, double, float, char, boolean, byte, short, long其他所有类型(包含数组)
ID
可变性不可变可变或不可变
内存分配
代价

所有的对象类型都继承或者间接继承自Object类。

基本类型有其对应的包装类型,如int -> Integer等,一般在定义集合类型时使用,其他情况下避免使用。这两种类型一般可以进行自动转换。

操作符是执行简单计算的符号,操作是接受输入并产生输出的函数(有时还会更改值本身)。

4.2 静态类型检查与动态类型检查

语言可分为静态类型语言动态类型语言,每个语言可以提供静态类型检查、动态类型检查或者无检查,从发现bug的角度讲,静态类型检查>>动态类型检查>>无检查

静态类型检查可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正确性、健壮性。静态类型检查可以发现以下错误:

  • 语法错误:大多数语言,包括Python都可以进行这类检查;
  • 类名、函数名错误:例如Math.sine(2);
  • 参数数目、类型错误:检查函数的参数信息;
  • 返回值类型错误:检查返回的值是否和声明的相同。

动态类型检查可以在运行时发现错误,例如:

  • 非法的参数值:例如x/y,其中y==0,在运行时发现错误并抛出异常;
  • 非法的返回值:特定的返回值不能在给定的类型中表示;
  • 越界:例如负值数组下标和过大的数组下标;
  • 空指针:例如在空的指针上调用函数。

静态检查是关于“类型”的检查,不考虑值;而动态检查是关于“值”的检查。

4.3 类型的可变性

改变一个变量是指改变一个指针,而改变变量的值则是改变指针指向的内容。为了安全性,需要尽量减少变化。

4.3.1 可变类型和不可变类型

不可变类型是指一旦创建,其值不能改变的类型。

对于引用类型,可以使用final关键字修饰,使这个指针不能变化。试图改变final的引用会导致边缘错误,这也是静态类型检查的一部分。final关键字的其他的用法如下:

  • final修饰的方法不可以被重写;
  • final修饰的类不可以被继承。

可变与不可变类型在多个引用指向同一个值会产生区别。

可变类型拥有方法可以修改自己的值或引用。不同于不可变类型,可变类型不需要产生大量的拷贝,效率较高。此外,可变类型还可以用于在多个模块之间共享数据。

不可变类型更加安全,在其他的质量指标上表现更好,因此需要折中。

注意:不要使用Date类型,因为它是一个可变的类型,使用可能导致难以调试的bug。

为了防止发生意外的问题,可以在返回可变类型时进行防御式拷贝,但可能导致内存浪费,不可变类型没有这种问题。因此,可变类型应尽量只在局部安全使用。

4.3.2 容器和数组

数组是固定长度的类型序列,List<T>是一个接口,用于表示变长类型序列。一般情况下,应尽量使用List<T>,避免使用数组。容器中只能放入引用类型。

Set<T>是代表一个无序集合的接口,Map<K, V>代表一个从K到V的映射。

迭代器是一个遍历元素集合并逐个返回元素的对象,是一个可变类型。在使用范围for语句时,会隐式使用迭代器。

在使用迭代器或者范围for时,不要改变目标类型的值,可能会对迭代器造成破坏。

4.3.3 不可变包装器

工具类Collections提供了一组方法,用于将给定的集合转换为一个不可修改的集合,如Collections.unmodifiableList、Collections.unmodifiableSet、Collections.unmodifiableMap等。

但是这样得到的结果的不可变性只能是运行时检查的,即试图修改时抛出异常,编译器无法进行静态检查。

List.of(T t1, ...)等提供一个不可修改的集合。要创建浅拷贝的集合,使用List.copyOf()等,但是这个方法需要Java 10+。

4.4 快照图

快照图用于用于描述程序运行时的内部状态,便于程序员之间的交流、刻画各类变量随时间变化、解释设计思路。

1. 基本类型的值:

2. 对象类型的值:

3. 不可变类型:使用双线椭圆 

 4. 不可变的引用:使用双线箭头

5. 修改可变对象的值:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值