项目源码与项目构建产物的版本管理

7 篇文章 0 订阅

前言

工作中杂事比较多,或许没有哪个公司会去给你专门的写技术博客的时间吧。我想说的是,也许会挤时间的人能够在工作间隙抽空写出自己对技术的感悟,一有某方面看法,立马能够捕捉当时想法记录下来,至少也方便后来的整理成文,而且能够用这种方式说服更多人认可他的观点。而对于我,事实上我没有写博客的习惯,但是我确实想写,记录出来,我只能说自己比较懒吧,可是我对我做的项目,对于我工作中遇到的诸多问题其实都有自己的想法,我时常有很多想要去改善的冲动,无奈,我目前做的项目有很多的问题,改动了一点小问题也不能拯救一个地球,地震呢还是会出现。因为我们一直相信的所谓的不要影响太大,只能让我们每一个项目成员束手束脚,始终不能解决根本问题!!像开头说的,我暂时只有在晚上努力绞尽脑汁去想工作中出现了哪些问题,如何有秩序的分析这些问题,并合理整理成文,剖析项目的根本管理问题。
其实我应该用一个富文本去写这些内容,但是我确实很少写博客,暂时只能在手机上先用这种笔记本的方式记下来,文中大部分都是文字的描述,我尽可能写的让大家看懂,明白我,理解我,赞同我!!!
介于项目问题比较多,代码规范问题,版本管理问题等。我今天就挑出项目根本的问题来谈!!!

正文

这个最根本的问题就是项目的版本管理问题。而我今天的话题是项目的代码版本管理与部署后的项目版本管理。
首先我强调的是前者关注的是源码,包括项目所有的java源代码、用到的jar库、用到的资源、所有为初始转化和编译而存在的编译脚本。而后者实际上是已经编译并且组装成符合webapp规范的目录的产物。即后者是前者转化过来的,当然更多的是编译过程,而编译后还要对资源和编译产物进行组装成最终web服务器能识别的标准产物,这个标准产物有它规范的目录,这话我又说了一遍,不懂的就百度java web应用部署的目录规范。所以我就抽象叫这个过程是一种转化过程,转化的过程可能复杂,也许你认为简单,说复杂是因为我们的源码目录事实上是可以很随意的,只要我们定制我们的编译脚本,按照我们自己的目录逻辑去构建项目,最终还是生成标准的Archive,即可部署的web app。
说了大半天,你可能还没理解我说这些干嘛。我想说的是我们没必要去关心构建过程最终生成产物与源码的区别,他们唯一的区别就是源码给我们看,产物给计算机看,我们是高级动物,我们当然看高级语言,我们知道这个源码经过那个构建脚本编译成最终产物扔给服务器就行了,我们无论任何时候都不要傻瓜蛋去对编译产物进行搬砖的动作。我们只要明白一点,源码只要固定在一个版本,经过我们已经定制的构建规则,它的产物永远不会变,而且是二进制的不变,结论就是源码与构建产物是一一对应的,就像如果你是男的就不用生孩子这样一一对应的因果关系,当然那些所谓男的也能生孩子的例外就不要跟我说了。

