功能标志——它们应该暴露给客户端应用程序吗?

Feature Flags - Should they be exposed to client applications?

我正在考虑在同时具有 javascript/html 和移动本机客户端的基于 Web 的应用程序中使用功能标志,并且正在尝试就以下内容做出明智的决定:

是否应该向客户端应用程序公开功能标志?

在与其他人讨论这个问题时,出现了 2 种关于客户端如何处理功能标志的方法,它们是:

1) 客户对功能标志一无所知。

响应数据的服务器端端点将包含额外的数据,以说明某项功能是打开还是关闭。

例如对于一个虚构的端点,/posts,数据可以像这样返回

增强ui功能已启用:

{
  enhanced_ui: true,
  [1,2,3,4,5]
}

增强ui功能禁用:

{
  enhanced_ui: false,
  [1,2,3,4,5]
}

2) 客户端可以访问端点,并请求功能标志状态。

例如/flagstates

{
  'enhanced_ui:true
}

客户然后使用它来隐藏或显示特征作为要求ui红色。

一些想法:

方法 #1 的移动部分较少 - 根本不需要客户端库来实现门。

问题来了 - 当动态标志更新时,客户端如何知道?我们可以实施 pub/sub 来接收通知并重新加载客户端,然后它们会自动获取最新的数据。

方法 #2 感觉它可能更容易管理标志更新的侦听,因为它是 returns 功能的单个端点,并且可以轻松推出状态更改。

这让我很感兴趣,而且我有一个要求ui要在我正在开发的产品中实现功能 flags/switches。过去一周我一直在研究这个领域,我将分享我的发现和想法(我并不是说它们是任何方面的最佳实践)。这些发现和想法将在很大程度上基于 ASP.Net Zero and ASP.Net Boilerplate,因为我发现这些与我正在寻找的示例实现最匹配。

Should feature flags be exposed to client applications?

是也不是。如果您正在构建ui将软件作为服务产品(可能具有多租户),那么您很可能必须进行某种管理ui,管理员用户可以在其中进行管理(CRUD/Enable/Disable ) 特征 。这意味着,如果您正在构建 SPA,您显然必须在 api 中实现端点(当然要适当保护),您的前端可以使用该端点来检索有关功能的详细信息和他们的当前状态用于编辑目的。这可能如下所示:

"features": [
    {
      "parentName": "string",
      "name": "string",
      "displayName": "string",
      "description": "string",
      "defaultValue": "string",
      "inputType": {
        "name": "string",
        "attributes": {
          "additionalProp1": {},
          "additionalProp2": {},
          "additionalProp3": {}
        }, 
      ....

特征模型当然会根据您的问题领域而有所不同,但以上内容应该让您了解一个通用模型来保存特征定义。

现在如您所见,该功能不仅仅是一个是否启用的布尔标志 - 它可能具有围绕它的属性。这对我来说根本不是显而易见的事情,因为我只是在相当简单的功能 (true/false) 的背景下考虑我的问题,而实际上,可能有更复杂的功能。

最后,当您的用户浏览您的应用时,如果您为启用了 EnhancedUI 功能的租户呈现 UI,您将需要知道该功能是否已启用。在 ASP.Net 零中,这是通过使用称为 IPermissionService 的东西完成的,它在前端和后端都实现了。在后端,权限服务基本上会检查用户是否应该被允许访问某些资源,这在功能切换上下文中意味着检查是否为给定租户启用了该功能。在前端 (Angular),权限服务检索这些权限 ( /api/services/app/Permission/GetAllPermissions):

{
  "items": [
    {
      "level": 0,
      "parentName": "string",
      "name": "string",
      "displayName": "string",
      "description": "string",
      "isGrantedByDefault": true
    }
  ]
}

然后可以使用它来创建某种 RouteGuard,如果某些内容未启用或不允许,您可以适当地重定向到 升级您的版本 页。

希望这能给您一些思考的想法。