为什么要为内部应用程序开发内部库?


10

我很难理解为什么您应该开发内部库以专门用于开发内部应用程序。我很感激,如果我想使用组织外部某人编写的软件,那么他们可以向我发送其头文件以及.a或.so文件,并且我可以将其链接到我的项目(假设它们在同一环境中编译) 。

但是,为什么当我可以访问头文件和实现文件并将它们仅包含在我的源代码树中并一起编译时,为什么要开发一个内部库以链接到内部应用程序呢?

换句话说:如果编写了一些源代码,您如何决定应将其编译为二进制库并链接到您的应用程序,还是仅将其包含在项目的源文件中并定期进行编译?

当我在每个项目中说“包含”文件时,并不是要复制每个文件并将其粘贴到当前正在开发的项目的源代码树中。我的意思是开发一些包含公共源代码的目录/库(与任何项目分开),这些源代码可以以通常的方式包含在项目文件中,即#include。

ps我在这里谈论的是针对多个桌面应用程序的c / c ++开发。


Answers:


25

创建库和共享库(在.dll或.so文件中)的原因很多,甚至出于内部使用:

  1. 跨项目重复使用更清洁
  2. 责任分离-您的部分代码可能更适合不同的开发人员或团队
  3. 您可以受益于其他团队所做的库改进,而不必查找特定的代码
  4. 更快的构建时间,如果库是稳定的,则不需要重新构建。
  5. 磁盘空间-您只能在项目中包含库和标头
  6. 如果您使用共享库,即使有多个程序正在使用它,也可以通过仅将一个副本加载到RAM中来节省内存。
  7. 通常,您最终会获得更好的库文档和测试
  8. 进行更干净的设计和代码思考,以将事物结构化为库,应该会导致每个库中具有相关的功能组,并且您倾向于将通用代码从应用程序中的应用程序细节中分离到库
  9. 如果库中拥有专有算法,则可以限制对源的访问,例如,不允许承包商或外包团队获取源。
  10. 可能将库代码置于与最初作为应用程序一部分编写的应用程序不同的许可下,一些公司甚至以开放库而闻名,它们引以为荣- 在开放源代码社区中赢得了广泛的赞誉,有时还进行了重大改进背部。

一些公司甚至有会计惯例,创建图书馆的项目在每次重用时都会得到一定的报销。


1
或者,在第9点的变体中,您可以使用与主要应用程序代码不同的许可来发布该库。
Michael Borgwardt

@MichaelBorgwardt-提示点10以上。
史蒂夫·巴恩斯

另外,将一些代码作为单独的库有助于避免编程时的快捷方式,例如“我将在此处添加此额外的参数..”,并有助于找到实现所需功能的更好方法。
Valdas

11

一些其他可能的原因可能适用于较大的,不重要的项目:

  • 编译时间:具有数千个文件,数千个类,函数等的庞大的整体C ++项目可能需要很长的编译时间(如果每次更改几行代码都想重新编译,这会损害生产率)。静态链接库和动态链接库是独立编译的,如果它们的源未更改,则无需重新编译。

  • 逻辑上分离的模块或子系统的分离:如果将不同功能区域放置在分离的模块中,则大型系统通常更易于管理,并且开发人员不必面对包含数千个文件/类的巨大文件夹/项目进行搜索。

  • 开发人员/团队之间的界限:如果可以让每个开发人员都在不同的模块中工作,则同时构建单独的新功能的开发人员可以减少合并冲突的可能性。

  • 不得发布到实时环境中的代码:例如,用于开发人员测试的单元测试库或“模拟”库,以替代实时系统组件(硬件,API,远程系统,数据库等)

  • 编译器标志:如果发现自己处于与某些第三方的API集成的非常不幸的境地,而第三方的API需要一个奇怪的编译器标志,则该库可以是位于第三方API与应用程序其余部分之间的“净化层”。

  • 可选功能/优化:在大型系统中,如果某些动态链接的模块对应用程序的基本功能不是至关重要的,则应用程序可能需要等待某些动态链接的模块才能在运行时加载到内存中。


