C++项目管理

该文章来自于阿里巴巴技术协会(ATA)精选文章。

1.编译的严谨性

(1) 头文件的正确性

C++ 采用"separate compilation"(分离式编译)意思就是说在编译一个 foo.cpp时,唯一的对其他依赖代码的要求就只是看到它们的头文件
(header files),所以,只要每次编译时可以确保 foo.cpp和它 include的所有header
files都是一致的就可以了。但是,我们目前并没有做到这一点,因为,

  • 一个员工不同时候的编译
  • 不同员工的编译
  • 不同机器上的编译

在以上的各种情况下,这些 header文件有可能不同或被其他人更改而无法察觉:

  • linux headers
  • glibc headers
  • gcc headers
  • 三方库 headers

alicpp 意在解决这个问题,因为在 alicpp环境下编译时,所有以上文件,甚至包括编译器本身,都是
alicpp gitrepo里的文件,并且这些文件是只读的(永远不会更改内容)。

(2) 三方库的菱形依赖问题

假如MyClass.cpp依赖了两个三方库 a和
b,它们又都同时依赖第三个三方库 c,此时我们必须保证 a和
b依赖的是同一个版本的 c,而不能是稍有差异的不同的 c,否则会出现难以查询的
buildproblem,编译会通过,但是生成的执行文件是有问题的。

alicpp 清楚记录每一套三方库的依赖关系,精确到版本号,以确保完全避免菱形依赖关系可能带来的隐患 。

2.链接的严谨性

(1) 动态库的正确性

我们有没有问过自己一个问题,那就是线上运行的时候找到的 .so是否是我们研发或测试时使用的同一个
.so文件?这些 .so包括:

  • linux 和 glibc 的,比如 libpthread.so, librt.so
  • C++ 的,比如 libstdc++.so, libboost_xxx.so
  • 三方库的,比如 openssl 的 libcrypto.so
  • 二方库的

对任何这些机载的 .so文件的依赖都会造成程序运行的不确定性,因为任何其他部门的人或任何人的错误操作都有可能对这些文件作变动。

前面提到的三方库菱形依赖问题在链接时依然存在,当两个三方库想要链接不同版本的 .so时,它们在执行时是冲突和危险的。

(2) 全静态链接

假如我们用静态链接的方式链接所有依赖的库,突然世界变的非常的美好,

  • 我们发布的时候不再需要准备什么 package,因为只有一个执行文件需要 push 到目标机器
  • 在目标机器上也不需要什么 ldconfig 或 LD_LIBRARY_PATH,不会有 .so 查询不到的问题
  • 因此也就不会链接到错误的 .so
  • 静态链接的程序因为没有 GOT (Global Offset Table) 的间接符号查询,所以执行速度会快

我们对目标机器的依赖性因此降至最低,只要是正确的 Linux大版本,就不会出任何问题,所有其他团队可以升级更换机器上的其他软件而不受其影响。

当然,全静态链接也有一些问题,

  • 链接速度慢:下面会提到解决方案
  • 文件可能很大:其实今天来讲 1GB 之内都是没有问题的
  • 执行时不能多个执行文件共享一个 copy 的 .so:但假如整个机器给了一个应用,那 .so 和 .a是使用相同内存量的
  • 在一些特殊情况下,不得已必须用 .so,比如动态生成的 .cpp 代码,Oracle 未开源的代码库,等等特殊情况

无论如何,大家应该看到全静态的美,尽可能的用静态方式链接更多的库,alicpp帮助大家准备全静态的链接指令。

(3) 半静态链接

如果我们很在意线上运行时不能链接到错误的 .so,我们可以靠生成特殊的 .so文件名来解决这个问题,比如:

pangu-trunk-3412562.so

<项目>-<repo>-<revision>.so

此时的 .so就成为“只读文件”(意思是名字和内容是一一对应的,没有人可以用同一个名字定义另一个改变了内容的文件),可以确保链接的绝对正确性。

3.编译和链接的速度