所以我总结一下,我们管理源码版本就是等于管理构建产物的版本。这里就只说源码版本,就可以解决所有问题了,可是我开篇的标题好像在扯什么犊子,说什么管理产物的版本,好像与管理源码的版本是分开的。
我在里只想说我前面说那么多都是在做铺垫,且往后看。。。
这里我就要谈到我们目前项目版本管理的现状,因为我们没有做到真正的版本管理,因为我们硬性的把这种一一对应的关系通过我们来搬运构建产物而分开的,我们自豪的认为我们改了某个java文件,我们就把那个java生成的class文件也就是所谓的产物替换掉原来的即可。我们欣然的认为这样还做到了所谓的打补丁功效。
首先这种思路咋一看起来似乎蛮合理的,那么下面我就推到它。
首先我们管理源码的版本就是基于文件系统版本管理。我们先抛开构建产物这一环节。什么是所谓基于文件系统的版本管理,其实所有的版本控制工具都是对一个目录下所有的实际文件的版本管理,如果某个文件改动了,你觉得它会影响其它文件吗?我们说的不是后期业务上的影响,比如有两个txt文档,你改动其中一个txt文档,另一个txt文档会变化吗?如果变化了,我觉得你孙子开挂了。那么我们改动其中一个文件,提交后,到了版本2,而线上的版本,注意我这里提的是线上的源码版本,它还仍处于版本1,那么我们要想更新到2就相当于拿刚才改动的那个文件去替换就ok了,任何只谈文件系统的版本管理,就是这么简单,改动什么文件,我们就替换哪些,不用全盘拷贝,就是这么简单,这就是版本控制工具遵循的很简单的原则,当然像git可以对文本文件做到控制内容的打补丁,更能优化它的管理。
而我想说的你涉及到构建产物的版本管理时,你觉得你改动了某个java文件,你也学着版本管理工具所谓的原则,去替换构建产物的对应文件,啊,但是构建产物编译了,成class字节码文件了,吼吼吼,简单啊,老子替换字节码不就ok了。这里我要纠正一个误区,诚然很多情况下,我们改动一个java文本文件,对应的class文件基本上会变,那么对应的构建后的产物全局来说也基本上就只有这个文件会变,这个文件就是那个产出的字节码class文件。所以我们这时按照版本控制器的原则也确实只有它改变了,我们做一回手动替换那个改变的产物文件,整个项目系统确实达到了一定的版本管理。
但是有意外情况啊,兄弟。举例,java编译规则有一条,就是一个java类A如果引用了另一个java类B中的一个常量配置参数,所谓的常量就是final加static修饰的,在整个系统运作过程中这个变量也不会变化,所以编译期间类A就直接把类B那个常量的值拿过来,记住是值,java这样做,是有它的原因的,因为编译期间就静态确定这些东西,还有一些固定大小内存分配的确定等等,就比如基本类型的出现就是这个原因,这样在编译期间就静态确定了,运行时就不用动态去检索可以优化java运行。OK,这样情况下,有一个需求我们要调下这个参数,那么我们就去修改类B的这个常量值,想当然的,我们很happy,我们觉得我们只改动了类B,也就是所谓版本控制器遵循的最基本的原则,改什么替换什么嘛,我们编译类B后,把字节码替换到产物目录中对应的旧的类B的字节码文件。
这样完事了吗?哥们?你可以测试下,如果类A是输出那个类B那个常量值,我相信,它绝对输出的是旧的常量值。原因就是刚才那条编译规则,你确实替换了类B的常量值,但是你整体编译项目,类B引用的常量值事实上也变了,因为它是静态写入值的,所以,当时你改变了类B,类A其实也变化了,而你只替换了类B。你还敢这样做吗?你还好意思乱用这种原则吗?我只能答到你是用错地方了,因为你是起初改动的是源码,而你替换是产物。你又不是直接的去改动class,再直接的去替换class,那么直接的去改动class,你觉得可能吗,我们操作的是高级语言,面向我们的只能是文本文件,中间你尚且不知道还有个构建的转化过程吗?构建是整体的,java类是各相逻辑关联的,你可以理解java的编译就是做了一个逻辑外挂处理,它对任何java文件的编译都有潜在的与底层jdk或第三方jar或自己编写的其它需要引用的类有着编译规则层面上的逻辑关联,这实质上就告诉我们编译是对应的一套整体代码和平台,我们不能把对源码的修改按照文件系统修改的原则联动到产出物应该的变化,我们也无需把精力用在关心这个变化上,我们更应该只关心源码层面上的版本,通过一套构建体系来产出我们最终要的发布版本。而对于任何一套系统或者说一个软件类项目,我们也更应该明白要以源码为基本版本管理来创作研发,因为我们做的都是上层应用级别的项目,读源码也就是读这个项目的逻辑运作,高级文本语言的修改最终构建后也会翻译成底层的计算指令,从而实现需求的增加以及bug的修复。再者来说,java虽然有所谓java与class对应关系,诚然这样,也不是一对一的。一个java内如果有匿名内部类,还可能生成多个字节码文件。打个比方,如果有一天java构建规则大改变,编译出来是个整体的某种类型的单个文件,你还怎么去一对一,改动,然后替换?似乎行不通吧?!
总结:说了这么多,不知道大家有没有明白这其中真正的规范。既然用版本控制工具可以很方便自动化的管理我们的文件系统,即项目源码,方便它的源码版本的回退与控制,为何还要多一事去操心构建产物的手动操作搬运,前面已经说了源码与构建产物是一一对应的的,中间经过构建脚本的构建即可,一切是多么自动化可控制化。
即便你想要弄出打补丁的方式,不想整体替换,你也得遵循原则。只要你不觉得麻烦,你也可以拿出两个版本的源码,各自构建后,再对构建产物做两相二进制对比,做手动替换也可呀,而不应该用上面说的方式去做。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值