【问题标题】:OOA&D / Java / Software Architecture - advise on structuring event handling code to avoid a complicated data flowOOA&D / Java / Software Architecture - 建议结构化事件处理代码以避免复杂的数据流
【发布时间】:2019-02-20 04:40:06
【问题描述】:

我在 Spring 中使用消息代理实现了生产者/消费者范式,我的生产者使用 WebSocket 提取数据并将其发布到队列中。

因此,生产者类似于: AcmeProducer.java handler/AcmeWebSocketHandler.java

处理程序一直很痛苦。

首先,处理程序有两个事件: 打开() onMessage()

onOpen 必须向 Web 套接字发送消息以订阅特定频道 onMessage 接收来自 WebSocket 的消息并将它们添加到队列中

onMessage 与 AcmeProducer.java 有一些依赖关系,例如它需要知道要订阅的货币对、它需要消息代理服务、ObjectMapper(json 反序列化器)和基准服务。

当消息从队列中被消费时,它们被转换为 OrderBook.java 的格式。每个生产者都有自己的 OrderBook 格式,因此也有自己的 AcmeOrderBook.java。

我觉得流程很难遵循,即使我已将一个生产者的课程放在同一个包中。每次我想在生产者中修复某些东西时,我都必须在类之间进行更改并搜索它在哪里。

是否有一些技术可以将复杂的数据流简化为易于理解的内容?

如您所知,像 AcmeHandler.java 这样的事件处理程序持有从系统其他地方(来自 websocket 实现)调用的回调,因此它们可能很难组织起来。带有事件的数据流也更加复杂,因为当处理程序位于单独的文件中时,它们不能使用主文件中定义的变量。

如果此代码不使用事件驱动范例,则数据流将很容易遵循。

最后,在使用带有 onOpen 和 onMessage 的 Web 套接字时,是否有任何构建代码的最佳实践? Producer/Consumer 是我能想到的最好的,但我不想将 Acme 的类分散在不同的包中。例如,AcmeOrderbook 应该在消费者类中,但由于它依赖于 AcmeProducer.java 和 AcmeHandler.java,它们经常同时被编辑,因此我将它们放在一起。

由于每个 WebSocket 处理程序中的依赖项都是相同的(只有相同接口的不同实现),我认为应该只注入一个东西,那就是一些 Context 变量。这是最佳做法吗?

【问题讨论】:

    标签: java websocket object-oriented-analysis event-driven-design


    【解决方案1】:

    我已经使用 Message Dispatcher 和 Message Handlers 解决了这个问题。

    调度程序仅检查消息是否为数据消息(快照或更新)并将控制权传递给消息处理程序类,该类本身检查消息的类型(快照或更新)并正确处理该类型。如果消息不是数据消息而是其他消息,则调度程序将根据消息的内容(某些事件)来调度消息。

    我还使用匿名函数添加了回调,现在它们更短了,回调终于透明了。

    例如,在匿名回调函数内部只有这样:

    messageDispatcher.dispatchMessage(context);
    

    这里的另一个关键方法是使用上下文。MessageDispatcher 是一个单独的类(自动装配)。

    我已将订单簿分离到每个生产者内部的目录中。

    好吧,一切都需要一切知识才能优雅地解决这个问题。

    解决此问题的最后一种模式:Java EE 对其端点和控制函数(如 onOpen、onMessage 等)使用注解。这也是一种不错的方法,因为这样回调变得不可见,并且容器会自动调用 onOpen / onMessage (使用注释)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多