php - 从 Websocket 服务器中移除 Switch 语句的味道

标签 php json refactoring ratchet

<分区>

我不确定这个问题属于这里,因为它“值得商榷”,但让我们试一试。

在阅读了很多关于它的例子和问题之后(比如 this one 看起来真的很相似),我仍然不知道我是否应该选择多态来代替开关。

都是关于 Ratchet WebSocket 服务器的,它接收 JSON 消息并根据消息 type 执行例程:

public function onMessage(ConnectionInterface $from, $msg) {
    /*!
    Triggers everytime a message is received by the application.
    Depending on @p $msg type, the application will broadcast @p $msg accordingly.

    @param ConnectionInterface $from 
    This is the socket (client) who sent @p $msg.
    @param string $msg
    A JSON string sent by the client.
    */
    $usermsg = json_decode($msg, true);
    if (isset($usermsg["message"])) {
        $actual_msg = $this->removeHTML($usermsg["message"]);
    }

    switch ($usermsg["type"]) {

        case 'text':
            $this->text($from, $actual_msg, "text");
            break;

        case 'token':
            $this->token($from, $usermsg["im"]);
            break;

        case "ready":
            $this->ready($from);
            break;

        case "action":
            $this->text($from, $actual_msg, "action");
            break;

        case "users":
            $this->whoIsOnline($from);
            break;

        case "listen":
            $this->listen($from);
            break;

        case "end":
            $this->finish($from, $actual_msg);
            break;

        case 'statInit':
            $this->statInit($from);
            break;
    }
}

事实是,$msg 是一个字符串,因为它是 JSON,根本没有为到达的任何消息实例化任何对象。这就是没有类层次结构的原因,因为消息不是对象。事实上,除了实际的服务器之外没有其他类。

无论如何,这是唯一存在于服务器端的开关(客户端中还有另一个开关,但它是 jQuery,所以情况不同),因此添加新功能应该是添加一个案例和一个方法,而不是那么难。该项目不会增长太多,但我希望它能够轻松扩展。

我是否应该坚持 OOP 设计并为到达的每条消息创建一个对象并应用多态性?似乎有点不知所措,因为服务器处理聊天消息。

最佳答案

一方面,归根结底这对您有用并且相对容易维护。完全 OOP 可能只是一种纯洁和/或 self 的练习。

如果您要将 OOP 方法提升到一个新的水平,如果是我,我会创建一个 SocketMessage 类,它在构造函数中接受 JSON 消息字符串。我还会为每个扩展它的消息类型创建一个 SocketHandler 类,其中包含单独的处理程序类。您的方法之后的一些粗略代码是:

public function onMessage(ConnectionInterface $from, $json) 
{
    $message = new SocketMessage($json);
    return $message->dispatch();
}

dispatch() 调用将是 SocketMessage 类的一部分,并将根据消息类型确定将其定向到哪个处理程序。它会知道哪些处理程序可用,因为您首先会在 SocketHandler 基类中注册它们。

// Somewhere that you initialize code
SocketHandler::register('text', Handlers\TextHandler::class);
SocketHandler::register('token', Handlers\TokenHandler::class);
SocketHandler::register('ready', Handlers\ReadyHandler::class);

注册处理程序只会将它们放入类中的静态数组中,以便稍后访问。在 SocketMessage::dispatch() 函数中,您可能会这样做:

class SocketMessage
{
    ...
    public function __construct($json)
    {
        // Parse raw message data
        $this->message = @json_decode($json, true);
        if (empty($this->message)) {
           throw new Exception('SocketMessage expects a valid JSON string.');
        }
    }
    ...
    public function dispatch()
    {
        $type = $this->message['type'];
        $handler = SocketHandler::get($type);

        return $handler->handle($this->message);
    }
    ...
} 

我真的不确定我要处理所有这些。我的主要观点是你可以让它更面向对象,这将导致它更灵活和可扩展,但也会带来更多的可维护性困难。这实际上是一个偏好和项目范围的问题(即它是一个由很多人维护的大型项目,还是您在业余时间玩的一个爱好脚本?)

关于php - 从 Websocket 服务器中移除 Switch 语句的味道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34346906/

相关文章:

php - 将对象传递给方法,将该对象分配给另一个对象,传入的对象仍然是我传入的同一对象

javascript - jQuery AJAX JSON 自动刷新使用动画显示数据不起作用

c++ - 构造函数的参数数量

javascript - FB之类的按钮edge.create事件在登录后不会触发

php - 如何使用 preg_match 查找模式匹配并保存到数组

mysql - 在 Mysql 中检索 JSON 数组内的 Json 数据值

visual-studio - Visual Studio : Is there a "move class to different namespace" refactoring?

oracle - 重构 PL/SQL : many cursors with same rowtype (in theory)

javascript - 仅当选中时才将复选框的值传递给变量

java - Jersey 2.22 和 json 不支持的媒体类型