dependency
dependency
PHODAL

查看标签 dependency

起先,我只是想写一篇如何提升软件质量的文章。后来在写质量文章的过程中,发现我还差一部分重要的内容没讲:依赖管理。于是,我着手准备写这篇文章,结果发现我还缺少一篇关于:依赖安全机制的文章——依赖孪生。所以,也就有了上一篇文章《依赖孪生:低成本的依赖安全方案》。 笑,为了安装好软件质量这个包,我已经陷入了依赖地狱了。 回到这篇文章,我们将介绍一些依赖管理的相关实践:从基础的依赖环境隔离到告别单体应用。 ## 1. 依赖的环境隔离 事实上,针对于不同项目、不同语言进行环境隔离,本不是这篇文章讨论的范围。但是,我们又不得不提及一些相关的内容。因为,我们总是习惯性也忘记了相关的内容。 由于不同的编程语言的包管理工具,存在对于依赖的 link 机制,所以对于它们的管理也稍有不同: - 全局统一依赖型语言的环境隔离。对于诸如 Python、Ruby 这一类脚本型语言来说,它们使用的是全局依赖,所以需要依赖于诸如 ``virtualenv`` 或者是 ``rbenv`` 为每个项目创造一个独立的运行时依赖环境。 - 项目独立的依赖隔离。对于使用 NPM 或者 Yarn 的前端开发人员来说,依赖存在于项目目录下的 ``node_modules``,自然而然地就进行了依赖隔离,但是需要对 Node.js 的版本进行限定。稍微一提,这种机制特别浪费硬盘。 - 包管理工具版本隔离。对于 Java 的 Gradle 来说,它稍有不同:统一的依赖存储路径,但是却不需要进行环境隔离,不过需要限定 Gradle 的版本。 - 其它。由于我的语言经验有限,暂时只有这些案例。 ``注``:由于经验有限,上述内容有些可能不太准确,如有有错误,欢迎指正。 总之,我们需要针对于不同类型的语言和包管理工具,采用与之匹配的有效的依赖环境隔离。 ## 2. 自建依赖创建 我们已经讨论了太多这方面的内容,这里就不详细展开了。 - 对于中大型组织来说,可以自建自己的依赖中心。 - 对于小型组织和团队来说,使用 Git 仓库也是一个不错的折中方案。 ## 3. 进行 LICENSE 扫描 对于依赖的 LICENSE 进行管理和风险识别,是依赖管理的一个重要的部分。除了常见的商用管理方案之外,我们还可以采用诸如于 Node.js 项目中的 https://github.com/mwilliamson/node-license-sniffer 或者是 https://github.com/3rd-Eden/licensing 都是一些不错的工具。 至于 LICENSE 选择的问题,永远都是 MIT 优先。 ## 4. 是否进依赖进行内联? 这是自 left-pad 事件之后,我采取的包的新策略(在我的开源项目上):对于小的软件包,直接复制源码,在项目中创建 ``third-party`` 放置相关的代码及 LICENSE。 这主要是结合了三个要素而考虑的: - 安全性 - 可迁移性 - 便利性(因人而异) 当然了内联依赖,涉及到一个版权问题——适合于代码少,不维护的项目。 ## 5. 依赖的协议隔离策略 除了内联之外,我们还要考虑的一个问题就是依赖的协议问题。 ### 策略1:再发布 当我们从 Google 上搜索代码的时候,往往会遇到代码在 ``gist``、``stackoverflow`` 或者 ``codepen`` 上,它们非常适合于我们复制到项目中使用,但是难免地可能会遇到一些版权问题。对于开源项目来说,可以直接在项目中使用,并进行标即可。而对于外部项目而言,一种最简单的方式就是二次发布这些软件包。 又或者是对于一些已经不维护的依赖包,而我们又需要,那么就只能在修改后二次发布这些软件包。 ### 策略2:二次协议 / 协议隔离层 对于 JavaScript / TypeScript 类库来说,在这方面的问题比较少,毕竟前端运行在客户端上,所以 Web 前端即『开源』。 如果真的非要使用某个开源软件,并且基于它之上修改,那么可以采取和 Android 开源协议类似的二次协议的方式。Linux 内核采用的是 GPL 协议,而 GPL 具有传染性——如果直接在 GPL 协议的类库上封装,那么只需要开源这部分的代码,因为认为我们的代码并不是衍生产品。而事实上 Free Software Foundation 动态地链接文件也产生了衍生产品,也就是说你用了 GPL 的库,你也需要开源你的代码。 为此,Android 系统在类库上采用的主要是 Apache-2.0 软件许可授权,对 GPL 进行了二次,它允许 Android 上的开发商基于 Android 的源代码进行开发而不向社区反馈。 所以,对协议进行隔离也是一个潜在可行方案,它从某种意义上将风险转移到了这一层级。 ## 6. 依赖更新机制 在日常的业务开发中,最痛苦的一件事莫过于:没有时间做技术升级,没有时间处理技术债。在这个时候,对于依赖更新这个问题,可能就会变得非常痛苦:你可能要亲眼目睹一个遗留系统的形成。所以,作为一个有责任的开发人员,你应该尽量去说服相关的人员,去做好相关的技术更新和升级。 除此,当依赖发现更新的时候,是否有相应的工具可以提供我们?一些现代化的工具,诸如于 Intellij IDEA 可以帮助我们更新依赖。也可以尝试包管理工具自带的升级命令,诸如于 NPM 中的:``npm outdated`` or ``npm outdated --parseable|wc -l``。不过大多数时候,我们可能会放弃升级——除非我们不得不升级。除此,https://david-dm.org 也是一个不错的工具——用于开源的公开 Node.js 项目。 相似的工具还有 [next-update](https://github.com/bahmutov/next-update) 是一个不错的更新工具。又或者是同一个作者写的 [next-updater](https://github.com/bahmutov/next-updater) 的工具。 ## 7. 版本选择?宽松型,还是严格型 在引入依赖的时候,我们需要稍微注意一个对于依赖的版本选择问题:到是宽松型,还是严格型。依赖的版本问题,主要会出现在**持续集成**和新成员加入项目。诸如于使用兼容发布条款,如 ~= 0.6.4,对于那些早期已经搭建了的开发来说,并不会有问题。而新的成员安装的时候,可能就变成了 0.6.5,在 API 上可能会发现一些细微的变化 。而诸如于使用 ``*`` 匹配版本的话,就更不严谨。 以 Python 语言中的 ``requirements.txt`` 为例,存在不同的描述版本的方式: ``` ~=: 兼容发布条款,如 ~= 0.6.4 等价于 0.6.* ==: 版本匹配条款 !=: 版本排除条款 <=, >=: 广泛的有序比较条款 <, >: 排除的有序比较条款 ===: 独断的比较条款 ``` 一些常见的情况如下: - 对于间断型维护的项目来说,往往选择严格型的依赖版本策略,因为大家都不想去碰了,哈哈。 - 对于长期开发的项目来说,选择宽松型的依赖版本策略,可以让项目可容易维护。 - …… ## 8. 使用依赖锁定 为了方便于在不同的开发人员之间能平稳地运行起项目,我们需要使用依赖锁定,以避免出现 DLL 地狱的问题。 > DLL 地狱(DLL Hell)指 Microsoft Windows 系统中,因为动态链接库(DLL)的版本或兼容性的问题而造成软件无法正常执行。 为此,我们需要依赖锁定配置文件,来记录已经安装的依赖的确切版本。除此,它还描述了生成的依赖树及其关系,以便于可重现安装依赖(即在后续的安装中能够生成相同的依赖树),而忽略依赖的更新。 依赖锁定配置与依赖配置的最大区别在于,依赖配置文件只描述了需要哪些依赖及期版本,而依赖锁定配置描述了依赖的子子孙孙依赖及期关系。 如我们的一部分依赖是在内部服务器,那么在安装的时候只会从内部服务器拉取相应的依赖,不会去外部环境下载。这个时候,我们所能做的是拷贝依赖,或者是删除这个文件,重新生成。与此同时,这个依赖锁定文件可以通过源码控制工具(如 git)来进行管理。 常见的锁定配置文件有,Ruby 中的 ``Gemfile.lock``,Node.js 中的 package-lock.json 或者 yarn.lock。无论你如何修改 ``package.json`` 的内容,它都会按照 ``package-lock.json`` 来安装依赖。 ## 9. 依赖代码安全检查 就目前来说,常见的有两种方式: - 商用解决方案。 - 依赖孪生机制。《依赖孪生:低成本的依赖安全方案》 笑~ ## 10. 告别大的单体架构 我的意思并不是说微服务好——不过真的很香,我的主要目的是想说:大的单体应用在依赖上存在着滞后的问题。 对于微服务来说,频繁更新的服务,必然可以做出依赖的及时更新;而对于基本不修改的服务来说,我们基本不会考虑去更新依赖。对于某一长期开发的单体应用而言,它们采用新的构架和编程语言非常困难。因为某个接口的修改,导致要修改一系列的代码,有可能相当于重写整个应用。 诸如于 Spring 框架本身一直在更新,而你正在使用的版本是 2.x,那么你可能与新版本已经不兼容。甚至于,需要维护自己版本的 Spring——出于更新漏洞的原因,你们重写了系统中的部分软件。 ## 11. == 什么是好的依赖 见下一篇文章。 参考内容:https://github.com/bahmutov/talks/blob/master/dependencies-best-practices-node.md

在阅读《零信任网络》的期间,我突然有了一个新的安全实施方案: 依赖孪生——针对于中小型 IT 组织的依赖方案。(PS:其实这只是吹吹而已,并没有那么夸张)。所以,我就顺手写了一篇文章,记录一下相关的实践和模式。

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

存档

分类

标签

作者