开源公司软件产品的复杂性和回报

发布于:2020-12-24 16:05:07

0

107

0

api django 框架 开源 salesforce 合作伙伴内容

那是2011年,我们Toopher正在构建一个复杂的身份验证API。我们的小型创业公司基于创始人Evan Grim的研究生项目,而认证API是我们的唯一产品。作为一家初创公司,我们专注于创造价值,因此我们利用现有工具,而不是从头开始构建一切。

我们用Django编写了整个产品,这是一个成熟的,包含电池的开源Python Web框架,致力于快速的应用程序开发(正是我们当时的工作!)。我们使用了Piston框架来处理API创建。这是一个不错的框架,没有什么可以满足我们的需求了。但是Piston最终被放弃为一个项目,迫使我们提出了自己的解决方案,我们做到了,我们称之为django-declarative-apis。

到这个时候,我们的小公司已经被Salesforce收购。实际上,Salesforce Authenticator应用程序是作为我们复杂的身份验证API的前端而构建的。我们意识到django-declarative-apis框架填补了Django生态系统中的空白,并希望将其开源,但遇到了两个问题。

首先,新框架已深深地嵌入到我们创建的自动两因素身份验证API中,并且将其发布到一个可以公开发布的单独程序包中将是一个挑战。

其次,尽管Salesforce制定了支持员工从事开源项目的政策,但当时并没有将先前专有代码转换为开源代码的流程。

我们想分享我们学到的东西,我们学到了两件事。首先,我们学习了如何为Django设计这样的库,以及如何将其与许多早已嵌入到应用程序中的意大利细面条逻辑解耦,以进行公共开源发行。其次,我们学习了如何通过Salesforce推出这样的开源版本,这是一个动态的地方,但也是一个很大的地方-您不仅可以获取专有代码,然后将其扔到GitHub上,然后再调用它。首先,让我们讨论一下技术挑战以及我们如何应对这些挑战。

反对意大利面条的逻辑

原始的API框架是一个非常程序化的解决方案。您从一个请求开始,然后提取参数并执行您需要做的事情,以一种方法形成响应。我们必须不断地使用新功能,而又不会破坏任何东西,最后我们得到了一堆令我们感到羞耻的意大利面条逻辑处理程序。对于单个处理程序,那里有一个非常多毛的500行方法。

它变得非常脆弱,每次不得不修改它时,我们都会感到难过。不同的行为集将基于输入参数运行,并且存在很多相互依赖关系。但是我们需要继续支持所有这种行为,因为我们有依赖于它的每个方面的客户。

关于版本2的想法已经出现了一段时间。最大的目标是使所有API处理程序都以声明方式进行编码。也就是说,可以根据代码确定处理程序的行为。您可以对代码进行静态分析,并了解所有需要了解的信息:如何调用处理程序,获得什么样的响应以及它在中间执行什么操作。

我们还希望从处理程序中的业务逻辑中抽象出HTTP请求-响应周期。在这一点上,现有的选择相当严格。对于任何处理程序,您都必须处理请求对象,并在处理程序方法中进行所需的任何数据转换,并使用与该代码的业务功能没有直接联系的逻辑对其进行污染。

我们想出了愿望清单界面。 Evan想出了一种更具进取性的前瞻性方法来编写我们的API,这启发了我们立即放弃我们考虑过的所有其他方法并全力以赴。这与我们之前看到的API处理程序的任何方式都不同。

使它与众不同的是,处理程序代码完全不知道HTTP接口。标头,编码,URL参数,所有这些东西都是通过一个类来处理的,该类将请求参数自动映射到该类中的字段。该类可能包含将请求数据转换为处理程序方法可用的数据的方法,从而确保处理程序代码仅包含业务逻辑。根据该请求,它可以提取必要的数据,收集所有依赖关系并准备响应对象。

如果请求引起任何副作用,例如发送电子邮件,则可以将其隔离到单独的任务方法中,同时保持该处理程序方法的清洁。使用附加的装饰器,可以使该task方法自动推迟运行,直到处理程序返回响应为止。通过分离所有此类内容,我们使处理程序变得更加易于维护。

框架一旦实现,就需要证明它是完整的功能。为此,我们在其中重新实现了超级多毛的500行处理程序。因为如果我们能够使该野兽在此框架中工作,那么我们将非常有信心它具有将所有API移植到该框架所需的全部功能。在快速完成一半的API(以及笨拙的野兽)之后,整个移植过程大约花费了一年的时间。

虽然最初的项目是作为身份验证器API和应用程序的一部分创建的(您可以在Apple和Google应用商店中以Salesforce Authenticator的身份看到它),但该框架是如此有用,我们决定将其拆开并使其成为一个单独的库。