有了严谨的编译和链接守则,我们就可以把大家统一到一个编译和链接的标准和流程上来,我们也就可以统一的来解决我们的编译和链接的速度问题。

(1) 编译的速度

alicpp 将致力于建立一套完整和庞大的编译系统来优化我们的日常编译过程 T264,其中会用到,

  • 大规模集群上的分布式编译
  • pre-compiled headers (PCH):因为我们完整的操控了所有 header files,我们可以提前编译好这些头文件
  • cached .o:我们绝大部分编译工作是和同事们编译相同的 .cpp,我们可以把编译结果记录在类似于 ccache 的内存中
  • offline compilations: 我们会在凌晨时分提前编译好常用文件

(2) 链接的速度

alicpp 会尝试 Google的 Gold Linker,可以
5到 10倍的提高链接速度 。

4.多模块代码共建

可以说我所看到的我们目前的 C/C++团队和模块之间的协作关系是混乱不堪的,因为我们没有遵守应有的法则。这里详细的记录和解释了每一个步骤和理由:

IMPORTANT: 这里的守则是“充分”和“必要”的,换句话讲,没有一个是不需要的,也没有一个是没有提到的。

(1) 模块的依赖性

我们每一个团队对其他团队的依赖性都可以按照进度要求来分成三种情况,

(a) 弱耦合

我们对对方的进度要求不高,我们需要的功能目前已经提供了,如果将来有新版本的话,升级了当然好,但是不升级也问题不大,即使升级也是低优先级的工作。典型的例子是对大多数三方库的要求。

(b) 强耦合

我们必须尽量跟上对方的进度,不然就造成软件对接的诸多问题或是线上支持的困难,但是我们又担心跟的太紧会看到对方不必要的新代码带来的 bug,此时我们要的是“尽量跟上,但并不要最新版本”。我们很多团队之间的关系就是这样的,比如
ODPS 软件依赖底层的飞天系统,但是 ODPS有自己的稳定性需求,不能对新写的飞天代码跟进太快。

(c) 强强耦合(一体)

我们必须和对方是相同进度,因为我们代码的依赖性太大,同时双方又在不断做调整。我们小团队之内就是这种情况。假如两三个小团队之间也相互依赖的非常紧密,也是处于一体状态中。

(2) 代码库的结构

针对以上三种依赖性,我们就可以直接确立代码库的结构:

IMPORTANT: 明明是强耦合的情况却自己定义成弱耦合是偷懒!明明是强强耦合的情况却自己定义成强耦合是分裂主义!我们要尽可能的把依赖性朝着强的方向确立。 
(a) 弱耦合

弱耦合的模块可以在不同的 git repo(svn库)里,比如
alicpp的三方库,甚至于一些二方库,它们可以有自己的 git repo,只要我们有办法找到他们的
include 和 lib就可以和它们对接编译和链接,我们也可以从容的针对它们的不同版本进行引进,非常长期的做版本升级工作。

(b) 强耦合

强耦合的模块必须在同一个 git repo(svn库)里开发,编译速度不是我们分属不同
git repo的借口,我们正在解决这个技术问题。代码权限是人为的分属不同 git repo的障碍,我们正在解决这个行政问题。我们之所以说“必须”在同一个
git repo,是因为下面会介绍到 git/svn的命令在做代码操作时,只有在一个
git repo里才能最容易和自然的实现。

(c) 强强耦合(一体)

强强耦合的模块必须在同一个 git branch(svn
branch)里进行,git branch或
svn branch是我们开发的最小单位,在同一个 branch里研发的人员应该坐在一起,有问题可以马上解决,只有这样才能让相互非常依赖的代码以高速前进。

(3) 代码周期

上图中,"aliyun"(阿里云)是多个强耦合团队的总和项目,是一个
git repo(svn库),"pangu"(盘古)是阿里云的一个负责底层库的团队,是一个
git/svnbranch,这张图里列出了所有维护代码库需要的 git/svn命令,

  • git branch: 一次性的,盘古创始人执行这个命令后,从此所有盘古团队的人就都在这个 branch 里写代码
  • git merge: 经常性的,盘古团队负责人负责定期的将盘古的代码 merge 进入 master/trunk,也同时把 master/trunk 的代码 merge 进入盘古 branch
  • git cherry-pick: 偶尔性的,有的时候另一个团队的 bug fix 或小改动是急需的,就只把那个diff (代码改动)采摘过来

