Close

软件开发原则-控制代码行

原则

编写代码单元应该少于15行,方便阅读、理解、测试、重构,超过15行应提取拆分,直至少于15行。

应用

下面我们通过例子来应用此原则。原代码如下:

func initEngine() *gin.Engine {
    router := gin.Default()
    m := melody.New()
    m.Config.MaxMessageSize = 10024
    m.Config.MessageBufferSize = 5120
    Rooms = make(map[string]RoomInfo)
    router.GET("/v", func(c *gin.Context) {
        m.HandleRequest(c.Writer, c.Request)
    })
    m.HandleConnect(func(session *melody.Session) {
        log.Info("[ws] connect:", session)
    })

    m.HandleDisconnect(func(session *melody.Session) {
        log.Info("[ws] disconnect", session)
    })

    m.HandleMessage(func(session *melody.Session, msg []byte) {
        reg, exists := session.Get("reg")
        log.Info("[ws] message:", string(msg), "reg:", reg)
        if string(msg) == WebSocketClientBye {
            if exists {
                sp := (reg).(*WSMessage)
                if removeRoom(sp.RoomID, sp.ClientID) != "" {
                    log.Warnf("Socket removeRoom error:%v", reg)
                }
            }
            log.Info("Socket bye", reg)
            return
        }
        message := &WSMessage{}
        err := json.Unmarshal(msg, message)
        if err != nil {
            log.Error("Json error :", err)
            return
        }
        switch message.CMD {
        case "register":
            log.Debug("register")
            session.Set("reg", message)
            return
        default:
            log.Debug("socket default json:", message)
            // check
            p := (reg).(*WSMessage)
            roomID := p.RoomID
            my := p.ClientID
            m.BroadcastFilter(msg, func(s *melody.Session) bool {
                if reg, exists = s.Get("reg"); exists {
                    sp := (reg).(*WSMessage)
                    if r, ok := Rooms[roomID]; ok {
                        for _, c := range r.Clients {
                            if (sp.ClientID == c.ClientID) && (c.ClientID != my) {
                                log.Info("[ws] <----sent---->", c, my, string(msg))
                                return true
                            }
                        }
                    } else {
                        log.Warnf("[ws] only myself???? roomID:%d,my:%v,msg:%v", roomID, my, string(msg))
                    }
                }
                return false
            })
        }

    })
    return router
}

这是一个初始化并实现WebSocketWeb功能的服务器,省略部分代码,并删除了一些调试信息。注释少的可怜,如果初次到这样的代码一定会觉得头大。在重构过程中发现使用此原则会让代码结构清晰,这也是我们重构的目的。下面简单介绍使用的方法:

  • 揉功能塞到一起了,应该想办法把相同的功能抽离出新的函数。

    原代码:

    m.BroadcastFilter(msg, func(s *melody.Session) bool {
                    if reg, exists = s.Get("reg"); exists {
                        sp := (reg).(*WSMessage)
                        if r, ok := Rooms[roomID]; ok {
                            for _, c := range r.Clients {
                                if (sp.ClientID == c.ClientID) && (c.ClientID != my) {
                                    log.Info("[ws] <----sent---->", c, my, string(msg))
                                    return true
                                }
                            }
                        } else {
                            log.Warnf("[ws] only myself???? roomID:%d,my:%v,msg:%v", roomID, my, string(msg))
                        }
                    }
                    return false
                })
    

    重构代码:

    // SendRoomBroadcast 发送房间广播
    func (wss *WebSocketServer) SendRoomBroadcast(roomID, my string, msg []byte) {
        wss.Server.BroadcastFilter(msg, func(s *melody.Session) bool {
            if reg, exists := s.Get("reg"); exists {
                sp := (reg).(*WSMessage)
                if r, ok := Rooms[roomID]; ok {
                    for _, c := range r.Clients {
                        if (sp.ClientID == c.ClientID) && (c.ClientID != my) {
                            return true
                        }
                    }
                } else {
                    log.Warnf("[ws] only myself???? roomID:%d,my:%v,msg:%v", roomID, my, string(msg))
                }
            }
            return false
        })
    }
    
    • 封装类

    当代码整

Leave a Reply

Your email address will not be published. Required fields are marked *