软件工程:小组开发过程技术(VS VSS UNIX C++)

(注:这个东西是2007年写的,算是个缅怀,或是个吐槽。所有注都是本次发布新加的。)

简介

本文讲述完全没有软件工程经验的软件小组如何借助VS VSS等工具为UNIX开发C++程序,实现在小组规模的初级开发过程。这不是TSPi或者CMM,这比CMM1级(初始级)还要低,可称之为CMM0。

目录

[1 概述](#1 概述)

[2 责任和责任感](#2 责任和责任感)

[3 概念](#3 概念)

[3.1 配置和配置项](#3.1 配置和配置项)

[3.2 软件配置管理](#3.2 软件配置管理)

[3.3 基线](#3.3 基线)

[4 开发过程](#4 开发过程)

[5 松散开发的问题](#5 松散开发的问题)

[6 测试和发布](#6 测试和发布)

[7 基本开发结构](#7 基本开发结构)

[7.1 结构图](#7.1 结构图)

[7.2 服务器](#7.2 服务器)

[7.3 开发者环境](#7.3 开发者环境)

[8 技术细节](#8 技术细节)

[8.1 版本控制VSS](#8.1 版本控制VSS)

[8.2 开发工具VS(visual studio)](#8.2 开发工具VS(visual studio))

[8.3 数据库工具TOAD](#8.3 数据库工具TOAD)

[8.4 数据库结构检查](#8.4 数据库结构检查)

[8.5 UNIX SHELL 脚本](#8.5 UNIX SHELL 脚本)

[8.6 维持单一版本](#8.6 维持单一版本)

[8.7 避免绝对依赖关系](#8.7 避免绝对依赖关系)

[8.8 记录变更历史](#8.8 记录变更历史)

[8.9 自动版本升级](#8.9 自动版本升级)

[8.10 版本标识和检测](#8.10 版本标识和检测)


1 概述

CMM对于内地大多数软件公司来说,仅仅是老板用红包(当然少不了吃饭和旅游)兑换的一块牌子,而项目负责人和程序员仍然在无序开发的泥沼中挣扎、应付永远做不完的需求和BUG。

我听过很多的言论,表达"软件文档是毫无意义的"这样的观点。我相信大多数程序员都对此心有戚戚焉,我个人的经验也同样在部分层面支持这个观点。

软件工程错了吗?

是的,软件工程错了,如果你只是想得到软件的好处。

软件工程是一套标准和方法,标准和方法本身并不能带来任何利益,每个标准和方法都有适用的基础条件和成本付出,只有正确地实施才会获得好处。

很多程序员都喜欢玩CS,有两款典型自动步枪(不能区分冲锋枪和自动步枪的请保持沉默),AK47(AK74)和M4(M16),这两种步枪孰优孰劣?简单地说,M4(M16)是高精尖武器(仅其塑料材质就可以吓退大多数仿制者),低后坐力、高精度,昂贵、复杂、精密、易损坏,只能由受过专业训练的士兵使用,并且需要后勤支持(看到美军在伊拉克把安全套套在枪口上以避免沙子进入导致卡壳吗?),AK47(AK74)则是简单武器,精度很差,廉价、耐用、无需维护,风沙海水都不怕,最适合沙漠、山区的恐怖分子使用。对恐怖分子而言,M16是毫无用处的塑料垃圾。

好了,恐怖分子们,拿起AK,准备战斗。

2 责任和责任感

每个人都有责任就是每个人都没有责任。

管理者是承担管理责任的人,小组负责人是管理者,带徒弟的师傅也是管理者。

甚至于,每个人都要管理自己的程序、文档、mp3和游戏,每个人都是管理者。当然,我们不会把希望寄托在每个人身上,因为------每个人都有责任就是每个人都没有责任。

任何把希望寄托在人的自觉性上的人都不能成为合格的管理者。

作为小组负责人,必须对全组负责。作为从零起步的开发小组,项目能否顺利进行完全取决于小组负责人的能力。

下面列出对小组负责人的要求,其中有些要求对个人能力是一个巨大的考验。

要掌握每个成员的技术能力,正确地分配任务。要能够估计成员完成任务的所需的时间。

要了解完成任务所需的技术,知道从何处取得相关技术的资料。高级管理者并不需要成为每项技术的专家,越是低级管理者则越是要精通技术。

要在心里正确估计进度,正确地估计代码质量。要估计测试和返工所需的时间。

要把握总体设计,检查任何影响其它模块、其他人的设计和变更。

要查看所有人的代码,要求代码风格尽量符合小组负责人的习惯。

要有安全意识,主动发现并预防可能发生的意外事件。

要了解下面章节所提到的概念和技术。

3 概念

3.1 配置和配置项

"配置"是在技术文档中明确说明并最终组成软件产品的功能或物理属性。因此"配置"包括了即将受控的所有产品特性,其内容及相关文档,软件版本,变更文档,软件运行的支持数据,以及其他一切保证软件一致性的组成要素,相对与硬件类配置,软件产品的"配置"包括更多的内容并具有易变性。

受控软件经常被划分为各类配置项(Configuraion items, CIs),这类划分是进行软件配置管理的基础和前提,CIs是逻辑上组成软件系统的各组成部分。比如一个软件产品包括几个程序模块,每个程序模块及其相关文档和支撑数据可能被命名为一个CI。一个系统包括的CIs的数目是一个与设计密切相关的问题。一个纯软件的CI通常也称之为软件配置项(CSCI)。

现在所有的配置管理工具均提供对配置项的管理工具,包括(Check in和Check out机制的 )版本管理和版本标号功能。由于版本和标号管理比较繁琐,一般推荐使用配置管理工具,减少事务性工作。

3.2 软件配置管理

软件配置管理是贯穿于整个软件过程中的保护性活动,它被设计来(1)标识变化,(2)控制变化,(3)保证变化被适当的发现,以及(4)向其他可能有兴趣的人员报告变化。

3.3 基线

基线(baseline)是配置项的稳定版本,是进一步开发的基础。一般一条基线包含一组配置项,在所有包含的配置项确认通过后(测试或评审通过)基线形成,基线一般采用更高级别的变更保护。

基线概念反过来解释就是一项工作所依赖的所有配置项。比如,一个新模块的开发依赖公共组件并需要与特定模块交互,那么新模块所依赖的基线至少要包括公共组件的特定版本、与特定模块交互的接口协议的特定版本(或者特定模块的特定版本)。

一般开发过程中我们通过打标签的方式标识基线,并尽量避免复杂的的基线划分。

4 开发过程

基本的开发过程分为设计、开发、测试、发布。发布是把软件和文档打包提供给客户的过程,该过程较简单,技术性不强,不多讨论。设计是难度最高的过程,通常只是在头脑里模拟完成,不会有成文的输出(我们偷懒省去了设计过程,至于更无法掌握的需求根本不必提及)。剩下的开发和测试是实际看得到的环节,通常我们制定项目计划只考虑开发和测试。

更现实一点说,多数的项目开发过程的开发和测试是混在一起的,开发人员在开发时自行测试自己的程序,没有独立的测试过程。

作为项目开发过程化的第一步,要形成版本概念(与基线概念相关)。版本是妥善保存的,成为追溯的依据。经常发生这样的情况:新版本测试发现问题,需要用旧版本检查以确定问题是新版产生还是旧版原有的,然后需要对比版本以寻找问题所在。

项目过程化的第二步,是要有独立的测试过程。独立的测试过程不一定要求专职的测试人员,开发人员可以互相测试。一定要在版本上测试,不能边改边测。发布的版本必须是测试通过的完整版本,不能是发现错误修改后只测试了出错点的版本(BUG修改经常在其他地方产生意想不到的错误)。

以上两步是最基本的,是小组范围内能够自行掌握的。形成版本使过程控制成为可能,独立测试则显著提高产品质量。

版本化原则上并不需要任何额外工具,在有版本控制工具以前可以做手工的存档。版本控制工具可以提供较好的版本管理,但不能偷懒把发布版本放在开发库里(尽管发布版本总是对应一个开发版,但管理上要求发布版本与开发版本脱离)。版本控制工具可以提供较好的过程管理,能够明确产品包含的有效源代码、文档,能够控制同一个文件的修改冲突,能够检查项目、文件所发生的变化,给小组负责人控制项目提供有力的支持。

独立的测试过程给软件质量提供一个可信赖的过程保障,开发者自测的局限性非常大(这是心理学原因,不是靠工作态度可以解决),通常交换测试就可以发现大量简单错误。在有独立测试部门的情况下,一般开发组提交给测试组的代码已经是经过开发组内部测试的版本(否则BUG太多面子上不好受并且会影响奖金)。

5 松散开发的问题

松散系统是由大量非紧密相关的部分组成的系统,各模块在大多数时候可以互不干扰地独立开发,但少数情况下需要修改公共部分。

由于多数情况下各自开发不需要交互,长时间以后导致每个人对公共基础(一般主要是数据库)的掌握不足。每个开发者都可能根据自己的需要增加了一些表,不同的开发者可能重复开发了相似的功能,不同的开发者可能对同一个数据做出了不同的假定。

在维护期对生产系统的BUG修复或特殊需求经常直接在生产系统上进行,因为问题经常与特定的环境和数据有关,很显然在生产系统上直接修改、测试是最快速的、最方便的方式。这种现象导致不兼容的特殊版本,对后续维护造成致命的障碍。管理者应该意识到这个问题。

松散开发和维护方式实际上不是一种开发模式,而是一种混乱。

在Windows环境下开发时很少所有人共享同一个数据库和同一套代码,然而在UNIX上却相当普遍。究其原因可能是因为UNIX上多数都是大系统,为每个人构建一套开发环境可能资源不允许,开发时经常麻烦管理员也不是很方便。

短期内解决这个问题所投入的成本与带来的长远好处相比是否值得?从现实看多数人的答案是"否"。

解决的办法有没有?当然有。但的确不是很省力的,一方面需要掌握多方面的技术,另一方面要投入人力资源进行控制。技术面和技术深度对内地从业者来说都是薄弱环节。若要加强控制就必须存在一个人对所有变更进行审查,确保所有变更都被统一记录以便其他人能够知晓。小组负责人应该亲自进行控制,小组负责人是唯一可能同时具有足够技术、权力、职责和责任心的人。

本文所提及的技术细节都是在数年里逐渐解决的,解决之前觉得很麻烦,解决之后觉得不过如此(技术问题从来如此)。多数技术要求对管理都有很大的作用,是因为有管理需要才引入这些技术。

应付同一个模块每天三次的紧急修改需求是不可能的,如果这样的事情发生,我们只能说质量已经失控。

对于突发的故障的维护,可以采用紧急处理策略,直接生成一个特殊版本解决问题(毕竟生产系统的故障必须尽快解决),然后再将特殊版本的修改并入正式版本。在生产系统直接修改不并入正式版本会导致最后产品不可维护,这是要通过制度才能解决的问题。

6 测试和发布

软件发布的版本必须是测试过的版本,中间不能有开发人员介入。作为管理者,不能信赖过程上不可靠的东西。

软件发布应尽量完整发布,不得不频繁发布小模块的时候必须谨慎小心,避免差错。

必须严格按照测试通过的顺序发布,必须严格按照发布顺序实施更新。

小模块发布时小组负责人必须仔细检查变更细节以确保不会产生模块冲突。

若与其他小组有关联则必须联合发布并且在代码中检查其它小组的模块的版本。

每个小模块的开发者无权发布模块。发布必须经过小组负责人的认可。

公共模块的修改必须在小组主要开发人员认可后进行,不可随意修改。

7 基本开发结构

(注:由于年代关系,后续提及的软件可能已经过时,用同等功能的替代即可)

7.1 结构图

7.2 服务器

服务器是核心。这个服务器不是开发用的主机,是用来共享资源和版本管理的服务器。

共享资源包括开发用的各种软件的副本、各种技术资料以及其他对团队有意义的东西。

版本管理一般都采用VSS,需要把VSS数据库目录放在服务器上共享。使用CVS可能无法顺利完成所有需要的工作。

需要一再强调的就是,只有入库的东西才被承认。声称代码写完了但是忘了入库的人一律扣发当月奖金并全组通报批评。

7.3 开发者环境

每个开发者拥有自己的开发环境,以避免开发干扰,因此需要在UNIX主机和数据库建立独立的用户。如果不能做到,至少保证两个用户,一个用来开发一个用来测试。

推荐开发者使用VS或其他集成开发环境。集成开发环境提供的辅助功能会极大地提高开发速度和代码质量。

可以统一使用VS作为开发环境,配合FTP工具上传。如果全部统一用VS则还可以使用VS直接访问VSS。用VS直接访问VSS与手工访问VSS相比较少犯VSS操作错误。

每个开发者使用独立的开发环境有助于使开发者明确认识到完成的代码必须入库。独立的测试环境也有助于开发者养成详细记录数据库变更的习惯。

8 技术细节

8.1 版本控制VSS

版本控制通常使用VSS或者CVS。使用版本控制的目的在于限制代码的随意修改、追溯代码的修改过程。就概念而言,VSS更符合版本控制概念,使用者能够形成正确的版本控制观念。

版本控制软件维护一个库存放代码,每个开发者将代码取回作本地开发,然后将代码放回,代码放回后其他开发者才能看到。

每个人都必须正确掌握VSS的使用,培训是必要的。

VSS默认配置为不允许多人签出,这正是我们需要的。每个人都需要设置对项目操作的递归选项,这样可以连同子目录一起操作。签入文件后应查看历史或比较文件以确认签入正确。

熟练掌握目录比较和查看历史对每个人都很重要。

8.2 开发工具VS(visual studio)

建立C++ Win32控制台项目,空项目。

将项目文件添加到项目中,建立与实际目录结构一致的VS文件组织结构。

如果有头文件需要配置搜索路径才能访问,则设置项目的"附加包含目录"。否则无法解析头文件,不能提供类型帮助。

如果不使用VS整合的VSS访问则每个开发者都要重复这些工作。如果把项目文件放在VS的项目文件之下的子目录(此时VS项目文件存储代码文件的相对路径)则可以直接复制VS项目文件给别人用。

如果使用VS整合的VSS访问则使用VS的添加到版本控制的功能将项目添加到VSS,其他人用VS的从版本控制打开项目即可。

VS不提供FTP功能,需要同时打开一个FTP软件来上传源代码。如果愿意,可以对VS做二次开发来简化操作。

VS提供的最大帮助是即时解析源代码提供变量、函数说明、类成员的信息等。VS提供的查找、替换、格式化功能也是很强大的。有经验的使用者可以写出一次编译通过的代码(呵呵,绝不是无BUG)。

8.3 数据库工具TOAD

TOAD能提供数据库的脚本、数据脚本、数据库变更脚本,能做全用户的导入导出。

导出的数据库结构脚本可以入库进行版本控制。可以用数据库脚本或数据库备份重建开发者环境。

对数据库的变化应该提供变更脚本。

所有用户共享一个库的风险是很大的,一个人的误操作就可能毁了一切。

8.4 数据库结构检查

标准的数据库结构检查是查询数据库数据字典。数据库数据字典是一组视图,可以查询所有的表、列、约束、同名词、序列、过程等的详细信息。

复杂的程序可能需要查询数据库结构来确定操作如何进行,这是完成一些自动维护任务所需要的。

8.5 UNIX SHELL 脚本

编写复杂的脚本可以执行很多复杂任务。比如自动检测机型、判断主机资源状况、执行数据库脚本(可以配合复杂的sqlplus脚本)检查数据库结构、根据实际情况执行不同的编译过程或其它程序等等。

整个项目保持为同一个软件包,用单一方式编译执行是很有价值的。脚本至少可以做到根据机型使用不同的配置文件、根据参数自动选择合适的优化开关、自动处理特殊的预编译宏、自动执行数据库检查脚本。

Shell编程的关键是掌握返回码的处理和条件逻辑,这样就可以有机地把命令组织起来像个像样的程序。

8.6 维持单一版本

不同厂商的UNIX环境有很多差异,尽可能选择通用的语法,避免编译问题。无法避免的可以用宏开关来处理。对宏开关要能用编译脚本自动处理,手工处理容易出错。

有时不同用户会提出冲突的需求,优先选择通过配置实现,实在不方便的可以用开关实现,但最好不要用宏开关,用全局变量开关比较好。

可以建立一个系统表记录用户信息,程序启动时初始化全局变量,程序根据全局变量决定特殊处理。

8.7 避免绝对依赖关系

任何一个系统都应该避免对环境做过多的假定,不依赖特定的用户、目录、端口、系统Key之类的东西。当系统发生问题需要调试的时候,很可能需要在正在运行的系统的"旁边"建立测试系统,比如在另一个目录用不同版本的代码编译执行,或者希望程序将输出输出到一个临时位置。设计时考虑调试需要可以方便后期的工作。

8.8 记录变更历史

项目必须有一个文件记录变更历史,由每个变更实施者填写。该文件可放置在项目根目录下。记录每个变更的时间、人员、原因、方案、变更的项目、相关影响等,特别是数据库的结构变化。每个变更顺序编号。

小组负责人将随时检查变更历史。

8.9 自动版本升级

软件升级应当简单,执行一个程序或脚本即可,不要让用户去执行琐碎的修改。

对开发而言同步不同的开发环境也需要这样做。

8.10 版本标识和检测

软件应标识自身,程序执行首先应显示版本信息。每个模块都有自己的标识。

应检查数据库结构和软件的预期是否一致。不一致时程序必须拒绝执行。

对相关模块版本也应同样检查。

(这里是结束)

相关推荐
Old Uncle Tom16 小时前
LLM 替代 SAST?Claude Code 安全审查工具的设计取舍与工程启示
人工智能·安全·软件工程
地图小课堂18 小时前
Bigemap Pro如何打开无人机航拍影像并套合配准(有坐标 geoTiff、ecw)
无人机·软件工程
长不大的杨瑞杰1 天前
OpenCode v2 多源上下文实战:Websearch、References、Attachments 与缓存预热
人工智能·安全·云计算·软件工程·devops
howard20052 天前
软件工程课程架构思维导图
软件工程·课程架构
七夜zippoe2 天前
软件工程3.0时代,大模型驱动测试实战指南
大模型·实战·软件工程·测试·驱动软件
rolt2 天前
04 ESLint和Dijkstra-评点茹炳晟文章中的一段话
人工智能·软件工程·ddd·领域驱动设计·敏捷开发
无心水2 天前
6、软件工程 核心考点与学习笔记
笔记·学习·软件工程·软考高级·架构师·软考·软考系统架构设计师
长不大的杨瑞杰2 天前
OpenCode v2 远程开发实战:Web UI、Pair、SSH 隧道与 OpenTunnel 安全接入
人工智能·安全·云计算·软件工程·devops
长不大的杨瑞杰3 天前
OpenCode v2 MCP 与插件体系实战:把数据库、工单和内部 API 安全接入 Agent
人工智能·安全·语言模型·软件工程·1024程序员节
rolt3 天前
[存档]Alistair Cockburn-2003年11月UMLChina交流会
软件工程·产品经理·uml·敏捷开发·用例·cockburn