IMPORTANT:
除了这些命令外,不再需要任何其他命令,更加进一步说,其他任何命令都是不允许的。

见上图,多个团队时,每个团队都在做同样的事,他们各自按照自己的进度 git merge和
git cherry-pick。注意,

  • 他们从不相互等待,只看自己的代码,稳定了就马上 git merge
  • 每个团队永远保持 master/trunk 的正确性和稳定性

那么如何保证 git merge后代码是正确稳定的呢?靠两件事,

  • pass 所有自己的 unit tests
  • pass 所有上层团队的 unit tests

NOTE:
这就是为什么我们要在一个 git repo里做强耦合的代码开发,因为底层的改动必须自己编译所有上层代码,并负责跑通上层的人写的保护自己的
unit tests。

假如 git merge后master/trunk变的不正确不稳定了呢?那相互伤害的团队必须同时补足各自的
unit test,因为双方都有责任:

  • 害人方没有写到一个 unit test 可以察觉错误
  • 被害方没有写好一个 unit test 可以防止别人伤害到你

久而久之,日积月累,我们的 unit test
就会变的无比复杂和盘根错节,变的让 bug无以遁形。

IMPORTANT:
代码的稳定性来自于天长日久积累的 unit tests,不是靠战战兢兢的研发,慢慢悠悠的发布,代码不是红酒,不是放在那里就会自己变好的,所以把发布时间拖长是不会让代码更稳定的。

(4) git merge 周期

一般来讲,我们可以每星期或每半个月 git merge一次,让其他所有团队看到自己的代码变化。刚刚开始
git merge时可能 break master(不是简单的 compilation
failure,而是逻辑错误)很多次,那不是因为我们 git merge太频繁了,而是因为我们的
unit test太少了,要在此期间为每一次 break加 unit test,直到稳定为止。

IMPORTANT:
明明已经可以 git merge而不做是偷懒!是耽误其他所有人进度的不负责行为!

(5) master/trunk break

必须在所有团队告诫大家master/trunk break是不可饶恕的错误!

  • 最后 git merge 的人必须负责跑通所有已有的 unit tests
  • 一旦 break 必须马上 fix
  • fix 里必须有新的 unit test 去避免将来的类似错误

(6) Master + Delta

每个团队发布的软件都是 Master +Delta,"Delta"是指自己团队的代码改动。不可以有任何其他的组合(比如
master +pangu branch + fuxi branch),原因很简单,因为每次 git merge时每个团队已经努力确保
master是正确的,而 pangu branch + fuxibranch并不是 fuxi团队背书认可的组合。

5.测试系统

对于 C/C++
这门语言来说,再也没有比 unit test更能让它稳定不出错的了。unit test就像马路上的车一样,而
bug就像想要跑到路对面的小老鼠一样,我们在抱怨我们的软件 bug特别多,很简单,因为我们的马路上就没有什么车在跑,好的
C++项目 unit test繁多,小老鼠根本没有机会可以跑到路的对面而不被撞到。

一个特别错误的认识就是把发布的时间拖长,认为这样软件问题就会减少。好吧,让我们来分析一下,

  • 时间拖的再长,其中做的测试有哪些?假如有更多的测试,或许等待是值得的,但是几乎再多的测试一般来讲一天是可以跑完的,那么,假如一个软件是一个月或半年才发布,只有一天是有效的,其余时间都是在无谓的等待。
  • 时间拖的再长,其中的问题是不会自己解决的,我们无非是把解决问题的时间压缩到更晚更短的时候而已。如果一个 bug 在我们头脑刚写完代码时是最容易解决的话,为什么要等到一个月后生疏了才去解决呢?
  • 缓慢的节奏让我们的程序员们变的技术迟钝,无法在快速迭代中学到专业的 C++ 代码研发

