组件版本管理
任何编程语言, 当组件有依赖关系+版本管理之后, 都会遇到同样的问题, 相依性地狱
常见的问题有:
- 循环依赖: A依赖于B, B依赖于C, C依赖于A, 相互循环依赖, 导致解析无法继续
- 版本不兼容: A依赖于B,C1, B依赖于C2, C1与C2不兼容时, 导致系统无法运行
- 依赖过多: 依赖的深度与广度都比较大, 导致系统过于复杂, 能性能调试带来诸多不便
比如:
- DLL, DLL初期缺少规化, 导致当覆盖或升级系统的DLL时, 经常出现冲突的情况
- JAR, 百家争鸣, 经常导致版本问题, 甚至象log4j,logback,jcf之间的纠缠
- js, 复杂的页面交互, 历史遗留问题, 经常导致loader后的几个js不兼容,而作者可能是同一人
同时也有一些版本库管理器
- APT, YUM linux上的软件包管理
- npm nodejs的软件包管理
- brew mac homebrew软件
- sublime 编辑器中的package control也算是
- maven jar包版本依赖管理
- eclipse-plugins 插件版本管理
- bundle ios.app, mac.app, 一种常用的app打包模式
- 还有很多很多
从已有的解决方案来思考下这个问题
- jar包以及java类都不会因循环依赖而导致问题, 因为依赖与运行解耦合了 考虑js.loader中的依赖, AMD因运行后才能得到依赖的module, 导致循环依赖不得不break 而CMD方案, 则提前将module设定为了{}, 少了点微不足道的功能, 但解耦合了, 从而可以将分析模块依赖与模块运行独立开来, 避免掉break
- 可以得出这样一个结论, 一个相互依赖+版本的组件库, 通常具备以下几个功能 a) 一个打包器, 通常由语言方制定好规范, 大家相互遵守 b) 一个版本管理工具, 通常会带有命令行, 可以查看树型依赖 c) 依赖的组件, 有远程仓库, 通过id, 可以通过http直接下载, 有中央仓库, 而大公司也喜欢制造自己软件仓库 d) 敲入安装命令后, 可以自行下载元信息, 分析依赖, 下载依赖, 执行初始化 e) 软件本身不参与自己的版本管理
- 版本不兼容的问题, 通常与实际情况有关, 很难有最佳实践, 向下兼容是比较靠谱的, 通常情况下, 一但不向下兼容, 通常都会在事后遇到依赖组件冲突问题, 除非完全统一升级 如果无法向下兼容, 那就另起炉灶吧, 换个名字, 换个命名空间, 换个全局变量
- 提前定义好接口规范, 小版本号bugfix, 中版本增加功能, 大版本号表示大幅重构或变更
因此:
- 在考虑是否采用版本号时, 首先要确定好, 是否有足够的精力去制造或者寻找一个合适的版本管理工具, 一个代码中央仓库, 一个有氛围的社区
- 如果没有, 就还是单版本吧, 一个稳定的核心, 每个组件都尽量只依赖于核心, 独立成单独组件, 不相互依赖, 采用简单代码冗余, 代替复杂版本管理
一句话: 要么简单, 要么复杂, 量力选择, 针对具体情况, 做出选择