说到软件项目的依赖管理,可以从三个方面来考虑:

一、由build system控制的dependency

现在的build system,都支持一定程度上的dependency management, 比如make支持target之间的dependency,ant也支持其每个target之间的dependency(区别是make的每个非PHONY的target是个文件,make会检查输入与输出之间的timestamp来达到incremental build的效果,而ant则是对上一次build没有任何记忆,除了javac task支持incremental compile)

上面的dependency讲的主要是如何确定build的顺序,但dependency管理的另一个非常重要的目标,是自动获取dependency,并设置好:

  • 对于C++来讲:includedir(-I), libdir(-L)
  • 对于Java来讲:classpath

手工的维护这些path,非常麻烦而且容易出错,因为我们在一个过低的level管理这些信息 - 事实上,正确的做法应该是:用户只需声明我依赖这个component或者我依赖这个library,dependency manager自动帮我设置好这些path。

总的来讲,dependency manager有这么几个作用:

  • 让用户在合适的逻辑层次声明dependency,自动设置好需要的path
  • Resolve transitive dependency
  • Conflict manage (diamond dependency)

这些功能都不是手工能够解决的。

二、不由build system控制的dependency

如果有两个或者多个不同的project,由不同的team开发,甚至使用了不同的build system,那么基本上是不可能把他们放在同一个build pipeline中编译的。但是他们之间又有dependency,该怎么处理?

这里其实就是一个升级的问题, 比如:

B -> A/1.0

而A还是不断的开发,可能会改变已有的实现(引起B的运行时错误),也可能改变已有的接口(引起B的编译时错误),如果B在一段时间之后升级到A的新版本A/1.1,B可能需要很长时间做migration - 或者说integration。其实从continuous integration的角度来理解这个问题,正确的做法应该是:

A要尽可能快的推出一个新的release,而B要立马跟上,这样每次B的改动都非常小,不容易出错,出了错也容易解决。

但推出一个新的release毕竟不是件小事,很多team会有自己的担心:资源不够,risk太高等等 - 所以上述是一个比较理想的情况。在达到那个情况之前,可以另外有个方案:

B继续使用A/1.0, 但是同时B新开出一个branch:B/edge,依赖于最新的A的代码,A的每次build,都会trigger B/edge的build (edge build),这样保证B总是build against最新的A,任何问题都可以在第一时间发现,并fix

关于edge build,值得另外写一篇文章讨论一下。

这里,这种不由build system控制的dependency,就需要由其他系统来控制,比如各种CI server中的job,一个job会trigger另外一个job,也是一种dependency关系,刚好对应起来。

三、dependency graph的显示

软件项目之间的dependency graph,很好的反映了各个项目之间的关系,注意这个dependency的单位不是project,而是release,这更动态的反映出了依赖关系,同时,由于你知道每个项目的dependency,根据这个信息就能建出一张完整的dependency graph,从而能得出所有consumer的信息,于是,我就有了关于这个项目的所有dependency和consumer的信息:

  • 我用了那些项目,用的版本会不会太老?
  • 我被哪些项目用了?受不受欢迎?是不是可以停止支持某个release了(如果没有太多consumer的话)

显示一个项目的dependency时,可以有以下几部分:

  • 直接dependency
  • 间接dependency
  • 直接consumer
  • 间接consumer
  • dependency graph

关于dependency graph,要注意的是:首先它是一张完整的图,正确的显示了所有直接dependency和间接dependency,但是这样的图,对于一个大的项目来讲的话,会比较乱 - 考虑某个项目即是直接dependency,又是间接dependency的情况,就会有多个箭头指向它。所以一般显示的时候,会将其的transitive reduction显示出来(tred,dot自动做reduction),在保证其reachbility的同时,减少边的数量,使图看起来比较简练:

还有要注意的一点是,我们需要提供额外的metadata,来保证这个图的正确性。以ivy为列,ivy.xml提供了比较完整的dependency信息(没有类似机制的build system至少要产生这种metadata),但其问题是对于有dependency conflict的情况(diamond dependency),如上面第二张图,如果b和c依赖于不同版本的d,单凭ivy.xml无法确认到底选d的那个版本,这是ant/ivy在build过程当时选择一定的conflict manager方式确定下来的,而这个信息,必须以某种方式告诉dependency graph - 一般的方式就是在build过程中产生metadata并予以保存。

对于没有ivy.xml这种机制的build system,需要产生metadata一保存:

  • 所有直接的dependency
  • 有conflict的间接dependency

然后可以根据所有项目的这个信息产生正确的dependency graph

