代码重构之 —— 一堆if、esle 逻辑的处理_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 代码重构之 —— 一堆if、esle 逻辑的处理

代码重构之 —— 一堆if、esle 逻辑的处理

 2014/5/21 23:09:45  麦舒  博客园  我要评论(0)
  • 摘要:这几天,接手一个同事的代码,关于微信接口开发的,那一堆的if,看得哥蛋痛了,这个毛病也是很多新手容易犯的,所以特地把这次重构写出来。下面来我们看看这个代码的问题所在,ifelse里面的代码块逻辑,不好改,使得它的重用性为0,并且难以阅读。当然,如果if只有一两个,或者3个,这样写是问题不大的。但是如果多了,这种代码便会让维护变得困难起来。if(strMsgType=="text"){textContentClient=rootElement.SelectSingleNode("Content"
  • 标签:代码

这几天,接手一个同事的代码,关于微信接口开发的,那一堆的 if,看得哥蛋痛了,这个毛病也是很多新手容易犯的,所以特地把这次重构写出来。

下面来我们看看这个代码的问题所在,if else 里面的代码块逻辑,不好改,使得它的重用性为 0,并且难以阅读。当然,如果 if 只有一两个,或者3个,这样写是问题不大的。

但是如果多了,这种代码便会让维护变得困难起来。

if (strMsgType == "text")
{
    textContentClient = rootElement.SelectSingleNode("Content").InnerText;
    strResult = SetMsgType_Text(strClientName, textContentClient, db, strServerName, Identity);
    System.Diagnostics.Trace.WriteLine(strResult);

    return Content(strResult);
}
else if (strMsgType == "event")
{
    string eventType = rootElement.SelectSingleNode("Event").InnerText.ToLower();
    if (eventType == "subscribe")
    {
        string keyCode = "";
        if (rootElement.SelectSingleNode("EventKey") != null)
            keyCode = rootElement.SelectSingleNode("EventKey").InnerText.ToLower();

        strResult = FormatEventSubscribe(keyCode);


        RecordReplyMessage();

        return Content(strResult);
    }
    else if (eventType == "scan")
    {
        string keyCode = rootElement.SelectSingleNode("EventKey").InnerText.ToLower();

        var outLetName = "欢迎关注";
        var outletDB = ShoppingContext.CreateInstance(Identity);
        var outLetModel = outletDB.Outlets.FirstOrDefault(o => o.SceneId == Int32.Parse(keyCode));
        if (outLetModel != null)
            outLetName += outLetModel.Name;


        return Content(GetTextTemp(strClientName, strServerName, outLetName));
    }
    else if (eventType == "click")
    {
        string keyCode = rootElement.SelectSingleNode("EventKey").InnerText.ToLower();
        strResult = FomatMenuMessage(keyCode);
        return Content(strResult);

    }
    else if (eventType == "unsubscribe")
    {
        var subIds = db.ReplyRecords.Where(r => r.FromOpenId == this.ClientId.ToString() && r.EMessType == EEventType.Subscribe.ToString() && r.KeyWord != null).Select(o => o.KeyWord).ToArray();
        var unSubIds = db.ReplyRecords.Where(r => r.FromOpenId == this.ClientId.ToString() && r.EMessType == EEventType.Unsubscribe.ToString() && r.KeyWord != null).Select(o => o.KeyWord).ToArray();

        var SencesId = "";
        foreach (var k in subIds)
        {
            if (!unSubIds.Contains(k))
            {
                this.ReplyModel.KeyWord = k;
                break;
            }
        }

        this.ReplyModel.EMessType = EEventType.Unsubscribe.ToString();
        RecordReplyMessage();
    }
}
else if (strMsgType.ToLower() == "location")
{
    string strLocation_X = rootElement.SelectSingleNode("Location_X").InnerText;
    string strLocation_Y = rootElement.SelectSingleNode("Location_Y").InnerText;

    strResult = FormatOutLetLBS(double.Parse(strLocation_X), double.Parse(strLocation_Y), 10);
    //strResult = FormatTextMessage(strLocation_X + "|" + strLocation_Y);
    return Content(strResult);
}
else if (strMsgType.ToLower() == "image")
{
    string strImgUrl = rootElement.SelectSingleNode("PicUrl").InnerText;
}

一种比较好处理方法就是把语句块内的代码抽出来,写成函数,如下面所示:

    public class MessageProcesser
    {
        public ReplyMessage Process(string xml)
        {
            var msg = PostMessage.FromXml(xml);
            switch (msg.MsgType)
            {
                case Models.PostMessageType.Event:
                    var eventType = ((EventMessage)msg).Event;
                    switch (eventType)
                    {
                        case EventType.Click:
                            return ProcessClickEvent((ClickEvent)msg);
                        case EventType.Location:
                            return ProcessLocationEvent((LocationEvent)msg);
                        case EventType.Scan:
                            return ProcessScanEvent((ScanEvent)msg);
                        case EventType.Subscribe:
                            return ProcessSubscribeEvent((SubscribeEvent)msg);
                        case EventType.Unsubscribe:
                            return ProcessUnsubscribeEvent((UnsubscribeEvent)msg);
                    }
                    break;
                case Models.PostMessageType.Image:
                    return ProcessImageMessage((ImageMessage)msg);
                case Models.PostMessageType.Link:
                    return ProcessLinkMessage((LinkMessage)msg);
                case Models.PostMessageType.Location:
                    return ProcessLocationMessage((LocationMessage)msg);
                case Models.PostMessageType.Text:
                    return ProcessTextMessage((TextMessage)msg);
                case Models.PostMessageType.Video:
                    return ProcessVideoMessage((VideoMessage)msg);
                case Models.PostMessageType.Voice:
                    return ProcessVoiceMessage((VoiceMessage)msg);
            }
            return null;
        }

        protected virtual ReplyMessage ProcessClickEvent(ClickEvent msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessLocationEvent(LocationEvent msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessScanEvent(ScanEvent msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessSubscribeEvent(SubscribeEvent msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessUnsubscribeEvent(UnsubscribeEvent msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessImageMessage(ImageMessage msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessLinkMessage(LinkMessage msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessLocationMessage(LocationMessage msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessTextMessage(TextMessage msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessVideoMessage(VideoMessage msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage ProcessVoiceMessage(VoiceMessage msg)
        {
            return DefaultProcess(msg);
        }

        protected virtual ReplyMessage DefaultProcess(PostMessage msg)
        {
            var reply = new TextReply(msg);
            if (msg.MsgType == PostMessageType.Event)
            {
                reply.Content = string.Format("{0} event is not processed.", ((EventMessage)msg).Event);
            }
            else
            {
                reply.Content = string.Format("{0} message is not processed.", msg.MsgType);
            }
            return reply;
        }


    }

在使用的时候,继承上面的类就行了。

public class MyMessageProcesser : WeiXin.MessageProcesser
{
    public MyMessageProcesser()
    {
    }

    protected override ReplyMessage ProcessSubscribeEvent(SubscribeEvent msg)
    {
        var reply = new TextReply(msg);
        reply.Content = "你好,欢迎关注";
        return reply;
    }

    protected override ReplyMessage ProcessUnsubscribeEvent(UnsubscribeEvent msg)
    {
        var reply = new TextReply(msg);
        reply.Content = "取消关注";
        return reply;
    }
}

欢迎讨论,欢迎板砖。

=======================================================

有朋友说,我只是把 if 换成了 switch,这个没错,但更重要的是,换成了一个可重写方法的类。

有朋友说,使用命令模式会不会更好点。是这样的,因为是微信的接口,以后就算是增加,也是很少会发生的,并且要作的改动也不多。所以不想变得太复杂了。现在是 if 内的语句块需要变动,因为要面对不同的用户,他们的处理都是不同的。

 

发表评论
用户名: 匿名