关于代码编译打包和版本管理的一些事情

来源:互联网 发布:js中的parent方法 编辑:程序博客网 时间:2024/05/31 19:57
最近对于代码编译、打包以及版本的管理有一些想法,虽然比较简单,也先记录下来,以后再逐步完善

1、项目参与的人比较多,大概是200个人一起开发,经常发生提交到SVN上的代码编译不通过的情况,浪费了很多时间。

分析了一下,大部分是由于以下2个原因:

第一种情况:开发人员本地机器上有代码A和代码B,但是代码A在SVN上已经是比较新的版本,删除了某个方法,然后开发人员在本地修改代码B,调用了这个在SVN上已经不存在的方法(但是在本地的代码A上还是有的)。然后本地开发环境当然是编译通过的,于是开发人员就提交了修改后的代码B,这样一来,SVN上的代码肯定就编译无法通过了,报NoSuchMethodException

第二种情况:开发人员在本地修改了很多代码,编译都通过了没有问题,但是提交的时候只提交了部分代码。这样SVN上的代码就不全了,也会造成编译无法通过,报ClassNotFound或者NoSuchMethod

要避免上述第一种情况,就要求开发人员在提交代码之前,先把本地的代码更新一下,这样如果本地编译通过再提交,就会比较少发生提交后SVN代码编译不通过的情况

针对第二种情况,就要求开发人员每次把修改的代码提交完整

2、关于打jar包

打jar包比较简单,通过eclipse的export --> jar的功能就可以,在打包的时候,可以选择具体要打包的代码,或者资源文件,以及依赖的其他jar包。比如一个普通的java工程,里面有一个lib目录,放了很多依赖的其他jar包。那在把这个工程打成jar包的时候,可以把lib目录也打出来,或者不打也是可以的,由自己选择,一般是不会打的

这里说个题外话,为什么有时候从svn上import了一个工程,发现无法编译(红叉叉),报缺少jar包呢。这时候要看一下工程对应的.classpath文件,里面可能是引用了user library,而user library是依赖eclipse的,并不像lib文件夹里的jar包那样,可以上传到svn上再下载下来。也就是说开发人员A机器上自己建了一个user library,开发人员B的机器上是不会自动有的

其他的library也是类似的情况,比如开发人员A引入了tomcat runtime library,那开发人员B如果不对eclipse进行配置,那这个工程也是会报错的

所以多人一起开发的时候,统一开发环境是很重要的,不是说引入的jar包一样就可以,eclipse的配置,容器的配置,user library的配置都需要统一,这个工作应该是和搭建开发框架同时进行的,在开发正式开始之前就应该做好

一个工程是可以打出很多个jar包的,并不是说一个工程就只能有一个jar包。因为本质上jar包就是一大堆类和资源文件的集合而已。比如说大家熟悉的spring框架,其实原始工程只有一个,但是根据模块的不同,最后打出了10多个jar包,不同的项目只需要引入必要的部分就可以了。还有logback也是这样的,发布的版本是有3个jar包的,logback-core.jar、logback-classic.jar、logback-access.jar,但是原始工程也是只有一个。如果把logback-classic单独还原成一个工程,这个工程也是要报编译不通过的,因为logback-core里的很多类都缺失了。

因此工程和jar包可以是一对多的关系。比如开发了一个通用工具类的工程,然后也可以根据需要把这个工程打成多个jar包,比如time-util.jar、string-util.jar等,道理是一样的

3、关于打war包

打war包的情况比较单纯,仅针对web应用。用export --> war的功能,可以很简单地打出一个war包,这个war包的目录结构符合servlet规范,可以扔到容器里直接运行。要注意的是,打包和开发也是不一样的。比如在eclipse上开发一个web应用,首先需要指定一个runtime library,如果选tomcat的话,eclipse会自动给工程引入一个java ee runtime library,这样开发的代码就不会报错了。像Servlet、HttpServletResponse这些类,都是在这个run time library里支持的。

但是到了发布war包的时候,WEB-INF/lib下的依赖jar包,会自动地打到war包里,可是runtime library里的这些jar包是不会的。这也很好理解,因为war包最终是扔到容器里运行的,容器里已经有了这些jar包(如果用tomcat的话,是放在%CATALINA_HOME%/lib里),所以如果应用的.war里还自带这些jar包,那么就重复了。甚至如果开发时依赖tomcat的jar包,最终部署到jboss里,那可能还会有jar包冲突的危险。

顺带一提,开发的时候依赖哪个runtime library一般是问题不大的,因为无论是jboss、tomcat或者其他servlet容器提供的jar包,都是符合serlvet规范的,也就是说这些必须的类都是有的,不会造成开发时编译不通过。但是代码不要依赖容器绑定的类,否则的话代码就和具体的容器耦合了。比如代码里用到了Catalina.class,那这个应用在jboss里就没法跑了

4、关于拉分支

项目做得差不多了,需要拿到2个不同的地方去上线,2个地方分别有一些特殊的需求,这时候代码的维护就要注意了

如果是简单的拉2个分支,那加上原有的主干,就有了3套代码,也就是3个工程。这样就糟糕了,如果发现主干版本上有一个BUG,那就需要在3套代码里一起改,如果有N个分支,那就需要改N+1次

如果选择其中一个版本作为主干,拉1个分支,那情况稍微好一点点,有N个局点的话,就需要维护N套代码,比上面那种情况少1套,但是也没有本质的区别

如果把所有的需求都合并到主干代码里来,这种情况是最理想的,不管有几个局点,都只需要维护1套代码就可以了。不过实际情况往往没有这么理想,比如2个地方的需求有冲突,那要合并成一套代码就比较困难了,需要在设计上做特别的考虑,比如用配置文件做一个开关等等

总结来说,对于多个版本的维护,有以下几条原则(不一定对,请大家指出)

A.条件允许的情况下,尽量保证只有一套代码。即使临时拉了分支,也要尽快(比如一周之内)合并到主版本中

B.对于需求有冲突的情况,或者某些需求这里要那里不要的情况,可以通过配置文件、开关等方式,也合并到一套代码里,避免出现拉分支的情况。这需要设计上多费工夫

C.版本发布要控制住节奏,比如有的地方要求11号实现一批需求,有的地方要求18号实现一批需求,不能盲目地答应。作为项目经理,应该自己心中有一个计划,比如承诺10号交付第一个版本升级补丁,30号交付第二个,那11号要求的那批需求,可以赶一赶落到10号的补丁里;18号那批需求,顶住压力也要落到30号那个版本里去。否则别人要什么就给什么,很容易就把研发团队给拖垮了