通常,许多内部项目通常都是小型微型应用程序,无法从拆分为单独的库中受益。如果您正在作为一个单独的开发人员来从事一个很小的项目,那么您可能不必担心将代码拆分到库中(但...)。不要忘记YAGNI原则


3
@downvoter-您能解释一下拒绝投票的原因吗?对答案的反馈对于提高每个人的网站质量非常有用。
本·科特雷尔

4

您最初提出的问题可能会对其他大多数答案造成误解。由于您不打算跨项目复制现有代码,而是要包含来自不同项目的相同源文件作为引用,因此任何“重复代码”自变量以及提供的许多其他自变量都变得毫无意义。

请注意,有时这是(并非总是如此)一种明智的技术。实际上,当您将要在项目中重用的所有源文件放在一个单独的include文件夹中时,您已经已经建立了一个库-源代码库,而不是二进制库。尤其是在C ++中,当使用模板创建通用库时,只有标头的lib就很常见,它只需要一个简单的include,而无需单独的链接准备。

所以我想您的真正问题是-什么时候构建源代码库,或者什么时候更喜欢预编译的二进制库?在这个站点的较早答案中,我讨论了仅标头库的优缺点,也许对您有所帮助。源代码库的主要优点是,它们不需要与使用它们的应用程序使用相同的运行时和/或兼容的编译器/链接器标志进行编译。缺点是增加了编译时间,并且要求提供对源代码的访问权限(显然,这对您所考虑的“内部”项目不是问题)。


的确,我的意思是说一个源代码库对于多个项目是通用的,您可以在其中通过典型的#include指令引用所需的文件-在您说完它之前,我不知道它的用语,我将对其进行编辑。现在提问。您的链接答案也非常有帮助。
安德鲁·穆塔格

@AndrewMurtagh:你这么快就接受MichaelBorgwardt的回答的事实令我惊讶,因为他写的东西似乎是对他还是我的误解。
布朗

好吧,他确实阐明了我最初的困惑,即我何时将将多个项目通用的代码分组到一个程序包中(无论是在二进制库还是在源代码库中),但是我同意,我是在说只有一个源目录可以在项目之间共享的代码,而不需要将每个文件复制并粘贴到每个项目中。
安德鲁·穆塔格

2

我同意其他评论者的看法,即他们不应重复代码。但是,就您而言,您(或您与之共事的人)似乎正在为未在其他地方重复的代码创建库。

在这种情况下,我警告不要过早泛化。很多时候,人们觉得一段代码可以重用。但是,在不了解第二个用例将如何使用此类代码的详细信息的情况下,很容易将额外的时间花费在“可重用性”功能上,而这些功能在其他情况下实际上将是无用的,或者会做出错误的假设。第二种情况。

为一个用例编写一个“库”可能会变成一项非常昂贵的工作,而且没有任何回报-我已经被这个问题困扰了好几次。

费用示例:

  1. 考虑“一般”用例的时间/精力
  2. 使“库”可分配给您的“客户”(您自己的代码)所花费的时间
  3. 即使不完全匹配下一个用例,未来使用“库”的压力

我的一般规则是:除非我在至少两个需要代码的地方,否则不要将代码放入库中。


2
我已经看到一些开发人员使用几乎完全相同的原因,为什么他们的代码都在一个> 20k的行源文件中。当结合古怪的命名和较差的注释时,您很快就会拥有比重写要快得多的代码。
史蒂夫·巴恩斯

要点:我当然不会反对编写可维护的,可读的代码。单独的文件,命名良好的方法/类和包结构都是可维护性的重要组成部分。我的意思是,当“库”只有一个用例时,编写和分发库的成本就会很高。
山姆

1
相反,我并不是说您在每种情况下都必须打包和分发一个库,只是好像您的代码有一天会变成一个库一样进行编写和构建通常要花点力气,即使代码永远不会变成代码,也常常会带来很多好处。作为图书馆分发。
史蒂夫·巴恩斯

1

当我有权访问头文件和实现文件,并且可以将它们包括在源代码树中并一起编译时,为什么应该开发一个内部库以链接到内部应用程序?

