当前课程知识点:软件理论与工程 >  第6章 项目管理 >  6.4 项目版本控制及调试 >  6.4 项目版本控制及调试

返回《软件理论与工程》慕课在线视频课程列表

6.4 项目版本控制及调试在线视频

返回《软件理论与工程》慕课在线视频列表

6.4 项目版本控制及调试课程教案、知识点、字幕

大家好

我们今天继续软件理论与工程

第六章 第四节 项目版本控制及调试

我是主讲人 高广宇

我们上一节课的时候

其实也提到了版本控制的内容

我们今天主要给详细的介绍一下版本控制

以及软件调试相关的内容

首先 什么是版本控制

版本控制的英文叫VSC

全称叫Version Control Systems

什么是版本控制

版本控制

它实际上是完整的记录一个文件集合

当然文件可以指代是代码

也可以指代是各种各样

我们前期的软件工程的文档

它整个随着时间变化

它的一个变化过程

这就是版本控制

所以说 早期的版本控制

是通过什么样的方式

通常是通过各种各样文件命名的方式

来实现的

为什么我们又需要版本控制

从图示上

我相信大家感同身受

因为我们在很多时候

当我们要完成文档

完成代码的时候

我们在不断的修改的过程中

就是随着时间前面提到的

我们是通过不断的去更改命名的方式

去对它进行修改

但是大家会发现一个问题

就是说有的时候

我们已经命名到final了

发现 好像我们又得修改

时候又变成final final

但时候发现

永无止境

没有任何一个规范可言

甚至到了最后

你自己连哪个是最新的

都已经搞不清楚了

所以在这种情况下

实际上 我们如果有版本控制

我们实际上就能够有效地解决问题

就能很规范化的管理起来

我们的代码和文档

所以说 我们为什么要使用版本控制

第一个是 我们容易去回溯

我们前期的文档

或者程序的版本

第二个是比较适合

大家去做共同协作开发

还有我们能够去回溯

或者说 寻找到整个软件或者文档

它的一个变化的一个过程

也适合去做一个备份

或者说一个文件的一个恢复

所以 这是版本控制的特点或者优势

图是我们的GitHub上的

一个版本控制的图示

有些同学经常用GitHub

当然就知道它的优势或者特点

知道它干嘛的

到底谁需要版本控制

或者谁在用版本控制

实际上 在整个软件工程过程中

所涉及到的所有人员

都可能需要用到版本控制

比如说程序员

它需要通过版本控制

来管理整个项目或者系统

包括所有的文档和程序

使用者

application 应用

也需要版本控制

包括咱们普通用户

我们平时在撰写Word

或者说PPT Excel表格的时候

我们都希望有一个版本控制

能够来保持它的一个更改变化的追溯

当然还包括管理人员

所以 实际上版本控制

它的应用范围非常广泛

它的使用者也非常的多

版本控制的话

通常包含两大类

一类就是集中式的版本控制

对于这类版本控制而言

它通常是有一个单一的叫central

一个中心的节点

然后来存储所有的资源

然后 每一个开发者

它拥有一个自己的local working copies

就有一个局部的工作

拷贝一个备份

它在它的上面去更改

但是是从central

集中式的节点

所复制和down下来的

对于这种集中式的控制来说

它的图示 如PPT所示

比较典型的集中式的版本控制的

系统或者工具

有包括像CVS和SVN

尤其是SVN

原来实用的是非常广泛

它们控制的一个工具或者一个软件

集中式的版本控制

它的一个工作流程

这里面有一个例子

我们首先看一下

比如说 我现在要作为一个普通的用户

我要去修改我的一个

比如说一个工程

我怎么做

我首先update

我的一个拷贝

简单来说就是

我首先从集中式的服务器上down下来

或者去更新一下最新的一个版本

然后 我在上面去做编辑

做修改

修改完了之后

我再去update一下

服务器上的版本

当然时候

因为别的人可能也在同时进行修改甚至上传

所以 有可能出现就是

原来修改的个版本

跟你最近down版本之间有不一致

所以时候

如果有必要的话

需要把改变去进行合并

合并完了之后

你确定完了最后的一个版本

然后 你把它去做一个commit

做一个提交

因为可能就是说你的修改

跟你最后一次从服务器上down下的版本的修改

合并到一起

你提交到服务器

服务器当然还需要去处理冲突或者并发

因为其他的合作者

