我和我的一个朋友有另一个争论。
考虑需要设计一个简单的基于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)。
我的论点是:
处理程序确实需要知道“路由”信息,比如说,正确回答它们:
this.replyTo(event['event_id'], reply); // or...
this.replyTo(event, reply);
即使我们需要隐藏event_id和处理程序中的类似东西,我们也可以在传递给处理程序之前将它们删除,从而节省流量
这个协议很简单,不应该被其他任何人使用。
你的想法是什么?
答案 0 :(得分:4)
在大项目的长期经验之后,我必须强烈反对gahooa和Charlie Martin的建议。敏捷和经典方法之间存在很大的紧张关系。他们的建议看起来像敏捷,但我不能同意。如果你设计的东西,永远不要设计它,你知道即使是现在也是错的。这不敏捷,它是愚蠢的。我无法相信您认为您的要求将来不会发生变化,因此请保持开放,重构影响最小化。当您的当前设计事件由不同的子系统处理为事件类型调度程序时 - >路由器到组 - >最终事件处理程序/存储或其他,在每个子系统中保持更改,相互之间的影响最小。最适合我的是像洋葱皮芽这样的设计协议,不会将其设计为当前要求之外的每个细微细节。这很敏捷。
你的论点:
ad 1.这是过早的优化。如果你真的需要最小化流量,请使用二进制协议;-)其他方式ti的成本/收益是错误的。
ad 2.它适用于内部程序检测,而不适用于协议本身。特别是在Erlang中,这是错误的设计。您的处理程序不应该直接返回目标,而是返回到某个路由器(通常返回调度程序),它保留了套接字所有权等。看起来再次过早优化了!
ad 3.我更喜欢相反的方法。为子系统提供最小的数据集,以最大限度地减少副作用,简化(单元)测试并避免诱使使用2.点的方法。必要时延长。不要以相反的方式做到。
P.S。:为什么你没有为活动命名但使用ID?再次过早优化?
编辑:明确了ID,这些是事件编号,但不是事件类。应该有另一个班级钥匙。
答案 1 :(得分:2)
赞成简单......
当您编写规范,分布式系统以及将在您无法控制的许多不同情况下使用的规范时,将需要正确。
务实,使用“语言的力量”并编写代码来处理每个案例通常会更好。除非需要,否则不要抽象。
保持简单。保持快速。保持清洁。
你不知道它可能需要演变成什么(特征或性能),你拥有的抽象越多,重新分解的难度就越大。
答案 2 :(得分:2)
曾几何时,ARPAnet仍然是新的,IP仍然是一个想法的萌芽,有人说“哦,哎呀,32位的IP地址是充足的 - 四个十亿地址?没有人会需要它。天哪,我们可以将它们分成不同的地址类型,有足够的空间。“
25年后,我们几乎不知道这将成为一个问题。
甚至没有与谈论域名命名。
重点是:你需要考虑可以改变什么。将它变成名称空间的层次结构只是为了优雅而是不必要和浪费的,当你的额外层不提供任何更多的信息内容时,那么为什么要这么麻烦。
另一方面,如果你这样做是为了让你的代码对问题的变化不那么敏感,或者为了使实现更容易或更不容易出错,那么它可能是值得的。
所以有你的答案:是只是更优雅,还是有其他优势?
答案 3 :(得分:0)
这是两个正确的解决方案。 如果你真的不得不担心网络流量,你的解决方案是可以接受的。 但是你还要记住,代码维护占用了代码生命周期的大部分,所以今天使代码更清晰,你可能会在将来节省一些时间(已经提到的维护)。
在我看来,你应该在强有力的事实基础上有好的论据来考虑这种优化。