因为如果“仅将它们包括在我的源代码树中”,那么您就是在复制代码

这样做的问题是,您将不会从复制代码的项目中获得任何改进(包括严重的错误修正),也不会从您所做的任何改进中受益。

您可能会认为可以通过简单地将代码的最新版本定期复制到源代码树中来解决此问题,甚至可以通过使用git中的子模块或类似的方式自动将其复制。但是由于不兼容的API更改,您将不断地中断构建。另一方面,库具有“官方”公共API,开发人员知道,如果不与客户协调,便无法更改该库。

最后,可能有技术原因-是否可能需要将部分代码保留为库,以便可以按需加载或什至按需加载和卸载,从而在不需要功能时减少内存使用?


1
因此,据我所知,将某些代码放入库中的主要原因是何时要在不同项目中使用它(即使它们都是内部开发的),以便不重复,更新,维护该代码。分别?而且,如果您只打算开发一个项目,则无需将某些内容放入库中(除非您打算以后在其他项目中使用它)。
安德鲁·穆塔格

@AndrewMurtagh:是的,这正是我所说的。尽管也可能有技术原因;我对C / C ++开发不是很熟悉-也许必须保留部分代码作为库,以便可以选择加载它,甚至可以根据需要加载和卸载它,从而在不需要功能时减少内存使用量?
Michael Borgwardt

我相信可以通过共享库来实现。感谢您的澄清,我将您的回答标记为已接受。
安德鲁·穆塔格

在过去的十年中,几乎每个VCS都支持外部引用或子模块。这消除了重复的代码和错误修正问题。如果您仍然认为它们是有效的问题,则可能会提供更多信息,说明为什么这些方法不是可行的解决方案。
西里西亚人

在维护中也要考虑。1)lib可以独立和并行维护。2)代码易于替换。3)小型代码库对于小型团队更易于管理,并且每个人都易于理解。4)如果上市时间很关键,那么您将更希望拥有更快的构建。libs中的代码是您不需要在管道(IMO)中反复编译的代码。5)它是可靠的可重用代码...您做到了;-)
Laiv

1

我想详细说明您的解决方案从长远来看的成本。

显然,将库添加到项目中会产生一些开销,如果这是第一次,那么以上都是:系统必须更改工作流,有时甚至是基础结构,某些团队成员可能不喜欢它(一开始)。因此,您的解决方案的优势显而易见,因为它现在的成本更低。

但是,随着项目的增长,“伪库”的成本也会增加。假设您有一个“伪库” A,供应用程序和单元测试人员使用。每次向中添加cpp时A,都必须将其添加到两个项目中,否则它们将不会链接。

如果您的“伪库”被另一个“伪库”使用B怎么办?您必须在多个项目中添加新的cpp。如果B切换到另一个库?您A只需要根据从所有项目中删除cpps即可B

如果使用真正的图书馆,那么所有这些都是免费的。因此,问题是,需要多少cpps才能证明迁移到真实库是合理的?

但是,等等,还有更多的抵押品:开发人员不喜欢这种愚蠢的工作,即寻找所有需要新cpp的项目,并将他/她的代码/类添加到已经存在的文件中的某处,这并不是一件好事。从长远来看。

因此,使用“伪库”可以成为破坏整体项目的第一步,但是您不应等待太久就可以使其成为一个真正的库,以能够利用其优势。


0

但是,为什么当我可以访问头文件和实现文件并将它们仅包含在我的源代码树中并一起编译时,为什么要开发一个内部库以链接到内部应用程序呢?

如果该库仅由一个应用程序使用过,那么您可能不需要将其作为单独的库。

如果库由三千五百份申请,那么你绝对需要它作为一个单独的库。

如果库中有错误并且您需要修复该怎么办?还是随之而来的一些法规变更意味着您必须改变图书馆的工作方式?

如果在单独的库中,则可以(可能)修复该库,对其进行重新测试并重新部署,并且每个应用程序都可以从该修复中受益。

如果它只是在源代码这是“本地”每个应用程序,那么你必须改变,重新构建,重新测试和每一个应用程序重新部署独立。这是一个很大更大(即更昂贵)的运动。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.