可能同样在做修改和提交

所以 他也需要去做

所以修改了合并

对于这种集中式的版本控制

它其实有一些问题

比如它的一些问题包括

第一个就是

如果我没有网络环境怎么办

因为它需要不断地去从个服务器上

update最新的version

最新的一个版本

如果没有网络怎么办

还有一个如果我要提交的

是一个非常大的一个更改 一个变动

我需要不断地跟个服务器

去update

去download 去commit

其实这个时候依赖于整个网络带宽

网络的环境影响也会很大

还有一个就是说

如果我想去知道整个项目或者工程

它的一个变化的一个历史记录

怎么办

实际上在集中式版本控制里面

只有中心服务器节点是知道的

对于普通的一个developer

每个开发者来说其实是

没有完整的历史信息的

所以整个集中式的版本控制

尤其在面向大规模软件开发的时候

是面临诸多的问题的

因此 就衍生出来

所谓的distributed分布式的版本控制

当然集中式和分布式

在整个计算机领域里面

是一个经常成对出现的两个词

分布式大家也很容易理解

自然而然就是说它不像集中式一样

有一个单一的服务器的集中节点

而是 大家分布的共同来承担

几乎相当的责任

共同来维护一个核心

所以说 在分布式的版本控制里面的话

每一个开发者自己的本地机器上

都维护了一个完整的工程的一个copy

也就是说

我的所有的更改的日志

都是在这有记录的

然后 在没有网络的环境下

我也可以去跟我本地的这个仓库

去进行一些交互

然后 来完成我相应的工作

这就是所谓的分布式的概念

也就是分散在各自的节点上

每一个节点之间

基本上可以理解为是公平的 平等的

当然 它也有一个简单的

轻量级的master节点

来共同协调不同的节点

不同的局部节点之间的交互

在这个时候

它要进行一个任务交互的时候

它的方式就是首先

我从master节点上

先去down下来一个最新的仓库

然后 我更新我自己的版本

我编辑它

然后我再提交它

同样 如果有必要的话

我再去跟我master节点

也就是跟所有的网络上其它节点去交互

去进行一个更新

在没有网络的情况下

我也可以跟自己的本地仓库

去进行版本的更改 控制或更新等等

对于集中式的版本控制和分布式的版本控制

其实各有优缺点

也谈不上说 谁绝对好 谁绝对的不好

通常是依赖于我们实际的

一个开发的任务

有的时候

可能集中式的开发构成 效率很高

然后 能够有效地去完成任务

因为有的时候应用分布式的这种方式

它也有问题

因为它需要去在每个机器上都留一个存储

一个备份

整个系统还是比较庞大的

对于中小软件和中小系统的开发来说

有的时候不见得是必然的

所以说

像集中式的版本控制

现在其实还是有很大的用武之地的

这个需要去理解分布式的版本控制

包括因为大家知道分布式版本控制里

比较经典的就是像Git

像包括有名的 像GitHub等等

好像是非常广泛

但是并不见得它是绝对的好

大家需要去理解

除了版本控制之外

我们接下来再讲一下软件调试

软件调试的话

我们首先 稍微区分几个概念

软件调试需要跟验证Validation要区分一下

Validation 是去发现问题

同时 去增加可行性

而Debugging是要去找出来问题

同时要把问题给解决掉

而Debugging还跟一个概念特别容易混淆

就是测试 Testing

测试是要去找出问题

但是 它并不关注于问题的解决

Debugging不一样

Debugging是要找出了问题

而且要精准到问题的一个位置

同时 要去找出来导致问题的原因

而且我们还要想办法去解决它

这是Debugging要做的事

而且Debugging在很多时候

在程序员或者说在开发人员角度去考虑

像Testing 通常是在设计人的角度考虑的比较多

那Debugging

它是要去找Bug

Bug实际上这是个英文词了

它为什么叫Bug

有一个渊源

大概在上个世纪40年代的

那个时候的计算机是电子计算机

它体系非常的庞大

它也是需要通过电子元器件的机械

或者电子的运算

才能去得到最终的数据的计算

然后 它所有的这些程序代码

数据的输入输出

也是需要通过指代

通过其它的东西去输入

它中间日志过程也不像现在

它不会自动去输出

需要人为去记录

在上个世纪40年代

有一个工程师叫Grace

他在记录日志的过程中发现

计算机发生了一次故障