谈谈软件项目的dependency的更多相关文章

  1. 学习笔记——Maven实战(三)多模块项目的POM重构

    重复,还是重复 程序员应该有狗一般的嗅觉,要能嗅到重复这一最常见的坏味道,不管重复披着怎样的外衣,一旦发现,都应该毫不留情地彻底地将其干掉.不要因为POM不是产品代码而纵容重复在这里发酵,例如这样一段 ...

  2. 团队项目——编写项目的Spec

    团队项目--编写项目的Spec 一.Spec的目标        spec主要用来说明软件的外部功能,和用户的交互情况,主要用来说明软件内部的设计.图片编辑器是与生活息息相关的一个必备软件,随的流行, ...

  3. 为什么项目的jar包会和tomcat的jar包冲突?

    为什么项目的jar包会和tomcat的jar包冲突? 碰到这个问题,猜测tomcat启动时会将自己的lib和项目的lib在逻辑上归并为一个大的lib,但是并没有做版本区分以及去重,这样相同的包可能就有 ...

  4. IDEA Maven项目的Mybatis逆向工程

    IDEA Maven项目的Mybatis逆向工程 1.配置.pom 如果是在多模块开发下,该文件逆向工程要生成的那个模块下的pom文件. <build> <plugins> & ...

  5. eclipse 导入包含子maven项目的maven项目时的正确方式(父子项目)

    eclipse 导入包含子maven项目的maven项目时的正确方式(父子项目) NO1 导入时依次选择 import > Maven > Existing Maven Projects ...

  6. dajie项目的坑

    1.首先IDEA巨坑无比的地方是引入时,只要哪怕一个依赖下载不到,就会长期阻塞,删除.重新引入都没用!! 2.注释掉项目及其子项目中所有pom.xml中引用的spring仓库,否则即使maven配置阿 ...

  7. mavean项目的jar位置的影响

    由于项目的数据库需求改变了,有mysql数据库变为oracle的,那么对于项目就是需要改变数据库连接池.这个项目运用了mavean框架,那么下载jar在pom.xml文件中填写就可以了,但是oracl ...

  8. Spring Boot 不使用默认的 parent,改用自己的项目的 parent

    在初学spring boot时,官方示例中,都是让我们继承一个spring的 spring-boot-starter-parent 这个parent: <parent> <group ...

  9. 对于maven创建spark项目的pom.xml配置文件(图文详解)

    不多说,直接上干货! http://mvnrepository.com/ 这里,怎么创建,见 Spark编程环境搭建(基于Intellij IDEA的Ultimate版本)(包含Java和Scala版 ...

随机推荐

  1. IIS和tomcat共用80端口

    IIS和tomcat共用80端口 很多机器都需要同时使用tomcat和iis两个服务器以部署不同的网站,而解决共用80端口的问题也经常遇到,今天实际操作了一回,以下是具体步骤: 实现tomcat和ii ...

  2. Oracle 外连接和 (+)号的用法

    对于外连接,Oracle中可以使用“(+)”来表示,9i可以使用LEFT/RIGHT/FULL OUTER JOIN,下面将配合实例一一介绍.1. LEFT OUTER JOIN:左外关联 SELEC ...

  3. SQL Server(四)——查询练习(45道习题)

    题目:设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher). 四个表的结构分别如表1-1的表(一)~表(四)所示,数据如表1 ...

  4. 十五天精通WCF——第十二天 说说wcf中的那几种序列化

    我们都知道wcf是由信道栈组成的,在我们传输的参数走到传输信道层之前,先需要经过序列化的过程,也就是将参数序列化为message,这篇 我们就来说说这里的序列化,蛮有意思的,可能初学者也明白,在wcf ...

  5. mysql-3 检索数据(1)

    SELECT 语句 SELECT检索表数据,必须至少给出两条信息--------想选择什么,以及从什么地方选择. 检索一个列 SELECT prod_name FROM products; 上述语句利 ...

  6. itext 实现pdf打印数字上标和下标

    https://kathleen1974.wordpress.com/category/itext-pdf/ In one of my project, we need to give the use ...

  7. SQL中JOIN 的用法

    关于sql语句中的连接(join)关键字,是较为常用而又不太容易理解的关键字,下面这个例子给出了一个简单的解释 --建表table1,table2:create table table1(id int ...

  8. db2服务端安装图解

    一. 准备工作 1. db2服务端安装包,版本:10.1.2 二. 安装图解过程 1. 响应文件是一个包含安装和配置信息的纯英文文本文件.可无需任何用户交互进行db2的批量安装.非必须的. 2. 点击 ...

  9. Android程序函数 将assets文件夹下的文件复制到手机的sd卡中(包括子文件夹)

    最近在做个功能是将asset文件夹下的所有文件(包括子文件)全部拷贝出来到指定目录下.所用的方法无非是用AssetManager.但是这里 有个问题是也要讲子文件夹和子文件都要拷贝出来.到网上Goog ...

  10. 如何在Chrome39添加360抢票王插件

    前言: 版本:Chrome 39.0.2171.95 m CRX文件来源:ext.se.360.cn 本文地址:http://www.cnblogs.com/go2bed/p/4206714.html ...