并不是让我们每天都发布,适当的控制风险是必要的,但是可以认为任何超过一个月的发布都是拖沓的和缓慢的,我们控制风险靠的是测试集群的设立,尽可能模拟线上环境的测试,灰度发布,等等手段,其中没有一个是“等待”。

IMPORTANT: “等待”就是浪费生命,浪费公司财产,是
C/C++ 代码研发效率低下的表现,是不知道如何提高系统稳定性的懦弱做法。希望大家真正的提高我们的工作节奏,摒弃等待的消极做法。

IMPORTANT: “迟迟不敢跟进别的团队的代码”是我们长期没有遵守以上共建守则造成的,希望大家达到共识后,敢于
git merge,在 break时耐心增加
unit test来巩固我们的对 bug的防守线,慢慢的我们就会对
master建立足够的稳定度和信任。

alicpp 将着手于建立 continuous buildsystem(连续
build系统)和 continuous testsystem(连续测试系统),真正建立一套完善的
C/C++测试系统。

6.诊断系统

alicpp 会根据实际需要逐步补充各种线上诊断系统,比如,

  • core dump 的自动收集和分析系统
  • gdb 的自动符号查询
  • request capture/replay 系统,可以让我们更容易的恢复现场
  • memory leak detector,自动监测内存泄漏
时间: 2024-10-18 09:53:49

C++项目管理的相关文章

2016年下半年项目管理师中高级报考说明

一.报考条件      亲,没有报考门槛,只要您年满18周岁就可.没有专业.职业和学历限制.二.需要购买哪些辅导资料    1.中高项的官方教材都是柳纯录老师主编的,中级考友最好买一本,高级考友无所谓.最好以张老师的课件为主.    2.张老师亲自编写了过关法宝系列资料,考试必备呀.三.培训效果怎样     合格率54%左右,其中,上午合格率84%左右,案例分析68%左右,论文80%左右.     论文押题神准--学员说的.      张老师的培训良心出品.四.我不是IT专业,也不从事IT岗位,

3月23日 项目管理师作业

一.项目进度管理1.进度管理包括哪六个过程?1.活动定义 2活动排序 3活动资源估算 4活动历时估算 5制定进度计划 6进度控制 2.什么是滚动式规划?滚动式回话就是规划逐步完善的一种表现形式,近期要完成的工作在工作分解结构最下层详细规划,而计划在远期完成的工作分解结构组成部分的工作,在工作分解结构较高层规划 3.什么是控制账户.规划组合?控制账户是指高层管理人员的控制点可以设在工作分解结构工作组合层次以上选定的管理点上.在上位规划有关的工作组合时,这些控制点用做规划的基础 规划组合是指规划组合

&quot;产品测试管理&amp;敏捷项目管理&quot;研讨会在深圳成功举办!

2015年1月9日,由深圳市共创力企业管理咨询发起的"产品测试管理&敏捷项目管理"研讨会在深圳南山科技园创新谷咖啡成功举办!参加此次研讨会的企业有华为.中兴.烽火.腾讯.康佳.OPPO.元征.神视检测等高新企业管理人员,研讨会由研发资深顾问杨学明先生主持.此次会议的议程如下: 2016.1.9 10:10~11:00 由华为员工分享敏捷项目管理实践  2016.1.9 11:00~12:00 由元征科技分享IPD模式下的测试管理  2016.1.9 12:00~13:00 午餐

Scrum与项目管理亲体验

GXTP2.0已经结束一段时间了,我们JC小组也对1.0与2.0的项目管理做了一个项目总结,因为我们每个人以后都会做项目组长,所以我就代表我们组对这次项目管理中的一些经验,不管是好的,不好的,都说一下~ 2.0项目成员组成: *丹.小胡.*游.丹妹.英群.颖子.超强.炎炎.梦洁.浩源.庆波 1.0的项目时长68天,2.0的项目时长20天,经过总共98天的奋战,我们系统有了非常大的进展.下面就说说我们在管理过程中的一些好与有待改进的地方: 一.可取之处 1.每天有晨会和晚会,晨会的主要工作是让每一

