你是否鄙视你的客户?你是否希望他们都消失?当你与客户互动时,你是否默默幻想他们转用你竞争对手的产品?简而言之,你讨厌你的客户吗?
也许你应该尝试使用你公司的外部 API 来表达你的鄙视。什么?你该怎么做?
在本文中,我记录了一些行业最佳实践,旨在向客户展示你有多么讨厌他们。所有这些都易于实施。见鬼,你的公司可能已经在做很多这些事情了。
你为什么要使用你公司的 API 来表达你的 ненависть 呢?我认为答案很简单:客户都是混蛋。
可恶的客户!总是使用我们的服务!为了报价而打扰我们的销售人员!通过给我们寄钱来为应收账款部门制造更多工作。因为诸如“文档是错误的”、“此功能已损坏”或“你的产品害死了我的猫”之类的愚蠢原因而需要客户支持。
看到了吗?混蛋。
年长的读者可能会怀念过去的美好时光,那时真正的垄断企业会假装爱他们的客户。现在我们都在为那些不承认自己是垄断企业但实际上讨厌客户的公司工作。哎,时代变了!
没有 API 是一个好的开始。这也是所有技巧中所需精力最少的。你所要做的就是考虑添加 API,然后不去做。
API 到底有什么用?主要是它允许客户实现你没有想到的功能。“听着,伙计,如果我们没有想到这个功能,它就不可能非常好。我们雇佣最优秀和最聪明的人整天思考新功能而不去实现它们。别来插手他们的地盘。”
API 还允许客户更多地使用你的产品。如果他们必须点击、点击、点击才能使用你的产品,他们只会少量使用。如果存在 API,他们可以自动化他们对你产品的使用,这将让他们更多地使用它。他们可以为他们的整个公司自动化配置。他们可以基于你的 API 构建全新的应用程序。想想他们可以通过 API 消耗多少你的产品。
真是太粗鲁了!如果他们更多地使用你的产品,你将不得不购买更多的服务器,花费更多的时间兑现他们的支票,并且,天哪,也许开始举办会议,人们在会议上使用诸如杠杆、黑客马拉松和粉笔讨论之类的术语。会议?真恶心。
好吧,你输掉了这场战斗,你的公司无论如何都想构建一个 API。至少你可以通过要求复杂的注册流程来稍微踩下刹车。自助服务入职是享乐主义的,可能会导致跳舞。
有多种方法可以使客户的入职过程变得艰巨。一些公司要求你开工单或与真人交谈。这将使任何内向的开发人员在使用你的 API 之前三思而后行。
一些公司希望你填写申请表才能编写应用程序。让人乞求使用你的产品是阻止新用户的好方法。
为了获得最佳效果,此类表格上的问题应由以前曾在中央情报局担任审讯员的人员编写:你为什么要使用此 API?你的应用程序将做什么?12 日晚上你在哪里?你母亲的娘家姓是什么,你能证明她真的是你母亲吗?
我曾经填写过这样一份表格,要求我描述我计划编写的应用程序。六个月后,一支由审计员组成的特警队出现在我家,武器闪耀,要求我向他们展示我的代码。他们想验证我是否撒谎。如果我的应用程序与我的申请不符,那么我可能会被送进应用程序监狱。
好吧,这不是一个真实的故事。但是,我确实在表格上看到过这个问题。可悲的是,我当时并没有想到特定的应用程序。我打算探索 API 并编写一些简单的基于 Python 的实用程序来自动化一些日常任务。但是,我不想解释所有这些,因为担心我的答案对于任何评判我的申请的人来说都不够好。在恐慌中,我只是将我的应用程序描述为“深紫色,带有白色高光”。几周后,我的申请获得批准。到目前为止,还没有任何审计员特警队访问过我,但作为预防措施,从那时起,我的代码编辑器就以深紫色为主题,带有白色高光。
可悲的是,一些公司不明白如何使注册变得困难。他们要么使流程完全自助服务,要么根本不需要任何类型的注册流程。他们什么时候才能学会呢?
另一种让客户打包走人的方法是对你的 API 收取高昂的费用。
还记得移动电话公司为一条 2 美元的数据线收取 100 美元吗?为什么 API 不能像那样?你有潜力对任何胆敢想有效利用你的产品的人施加附加费。不要浪费这个机会!
对你的服务收费是正常的,或者只在“企业版”中包含 API 访问权限。事实上,这是一种阻止垃圾邮件发送者或其他滥用服务的人的好方法。
但这不是我在这里谈论的。我的意思是,你应该对 API 收取很多额外的费用。很多。钱。
将其作为一种收入来源,而不是鼓励人们使用你的产品的方式。使 API 访问变得非常昂贵,以至于销售部门认为 API 代表额外的利润激励。
这对于本地部署软件来说更容易。在那儿,SDK 可以单独出售,也许可以使用另一个未公开宣传的 SKU。需要管理层批准、教皇的祝福和你母亲的便条。
没有什么比使你的 API 文档对搜索引擎不可见更能说明“我们实际上不希望你使用我们的 API”了。几十年前的“构建、运行、调试”周期已被“运行、崩溃、谷歌、修复”所取代。如果你的 API 文档没有出现在搜索引擎中,你就把你的客户送回了旧时代。
幸运的是,这可以很容易地通过将文档放在登录屏幕后面来完成。如果谷歌无法抓取它,它就无法索引它。在谷歌上搜索关于你的 API 的答案将是不可能的。
要求某种注册或登录才能访问你的 API 文档,还可以防止你的竞争对手检查你的 API 并从中学习。没有竞争对手会想到使用他们的家庭住址注册,或者从朋友那里分享密码,对吧?绝不会。他们没有那么聪明。这绝不可能发生。你当然永远不会这样做,那么他们为什么要这样做呢?
如果你的管理层拒绝将文档隐藏在登录后面,请考虑将你的文档制作成 PDF 文件。这几乎同样令人沮丧。大多数搜索引擎都可以窥探 PDF,但如果你打印文档并将每一页扫描成位图,则无法窥探。如果搜索引擎 OCR 这样的文档,只需重新格式化你的文本为列,或者在扫描时倾斜文档。坚强点,年轻的士兵!只需一点点努力和大量的勇气,你就可以领先于任何想要轻松访问你的文档的人一步。
许多 API 使用 JSON:API (jsonapi.org) 或 JSON-RPC (jsonrpc.org)。它们是轻量级的,易于使用,并且易于调试。
为什么会有人这样做?
调试很无聊。你难道不想吸引那些第一次尝试就编写无错误代码的客户吗?
为了真正表达你对客户的鄙视,请使用专有协议,以便语言支持仅限于你提供的客户端库,最好是作为永远不会更新的二进制 blob。如果你仔细设计它,专有协议也可能难以理解且无法调试。
或者,你可以使用 SOAP(简单对象访问协议)。根据维基百科,SOAP“可能很臃肿且过于冗长,使其带宽饥渴且速度缓慢。它也基于 XML,使其解析和操作成本高昂——尤其是在移动或嵌入式客户端上”(https://en.wikipedia.org/wiki/SOAPjr)。听起来像是双赢!
我最喜欢的表达对客户鄙视的方式之一是每次只允许一个 API 密钥。任何你可以做的事情,让客户的操作充满辛劳和认知负荷,都表明“我不在乎你”。
API 密钥基本上是一个密码,用于识别和验证客户。你的电子邮件帐户只有一个密码;你为什么需要不止一个?那会很奇怪,对吧?
最终,客户将需要更改或“轮换”他们的 API 密钥。也许它泄露了。也许一名员工离开了公司并拥有密钥的副本。也许他们只是需要每年轮换密钥作为其安全策略的一部分。
这是最搞笑的部分。如果你每次只允许一个 API 密钥,你就创造了一个两难境地。客户无法在服务器上更改 API 密钥,因为客户端将失去访问权限,直到它们也被更新为止。他们不能先更改客户端,因为服务器还不知道新的 API 密钥。如果存在多个客户端,那么你基本上是在期望你的客户在完全相同的时间闪断所有客户端。基本物理学表明这不可能发生。即使它可能发生,也没有办法金丝雀测试新密钥;你在没有人期望的地方增加了部署风险和复杂性。
他们说伟大喜剧的秘诀是时机。想象一下,一个客户使用你的产品一年后才意识到密钥轮换在逻辑上是不可能的,这是多么滑稽。惊喜!
滑稽?还是鄙视。随便吧。
一些公司不了解喜剧,或者如何表达对客户的鄙视。他们允许客户在服务器上添加新密钥,逐步将新密钥推广到所有客户端,并在沿途进行测试,然后停用旧密钥。真恶心!
随着你的 API 的发展,API 和文档可能会失去同步。没有什么比构建一个鼓励这种错误的系统更能说明“我不在乎我的用户”了。
或者你可以追求三连冠:API 与文档不同步,而文档又与你提供的客户端库不同步。
当然,有一些系统(例如 Swagger (https://swagger.org.cn/tools/open-source/) 和 gRPC (http://www.grpc.io))让你在一个地方定义 API 及其文档,然后自动生成文档、服务器存根、多种语言的客户端 SDK 绑定等等。但是,一次完成工作并让计算机免费生成你所需的所有下游工件有什么乐趣呢?一致性是为傻瓜准备的。
将基础设施视为代码 (IaC) 的能力正在成为运营团队的首要任务。它不仅使运营更轻松、更可测试和更可靠,而且还为 SOC2(服务组织控制)和 PCI(支付卡行业)等要求的安全合规最佳实践铺平了道路。
一些公司浪费时间让客户更容易做到这一点。他们为从 Terraform、Ansible、Chef、Puppet 和类似系统访问其服务提供官方支持的模块。他们使他们的客户端软件易于使用,方法是托管多个 Linux 发行版的存储库,并为在 Windows 上轻松安装提供 Chocolatey 源。
忽略所有这些技术并希望开源社区会提供要简单得多。是的,这可能会导致令人困惑的不兼容选项阵列,但你可以宣扬“用户选择”的好处。
我把最书呆子的技巧留到了最后。
如果多次执行操作与执行一次操作产生相同的结果,则该操作是幂等的。
假设有一个 API 调用可以创建虚拟机 (VM)。如果此 API 调用是幂等的,则我们第一次调用它时会创建 VM。第二次调用它时,系统检测到 VM 已经存在,并且只是返回而不出错。如果此 API 调用是非幂等的,则调用它 10 次将导致创建 10 个 VM。(注意:幂等的反义词不是强大的。)
同样,幂等的删除调用将删除对象;后续调用将悄悄地不执行任何操作并返回成功状态代码。如果调用是非幂等的,则第二次调用将返回“未找到”错误,这将使开发人员感到困惑,并可能使他们质疑存在的意义。
为什么会有人多次进行相同的 API 调用?重试。在处理 RPC(远程过程调用)时,响应可能是成功、失败或根本没有回复。如果你没有收到服务器的回复,则必须重试请求。
使用幂等协议,你可以简单地重新发送请求。使用非幂等协议,每个操作之后都必须有代码来发现当前状态并执行正确的操作以进行恢复。将所有恢复逻辑放在客户端中是一种分层违规行为。
在 VM 示例中,你必须查询清单并查看你要求创建的 VM 是否存在。如果它存在,你必须确保它已正确创建或处于良好状态。如果它处于不良状态,你修复它或删除它并重新开始。潜在条件和边缘情况的列表还在不断增加。
这是一个简单的例子。从其他 API 调用中恢复可能更加复杂。恢复失败的尝试也可能失败。现在你面临着一个无限递归的失败世界、失败的恢复尝试等等。乍一看看起来正常的代码最终会创建零个 VM,或三个 VM,或更多。对于多个并发客户端,你必须处理时序、锁定问题、交叉消息和 heisenbug 巢穴。
将此逻辑放在客户端库中可确保客户端需要更频繁的更新。要求用户实现恢复逻辑是令人愉悦的邪恶:他们甚至如何知道他们应该实现什么?
当 API 是幂等的时候,这些问题会减少或消除。
为什么不简单地使用更可靠的网络?哦,那真是太可爱了。网络永远不可靠。它们不可能可靠。认为网络是可靠的是分布式计算的第一个谬论 (https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing)。
如果网络不可靠,那么网络 API 本身也必然不可靠。请求可能会在发送到服务器的途中丢失并且永远不会执行。执行可能已完成,但返回给我们的回复丢失了。服务器可能会在操作期间重启。客户端可能会在发送请求、等待请求或接收请求后但在本地状态存储在稳定存储上之前重启。这么多边缘情况!
在分布式计算中,一切都可能失败。如果你讨厌你的客户,你可以确保处理失败是繁琐的、容易出错的,而且完全不可能 100% 正确。客户将始终在修复边缘案例而不是做有成效的工作。
不要破坏乐趣。使用非幂等 API 来表达你对客户的鄙视。
表 1 总结了这些技巧,以及公司可能意外地为其 API 客户提供良好服务的方式。
技巧 | 以鄙视对待客户 | 向客户表达爱意 |
---|---|---|
1 | 不要有 API | 拥有 API |
2 | 使注册变得困难,用户必须证明他们的请求是合理的 | 自助服务入职 |
3 | API 访问特权的过高费用 | 免费或作为“企业级”软件包的一部分启用 API 访问 |
4 | API 文档在登录页面之后或以其他方式从搜索引擎隐藏 | API 文档可自由访问并被公共搜索引擎引用 |
5 | 使用专有或糟糕的协议 | 使用行业标准协议,例如 JSON:API 或 gRPC (https://grpc.org.cn) |
6 | 只允许一个 API 密钥 | 为每次轮换允许多个 API 密钥 |
7 | 通过手动维护文档来考验命运 | 使用 Swagger 或 gRPC 等自动化系统使文档与代码保持同步 |
8 | 忽略基础设施即代码 (IaC) 革命 | 将 IaC 作为首要任务:为 Terraform、Chef、Puppet、Chocolatey 和类似系统提供官方支持的模块 |
9 | 尽可能将 API 设计为非幂等的 | 尽可能将 API 设计为幂等的 |
表 1 使用 API 对待或反对客户的技巧
你的同事可能会抵制其中一些技巧。你如何让他们加入?
你可以让他们阅读本文,但这可能会适得其反。如果错误的人阅读了它,他或她可能会反击并做相反的事情。
如果发生这种情况,你最终可能会得到一个很棒的 API,它易于上手、易于使用、拥有易于访问的出色文档,并帮助人们编写第一次和每次都能正常工作的代码。
本文以玩笑的方式写成,旨在说明一个观点。尽管一些公司确实做了这里列出的坏事,但他们这样做并不是为了伤害客户。以我的经验,工程师们以做好工作并以制作精良的系统给客户留下深刻印象而自豪。我相信,当公司做本文中的那些不正当的事情时,是出于无知、缺乏资源或不可能完成的期限。
幸运的是,在某些情况下,好的做法比坏的做法更容易实施。创建身份验证系统以限制对文档的访问比使文档可以自由访问更困难。将所有文档放在一个长页面上以便可以使用 Ctrl-F 搜索,比将每个 API 调用放在单独的页面上更容易。
可悲的是,其中一些好的做法确实需要大量工作。创建自助服务入职系统并非易事。它需要多次迭代可用性测试和修订。易用性永远不会在第一次猜测中实现。
证明所有这些良好实践所需的资源可能是困难的,尤其是在 API 没有被你的许多客户使用时。“当几乎没有人使用我们的 API 时,投资回报率是多少?”你的管理层可能会问。我以不同的方式看待它:也许使用率很低是因为你没有做这些事情。
托马斯·A·利蒙切利是纽约市 Stack Overflow Inc. 的 SRE 经理。他领导 DNSControl 项目,该项目将 IaC 原则应用于 DNS 管理。他的著作包括系统和网络管理实践 (http://the-sysadmin-book.com)、云系统管理实践 (http://the-cloud-book.com) 和系统管理员的时间管理 (http://shop.oreilly.com/product/9780596007836.do)。他的博客在 EverythingSysadmin.com,推特在 @YesThatTom。他拥有德鲁大学计算机科学学士学位。
程序员也是人
编程语言和 API 设计人员可以从人机工程学设计领域学到很多东西。
肯·阿诺德
https://queue.org.cn/detail.cfm?id=1071731
被 Fork 走了
被开源占了便宜
刻薄守则
https://queue.org.cn/detail.cfm?id=2611431
管理技术债务
今天节省金钱和时间的捷径可能会在未来让你付出代价。
埃里克·奥尔曼
https://queue.org.cn/detail.cfm?id=2168798
版权所有 © 2019 归所有者/作者所有。出版权已许可给 。
最初发表于 Queue 第 17 卷,第 5 期—
在 数字图书馆 中评论本文
路易吉·里佐 - 重新审视网络 I/O API:netmap 框架
如今,10 千兆接口在数据中心和服务器中得到越来越广泛的应用。在这些链路上,数据包的流速高达每 67.2 纳秒一个,但现代操作系统仅将一个数据包在线缆和应用程序之间移动就需要花费 10-20 倍的时间。我们可以做得更好,不是通过更强大的硬件,而是通过修改很久以前关于设备驱动程序和网络堆栈设计的架构决策。
米奇·亨宁 - API:设计至关重要
作为一名软件工程师超过 25 年,我仍然发现自己低估了完成特定编程任务所需的时间。有时,由此导致的进度延误是由于我自身的缺点造成的:当我深入研究一个问题时,我只是发现它比我最初想象的要困难得多,因此解决问题需要更长的时间——这就是程序员的生活。同样,我也经常清楚地知道我想实现什么以及如何实现它,但这仍然比预期的要花费更长的时间。当这种情况发生时,通常是因为我正在与一个 API 作斗争,这个 API 似乎竭尽全力在我的道路上投掷石头并使我的生活变得艰难。