当我考虑静态库文件夹和程序包管理器的优缺点时,我觉得库文件夹是一种更好的方法。
我看到的带有库文件夹的优点:
- 无需外部工具即可管理软件包。
- 无需互联网连接即可构建。
- 更快的构建(无需软件包检查)。
- 更简单的环境(所需知识更少)。
我在套件管理员中看到的优点:
- 帮助处理复杂的依赖关系树(可以通过下载依赖关系及其所有依赖关系进行管理)。
- 帮助检查是否有可用的新版本。
业界似乎已经决定对当今构建的几乎所有产品都遵循包管理器的路径。那么,我想念什么?
当我考虑静态库文件夹和程序包管理器的优缺点时,我觉得库文件夹是一种更好的方法。
我看到的带有库文件夹的优点:
我在套件管理员中看到的优点:
业界似乎已经决定对当今构建的几乎所有产品都遵循包管理器的路径。那么,我想念什么?
Answers:
其他答案缺少的重要一点:
使用软件包管理器意味着具有一个配置,该配置指示您正在使用的库版本,并确保配置信息实际上是正确的。
如果您了解以下情况,那么了解使用的库和版本是非常重要的:
另外,当您实际进行更新时,程序包管理器(通常)确保按需更新所有传递依赖项。
而使用lib
文件夹,您只有一堆(可能是二进制文件,并且可能已修改)文件,并且您必须猜测它们来自何处以及它们是什么版本(或信任某些自述文件,该文件可能正确也可能不正确) )。
解决您的其他问题:
无需外部工具即可管理软件包。
没错,但是a)作为软件开发人员,无论如何,您都需要安装大量工具,因此通常并不重要; b)在任何给定的领域(Maven / Gradle for Java, npm for JS / TypeScript等),因此您不需要安装数十个。
无需互联网连接即可构建。
我知道的所有软件包管理器都必须在下载所需的依赖项后脱机工作(下载项目本身后立即发生)。
更快的构建(无需软件包检查)。
可能是正确的,但脱机软件包检查似乎不太可能花费大量时间(它只是比较一些版本号)。一个在线检查可能需要一段时间,但如果需要的话,可以关闭(如果它甚至在默认情况下-的Maven例如永不检查更新的发行版本)。
更简单的环境(所需知识更少)。
是的,但是如上所述,lib
文件夹也需要知识。而且,如上所述,您可能只会使用少数几个不同的软件包管理器,您已经知道了。
从小规模开发转向大型工作后,lib文件夹的优点迅速消失。
例如,不需要外部工具的“好处”被手动管理依赖项所需的工作所压倒,因此该工具将成为您(从多个角度而言)。
包管理器不需要Internet连接。您可以使用本地存储库。
更快的构建可能是正确的,但几乎不应该决定是否使用软件包管理器。我们毕竟不是在谈论差异的大小,这也取决于您的配置。您可以使用软件包管理器轻松进行缓慢的构建,但这基本上是破坏活动。
更简单的环境(需要更少的知识)?同样,在小规模开发中绝对有可能。您可能可以完全掌握项目,直到所使用的几个库中的每一个。添加一个简单的makefile /其他构建脚本,您将获得一个完整的软件包。
但这并不能使环境更简单,它只能在简单的环境中工作。在大规模开发中,您会很高兴使用标准工具而不是自定义解决方案。毕竟,您只需要学习一次(当打包管理器du jour被新的好东西所取代时,您也必须学习它)。
blah install libfoo
。然后,将其乘以5个依赖项。
您缺少了包管理器的许多优点。
您还夸大了“好处”的价值。
无需外部工具即可管理软件包。
“外部”要做什么?我将NuGet可执行文件检入到存储库中。这是我可以签入的唯一二进制文件,因为它很小,意味着我不需要签入任何其他二进制文件。
pip不会在这方面造成问题,因为它现在默认情况下已与Python捆绑在一起,并且不兼容和向后不兼容的更改极为罕见。无论如何,如果没有在项目外部安装Python,就不会开发Python代码。
当它们被广泛采用时,程序包管理器趋向于非常稳定。对于大多数项目,如果没有某种在全球范围内安装的工具,您将无法摆脱,而单个软件包管理器的需求就非常轻。通常,与安装语言运行库相比,它并不麻烦。
无需互联网连接即可构建。
没有网络连接,我无法连接到数据库。如果数据库是Amazon托管的,无论如何我都需要完整的Internet连接。我需要Internet连接才能通过源代码控制推送和拉取更改。如果没有某种网络连接,构建服务器也无法签出要构建的代码。没有电子邮件,您就无法发送或接收电子邮件。如果没有一个库,您将无法下载将它们放入lib文件夹中!在没有Internet连接的情况下进行永久开发实际上是闻所未闻的。在极少数必要的情况下,您可以通过将软件包下载到软件包管理器可以使用的位置来解决此问题。(我知道NuGet和pip很高兴从一个简单的文件夹或网络驱动器中拉出;我怀疑大多数其他人也可以。)
更快的构建(无需软件包检查)。
在自动构建过程中需要30秒,在本地开发人员构建过程中需要5秒,这是我上面概述的优点的一个很好的折衷方案。与收益解决的问题相比,这些琐碎的时间框架通常甚至都不值得考虑。
更简单的环境(所需知识更少)。
针对包管理的一个工具没有对库管理是不是一个真正的公平的比较,反正。没有该工具,您必须了解项目正在使用的任何自定义过程管理其库。这意味着您永远不确定您现有的知识是否适用于您所采用的任何新项目。您必须处理某人想出的任何大杂烩方法,或者自己动手制作。那可能是包含所有库的目录,或者可能更奇怪。也许是为了避免检入库,有人将它们全部放到了网络驱动器上,唯一的版本指示符是文件夹名称。那或全局安装真的更好吗?相比之下,包管理器为您提供了一个干净的约定,该约定将适用于您遇到的大多数项目。
共同的主题是它们不仅在项目内部甚至在整个项目中都提供一致性,文档和功能。这简化了每个人的生活。
最近,我们将产品从使用手动下载的库转换为使用Nuget进行自动软件包管理,我可以说使用软件包管理器有很多好处。
我们的产品在27个C#项目中实施,相对于今天的标准而言,这个规模还很小。我们的某些第三方依赖项具有数十个程序集。
在Nuget之前,如果我想将所有依赖项更新到最新版本,则必须:
有27个项目和数十个依赖程序集,此过程非常容易出错,可能需要几个小时。
现在我们已经更新为使用Nuget,这一切都由一个命令完成。
无需外部工具即可管理软件包
那不是很重要吗?如果使用软件包管理器,则不需要lib文件夹。我也不必自己管理软件包。
无需互联网连接即可构建
除了今天在开发时没有互联网连接的情况很少见(也许在运输过程中除外)之外,体面的软件包管理器不要求您必须具有最新版本才能构建应用程序。它可能会抱怨,但是没有理由不使用已经安装的版本进行构建
更快的构建(无需软件包检查)
那是一个极小的边际加速,但可以说是正确的。
更简单的环境(所需知识更少)
如今,大多数软件包管理器是如此简单,以至于不值得尝试通过这些方法解决它们。如果您愿意,甚至还有视觉客户。实际上,他们隐藏了许多正在发生的小问题。
包管理器还允许您在不同项目之间共享这些包。如果我的5个项目使用相同版本的Boost,则无需为每个项目重复此步骤。对于您所说的复杂的依赖关系树尤其如此。
使用lib文件夹,您只能管理该项目的软件包,而软件包管理器允许您使用单个工具在整个开发环境中执行此操作。
只是使用库(lib目录)和使用它们来维护元信息 (包管理器)之间是有区别的。这样的元信息涉及版本号,库之间的(传递)依赖性等。
对DLL地狱,库兼容性,java模块系统,OSGi等的讨论至少应该足以说服某种形式的依赖管理形式。
另外,还有一个共享(本地)存储库的好处,因此几个项目不需要维护导入的库的副本。如果一个项目有20个子模块,则其中一些模块具有40个奇数依赖项。
在某些情况下,可能需要lib文件夹,例如,在处理过时的库(不再维护/可用的版本),库的本地修改版本,...
但是对于其他所有方面,就像开发人员承担了程序包管理器的角色:
恕我直言,它所需要的知识较少,因为您必须了解外部工具的用法,而无需了解库(即依赖项)。
共享库被视为90年代Unix和Windows系统的一项进步的一个主要原因是,当加载使用同一组库的多个程序时,它们如何降低RAM使用率。仅需要为每个确切的库和该库的版本分配一次代码空间,剩下的每个实例的唯一内存使用情况是静态变量。
许多操作系统以依赖于unix mmap()api之类的机制的方式来实现共享库-这意味着一个库不仅需要完全相同的版本,而且实际上需要完全相同的FILE。要完全利用附带自己的库集的程序,这根本是不可能的。
与90年代相比,鉴于内存便宜得多,并且库版本需要更多的多样性,因此这种说法在今天没有太大的意义。