管理经验(二)——项目管理基础

 引 开始准备信息系统项目管理师的考试,借机熟悉并掌握一些项目管理方面的知识.学习也有一段时日,考试的目的更是为了开阔自己的眼界,提升自己的能力,本篇博文仅是对项管内容绪论部分的总结.如图示: 释 先看我们的二级主题:项目.生命期.干系人.管理,在这里之所以我没有标出他们之间的关系,实则是因为他们之间说简单也简单,说复杂也复杂,用一句话总结:项目管理主要涉及到项目是什么.项目的整个阶段.相关的人及其管理.用更简洁的话说是:人.事.物.管理. 人--"干系人"(相关的人) 事--&q

技术开发团队的项目管理工具

前言 小型技术研发团队,往往开发流程比较简单:整理需求/bug.分配任务到个人.完成指定任务.验收.涉及到的相关管理工具主要是:项目/任务管理系统.源代码管理系统. 项目管理系统 从09年开始,我用过ActiveCollab做项目管理工具:后面12年开始使用禅道. AC从0.7以后的版本转向商业,但毫无疑问,这套系统给人一种优雅的感觉:而禅道,本身功能非常强大,一看就是一个工具,只是稍微缺少一点那种文艺范. 其实,日常生活中,个人还在尝试使用很多新兴的任务管理平台,像 Tower.TeamBit

你在做哪一种项目管理

小编今天才知道原来项目管理还分模式的.对于一些项目管理小白的小编不知道项目管理的典型模式还是可以原谅的.但是,作为业内人士的项目经理们,你在做哪一种项目管理,如果你也说不出来,以后容易给项目管理菜鸟笑话哦.据说项目管理过程分为两大类,学过项目管理理论知识的,应该都知道吧.项目管理模式就是基于这两分类而产生的. 项目由过程组成,项目过程可以分为两大类:一类是创造项目产品的过程(Project oriented Processes),另一类是项目管理过程(Project Management Pro

做BI项目管理的朋友,应关注什么

做BI项目管理的朋友,应关注什么呢?BI项目其实也是it项目的一种,一些it项目管理需要注意的事情,同样是需要做BI项目管理的朋友关注的.但是,对于BI项目来说,也尤其独有的一些管理细节需要做BI项目管理的朋友好好关注.注意这些细节,并且把这些方面的管理做到位,能够减少很多麻烦事情哦. 1.项目范畴制定和管理 很多人会自然地把这个步骤理解为用户需求的收集和制定.其实用户需求只是这个过程中的一个手段和结果.不管是自主开发,还是集成商为商业用户开放的项目,最终目的都是为用户解决工作中的问题,同时提高

大型it项目管理的六大风险管理

it项目的不确定性非常大,因此风险的发生可能性就大起来了.而对于大型it项目管理来说,风险管理就更应该引起注意.由于项目规模大,人员多,技术难度大,因此,面临的不确定会更大.那么,该如何去应对大型it项目管理的风险,对其做好管理呢?下文会从大型it项目管理的六大风险管理出发,介绍一些解决方法,主要是以银行核心系统升级项目来为例. 项目的成功离不开项目组所有成员的拼搏努力,同时也离不开成功的项目管理,尤其是风险管理.从项目启动阶段,制定了定性的风险计划,识别出风险级别最高的几个风险.为了减轻技术风

软件企业如何适应项目管理

现在社会的变化非常快,如今很多软件公司都是依靠开发项目来发展.倘若还应用传统管理模式来运作,是很难适应IT行业的节奏.那么,软件企业如何适应项目管理.这成为很多软件企业需要思考的问题. 软件企业初涉项目管理,容易出现问题多多的局面 项目管理虽然没有非常高深的理论,但要真正实施起来,也绝非易事.一个典型的项目基本可以划分为启动.计划.控制.执行.收尾五个过程.而软件企业实施项目管理的挑战,可以说是贯穿于项目的整个生命周期. 启动过程面临的第一个挑战是"项目目标含糊,充满冲突".项目的利益