代碼重構(gòu)怎么做

字號:


    這幾天,接手一個(gè)同事的代碼,關(guān)于微信接口開發(fā)的,那一堆的 if,看得哥蛋痛了,這個(gè)毛病也是很多新手容易犯的,所以特地把這次重構(gòu)寫出來。
    下面來我們看看這個(gè)代碼的問題所在,if else 里面的代碼塊邏輯,不好改,使得它的重用性為 0,并且難以閱讀。當(dāng)然,如果 if 只有一兩個(gè),或者3個(gè),這樣寫是問題不大的。
    但是如果多了,這種代碼便會讓維護(hù)變得困難起來。
    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 = "歡迎關(guān)注";
    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;
    }
    一種比較好的處理方法就是把語句塊內(nèi)的代碼抽出來,寫成函數(shù),如下面所示:
    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;
    }
    }