【问题标题】:Protocol simplicity versus "properness"协议简单性与“适当性”
【发布时间】:2009-03-08 17:30:12
【问题描述】:

我和我的一个朋友又发生了争执。

考虑需要设计一个基于 JSON 的简单协议,该协议主要用于在各方之间发送某种事件(消息)。

比如说

 { event_id: 1, chat_message: "Hello" }
 { event_id: 2, group_id: 3, presence: "online" }
 ...

我建议像上面一样保留这个协议,而我的朋友建议做这样的事情:

 { event_id: 1, details: { chat_message: "Hello" } }
 { event_id: 2, group_id: 3, details: {  presence: "online" } }
 ...

他的论点是,就像 TCP 和 HTTP 处于不同的“责任”层一样,该协议应该使用“详细信息”子对象来保持数据分离。

他的另一个论点是处理匹配事件的处理程序不应该知道任何有关“路由”信息(例如 event_id)的信息。

我的论点是:

  1. 为了向处理程序隐藏这些信息,我们正在增加每条消息的长度(以及网络流量,这对于与大量消息交换的系统可能很重要)
  2. 处理程序确实需要知道“路由”信息,例如,才能正确回答它们:

    this.replyTo(event['event_id'], reply); // or...
    this.replyTo(event, reply); 
    
  3. 即使我们需要从处理程序中隐藏 event_id 之类的东西,我们也可以在传递给处理程序之前将它们去掉,这样仍然可以节省流量

这个协议非常简单,不应该被其他人使用。

怎么想?

【问题讨论】:

  • 带宽差异不大,尤其是如果您在此之上进行压缩。只是想我会提到。
  • 是的,它不是——但为什么我们需要添加它...基本上什么都没有?

标签: actionscript-3 erlang network-programming network-protocols


【解决方案1】:

在大型项目的长期经验之后,我必须强烈反对gahooaCharlie Martin 的建议。敏捷方法和经典方法之间存在很大的张力。他们的建议看起来很敏捷,但我不能同意。如果你设计了一些东西,千万不要以你现在就知道是错误的方式来设计它。这不是敏捷,是愚蠢。我无法相信您认为您的需求在未来不会改变,因此请保持敞开大门并将重构影响降至最低。在您当前的设计中,当事件由不同的子系统作为事件类型分派器 -> 路由器到组 -> 最终事件处理程序/存储或其他方式处理时,请保持每个子系统中的更改相互之间的影响最小。对我来说最好的负担是像洋葱皮芽这样的设计协议,不要将其设计到您当前要求之外的每个细微细节。它很敏捷。

你的论点:

ad 1. 这是过早的优化。如果您确实需要最小化流量,请改用二进制协议;-) ti 的其他方式成本/收益是错误的。

ad 2. 它适用于内部程序检测,而不适用于协议本身。这是错误的设计,尤其是在 Erlang 中。您的处理程序不应该直接返回到目的地,而是返回到保持套接字所有权和类似情况的某个路由器(通常返回到调度程序)。看来又是过早优化了!

ad 3. 我更喜欢相反的方法。为子系统提供最小的数据集以最大程度地减少副作用,简化(单元)测试并避免诱惑使用第 2 点的方法。必要时延长。不要反其道而行之。

P.S.:为什么你不命名你的活动,而是使用 ID?又过早优化了?

编辑: Id 已明确,它们是事件编号但不是事件类别。应该有另一个类键。

【讨论】:

  • 1.谁说 JSON 不能打包成二进制文件? :)
  • 2.为了让路由器路由消息,它需要知道它应该将消息路由到哪里。我并不是说应该将消息直接返回到目的地,根本不是!我相信我明确说过它应该通过路由器。 replyTo() 方法实际上是路由器的快捷方式
  • 3.确切地。必要时延长。如有必要,添加“详细信息”。到目前为止,我还没有看到添加它的理由:)
  • P.S.:因为使用数字名称是愚蠢的 :) event_id 是一个连续的 id,而不是消息的类型(将在 event_class 或类似的东西中指定)
  • ad ad 1. 当你将打包到二进制文件时为什么要关心深度?
【解决方案2】:

倾向于简单...

当您编写规范、分布式系统以及将在您无法控制的许多不同情况下使用的规范时,将需要适当性。

务实,通常最好利用“语言的力量”并编写代码来处理每种情况。除非您需要,否则不要抽象

保持简单。保持快速。保持清洁。

您不知道它可能需要演变成什么(功能或性能),并且您拥有的抽象越多,重构就越困难。

【讨论】:

  • 没错,这听起来很接近我的想法
  • 在这种情况下,保持简单的一个演示部分意味着使另一个部分变得复杂且不太灵活。
【解决方案3】:

曾几何时,当 ARPAnet 还是新事物并且 IP 还只是一个想法的萌芽时,有人说“哦,天哪,32 位 IP 地址就足够了——4 十亿 个地址?没有人会需要它。见鬼,我们可以将它们分成不同的地址类型,有足够的空间。”

25 年后,我们几乎不知道这将是一个问题。

甚至不要跟我谈关于域名的事情。

重点是:您需要考虑可以改变什么。 为了优雅将其变成命名空间的层次结构是不必要且浪费的,而且当您的额外层不提供任何更多信息内容时,那何必费心呢。

另一方面,如果您这样做是为了使您的代码对问题的变化不那么敏感,或者使实施明显更容易或不易出错,那么它可能是值得的。

所以这就是你的答案:只是更优雅,还是有其他优势?

【讨论】:

    【解决方案4】:

    这是两个正确的解决方案。 如果您真的必须担心网络流量,您的解决方案是可以接受的。 但是您还必须记住,代码维护占据了代码生命周期的大部分时间,因此今天让代码更整洁,您将来可能会节省一些时间(已经提到过维护)。

    在我看来,您应该有基于强有力事实的充分论证来考虑此类优化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-09
      • 2019-06-20
      相关资源
      最近更新 更多