然后 当他在寻找问题的时候发现

导致计算机故障的原因

是某一个电子元器件的位置

有一个bug

bug的英文叫虫子

有一个小虫子导致电路短路了

所以没法去运行

所以 当他手工描述日志记录文档的时候

他就把小虫子贴到了上面

同时详细地描述了问题

因此 我们就对计算机运行过程中

导致它发生错误的东西叫什么

叫bug

当然这只是一个说法

并不是绝对的是这么个意思

大家有这么一个传统 就这么去描述

Debugging实际上就是说去找

使得整个程序发生问题的一个位置以及原因

就是bug

对于一个bug来说

它是怎么样产生的

它通常

最开始是来自于人

也就是说程序员写代码的时候的错误

才留下了一些隐患

同时 因为这些隐患

导致我们整个计算过程中就发生错误

这些计算的错误

使得最后我们程序的功能实现

就会出现问题

使得它最后呈现出来的结果

就发生了一些不一致

或者发生了错误

所以 我们整个Debugging

是在我们找到或者发现了

这种可看见的错误

或者不一致了之后才开始的

我们这个是要反过去找

到底在哪个位置

发生了什么问题

所以说 我们怎么样去做Debugging

或者怎么样去防止

这些错误的发生

通常来说

其实除了Debugging之外

Debugging其实是最后一道关卡

我们为了防止错误的发生

也有其它的方式

比如说我们使得错误

在最开始的时候

就不可能被发生

比如说通过语言机制

我们都知道Java语言

就自己的内存管理机制

它能够防止内存泄露

第二个是说

我们尽量地去确保这些错误

在第一次出现的时候就被发现

不让它在后面发生

第三个来说

因为错误 你不能让它被隐藏

你必须让它在第一时间 可见

就尽快地呈现出来

这样才能在最开始的时候

我们去解决它

当然我们最后一道关卡就是Debugging

如果它真的发生了

这个时候再回过去去找它

到底在哪

对于整个Debugging来说

我们也有各种各样的方式

刚才前面也提到了

比如说 我们这里面有一个例子

我们这是一个简单的语句

我们一个while循环

我们去判断一下

对于一个数组中到底有没有k的元素

这里面是说

int i等于0

while true就循环

我们用了一个永真的条件

然后去判断

如果说a[i] i++

不断去迭代

如果有一个a[i]==k

我就认为我找到了 我就break

这个 程序简单看起来没有什么问题

没有什么错误的

本身也没什么错误

你去Debugging

你去调试什么应该也是能过得去的

但是 这个程序

实际上是隐藏了一个bug的

为什么这么说

大家看到

因为 现在是一个永真的判别条件

循环的退出完全依靠if语句

所以 如果if语句不成立的情况

永远不成立的情况下

这个循环就变成一个死循环了

而且永远在这就出不去了

而且 虽然你认为就是说

写程序的时候认为我们的应用场景

它可能是应该会有

k应该是能出去的

但是 当我们换了一个应用场景的时候

你不能够一直确保条件是存在了

所以 像这个就是隐藏的bug

但实际上在最早期的时候

其实是不太容易被发现

也没法通过语言机制去发现

怎么办

实际上我们可以做一些小的调整

比如说

我刚才发现

它是因为循环退不出去的这种问题

我们加一个简单的判别条件

如果i小于数组的长度的时候

我们就可以去执行循环

如果它超过长度了

我人为的 让它去退出

其实也是没有问题

至少能够确保它避免死循环问题

但实际上

对于这个代码来说

它还会有问题

大家可以自己想一下

看一下是什么问题

实际上 我们能够发现

我们现在 如果循环退出了

前面 用永真的方式的时候

我们知道循环退出是因为break出来的

现在整个循环出去了

有两个出口

一个是break

一个是i大于等于a.length

所以 当循环退出的时候

就不确定是通过哪个出口出来的

如果我后续的代码

又依赖于前面的两个条件里面

我要确定是因为哪个条件

在这种情况下

这个代码就有可能有问题

就是有可能数组里

没有k元素

但是也退出来了

所以在这种情况下

这个代码其实也是有一定的问题

有这个bug

实际上

我们从Debugging角度上来说

我们可以加入一些assert

也就是 中文叫断言

循环退出了之后

加一个断言去判断

它到底是通过哪个条件出来的

或者说通过哪个条件出来之后

我是不要对程序做一个中断