第一步是将其复制并粘贴到主项目(其自己的顶级目录)中的干净模块中。杂乱无章,但是将这段代码移到其自己的模块中暴露了耦合,并向我们展示了我们需要解开哪些类型的结。我们在这个新模块中重构了所有破坏的依赖关系,然后返回到原始API并对其进行了重构以与新的修补程序一起使用。此时,我们在两个项目中都有相同的模块,因此我们可以从原始API中删除框架代码。最后一步是使新框架可用于Salesforce中的项目安装-一个真正的库,而不仅仅是一个子模块。

分享您引以为豪的东西

我们一直有野心要开源我们创建的框架。当您创建引以为傲的新颖解决方案时,让其他人使用和贡献它只能对整个软件社区有所帮助。另外,通过开源,我们可以使用一些一流的工具,例如Travis CI,并且可以更轻松地将这个框架整合到Salesforce的项目中。

但这仍然是我们待办事项列表中的低优先级项目。至少直到Demian Brecht加入该团队为止。他是我们的开源倡导者,他不仅相信以个人身份参与开源社区,而且相信回馈开源社区的公司的有形和无形利益。他活跃于Salesforce内部和外部的许多开源项目。到目前为止,django-declarative-apis已经是一个子模块,在Salesforce的许多项目中都被大量使用。我们很自然地将其开源。

但是,当我们与团队中的人们交谈时,一个共同的主题是他们喜欢开源软件,但以前从未对此做出过贡献,并且对此感到有些害羞。我们希望给他们这种机会,并帮助他们开始以有意义的方式为开源项目做出贡献。他们会与我们的客户或休闲爱好者(任何想使用和塑造它的人)一起公开开发该库。

这样,您的团队可以公开开发代码,这将为您带来巨大的好处;因为任何人都可以看到您的代码,将其添加到项目中并评论您的拉取请求,所以您有更多的责任来考虑您所做的更改。您会收到有关更周到的更改的更好的提交消息,这使您的开发过程具有自记录功能。

工程团队正在考虑将框架开源,然后我们需要与法律部门合作以实现该框架。对于他们来说,这是一个全新的情况。他们建立了一个矩阵,用于以开源形式启动一个新项目或在现有的开源项目上工作,但没有采取从安全相关产品中提取框架并公开发布代码的方式。

因为我们正在开拓新的天地,所以我们必须确保我们的i点缀成点,而t的点缀在各处。我们需要仔细检查所有代码,以确保没有任何值得我们放弃的专利。我们让产品安全人员确保我们不会无意间泄露一些简单的方法来入侵我们。这是同类项目中的第一个项目,所以花了大约六个月的时间,但是由于我们经历了整个项目并弄清了问题,因此,Salesforce的现有项目的开源采购现在变得更加精简(而且很平常)。这些天来,我们有一个正式的开源采购流程,该流程有时是即时的,但很少需要4-6周以上的时间!因此,我们现在每年在公司范围内公开采购数十个项目。

对于我们而言,将其开源是有实际好处的,而与社区相关或外部无关。内在的好处围绕着我们的部署流程而展开。我们在Heroku上部署了我们的API,这使安装开源和公共存储库中的依赖关系变得容易。作为Salesforce内部的一个封闭库,我们不得不跳很多圈来向项目添加django-declarative-api。箍之一的一个示例是提供依赖关系,即将库的整个源树镜像到依赖项目中,而不是简单地在配置文件中指定依赖关系和版本。当它变成开源时,突然之间,我们不再需要消耗封闭源代码依赖项,也没有其他任何障碍。

除了使我们的工作流程更容易之外,使项目开源还使我们能够使用某些最佳工具,例如Travis CI。这些工具周围有庞大的社区,因为它们本身就是开源的。能够参与这些社区并为社区做出贡献真是太好了。如果开源,意味着我们可以在django-declarative-apis周围找到一些社区,那就太好了。但是,没有任何这些都是值得的。

我们为这个图书馆感到骄傲,并很高兴能够与社区分享。当您在django-declarative-apis中实现具有相当程度的复杂性的新端点时,您会非常感谢它在很大程度上保护了您免于编写不良代码。我们接受复杂性作为我们的权衡;但是如果它允许我们在每天实施的处理程序中表达更多的简单性,我们愿意接受框架中的更多复杂性。

最后,这两个部分都是学习经验。我们造成了很多技术债务,与尝试进行零散维修相比,重新开始比以前更能解决问题。我们还发现,Salesforce的同僚很高兴地解释了为何存在法律法规,这很有帮助。开源过程花费了更长的时间。