就比如说如果没有k值

后面的操作就没有意义了

就中断它了 不执行它了

所以 这个是关于我们在Debugging过程中

比如说通过刚才说的这种不同的

去更改程序的一个编写方式

或者加入断言

加入其它工具的操作过程

然后 能够有效地去避免问题

到底我们在什么时候

可能我们需要去 像加入断言

或者去做这么一个事

实际上 这个东西也不是尽然的

跟实际的场景有关系

有的时候 我需要加这么一个断言

因为如果它不满足的条件就直接退出

因为后面有的程序

可能严格依赖于这个条件

有的时候可能就是说

这个bug或者这个断言

对于整个程序来说

它的整个系统来说

它的影响不大

我后面的程序对它依赖性很小

但在这种情况下

其实我不用加断言

就让它从哪个出口出去都无所谓

所以 对于这种纠正

或者对于这种debug的纠正

其实 它是依赖于一个上下文的一个环境的

在这里最后

再给大家讲一个就是

这个Debugging的一个好处

或者说它到底会有什么问题

其实一个最典型的问题就是说

它的灾难性的后果

比如说在欧洲的Ariane-5

这个火箭发射的过程

当时 就是因为一个小小的bug所导致的

它当时是因为

它把Ariane-4的这一个程序

直接挪到了Ariane-5上来用

但是 它忽略了整个Ariane-5上用的处理器变了

它的一个字段的长度发生了变化

所以 发生了溢出

像这种问题的话

如果通过编译或者说检查代码

是检查不出来的

我们就需要去通过什么

通过Debugging的方式

认真地去在中间

加入像断言

或者其它的判断

或者操作的方式

去避免这样的问题的发生

这个就是一个Ariane-5的火箭的示意图

这就是刚才提到的灾难性的一个后果

我们这一节 包括我们这一章

就讲到这里

好 谢谢大家

软件理论与工程课程列表:

课程概述

-课程概述

第1章 软件与软件工程

-1.1 软件的本质

--1.1 软件的本质

-1.2 软件工程

--1.2 软件工程

-1.3 软件过程结构

--1.3 软件过程结构

-1.4 过程模型

--1.4 过程模型

-1.5 敏捷开发方法

--1.5 敏捷开发方法

-第1章 习题

--第1章 习题

第2章 需求分析

-2.1 需求工程过程

--2.1 需求工程过程

-2.2 需求获取

--2.2 需求获取

-2.3 需求分析

--2.3 需求分析

-2.4 过程建模

--2.4 过程建模

-2.5 面向对象建模

--2.5 面向对象建模

-第2章 习题

--第2章 习题

第3章 软件设计

-3.1 设计概述

--3.1 设计概述

-3.2 设计的概念

--3.2 设计的概念

-3.3 设计模型元素

--3.3 设计模型元素

-3.4 体系结构概述

--3.4 体系结构概述

-3.5 体系结构风格

--3.5 体系结构风格

-3.6 构件级设计

--3.6 构件级设计

-3.7 UI设计

--3.7 UI设计

-3.8 基于模式的设计

--3.8 基于模式的设计

-第3章 习题

--第3章 习题

第4章 UML方法

-4.1 UML概述

--4.1 UML概述

-4.2 UML 及UML中的事物

--4.2 UML 及UML中的事物

-4.3 UML关系和图

--4.3 UML关系和图

-4.4 UML 图细节(上)

--4.4 UML 图细节(上)

-4.4 UML 图细节(下)

--4.4 UML 图细节(下)

-第4章 习题

--第4章 习题

第5章 软件测试

-5.1 软件测试策略

--5.1 软件测试策略(上)

--5.1 软件测试策略(下)

-5.2 测试传统的应用系统

--5.2 测试传统的应用系统

-5.3 测试面向对象的应用系统

--5.3 测试面向对象的应用系统

-5.4 测试web应用系统

--5.4 测试web应用系统

-5.5 测试移动应用系统

--5.5 测试移动应用系统

-第5章 习题

--第5章 习题

第6章 项目管理

-6.1 软件项目估算

--6.1 软件项目估算

-6.2 软件过程管理

--6.2 软件过程管理

-6.3 软件配置管理

--6.3 软件配置管理

-6.4 项目版本控制及调试

--6.4 项目版本控制及调试

-第6章 习题

--第6章 习题

6.4 项目版本控制及调试笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。