Remember it once. NET code refactoring (top)

Source: Internet
Author: User
Requirement: Yes, to develop a template for sending text messages, different customers may use different templates, and the variable parameters used by different customers are different.


Before in order to emergency, the online has completed a text message template to send text messages, SMS Template table has also been created, and in the table has a new record. I just need to do a text message template additions and deletions to check the interface on it, it seems that my task is quite simple, the old driver should know, after a mess.


Shown is a table that has already been created

The SQL creation script is as follows:

Before this is already developed a Send SMS API interface for the customer to call, that is, the caller (customer), will not modify the code, only my side to modify. Although reluctant to take half of the task, but no way, it is impossible to give you the development of the task is to start from scratch.


The entity class code is as follows:

Dot class:

This is the previous code, the business entity class MessageModuleBusiness.cs code is as follows:

public class Messagemodulebusiness:genericrepository<model.messagemodule> {private Unitofwork.unitofwor        K unitofwork = new unitofwork.unitofwork ();            Get template Content public string getcontent (Messagecontext messagecontext) {string messagecontent = ""; String TypeCode = String. IsNullOrEmpty (Messagecontext.servicecode)?            "001": Messagecontext.servicecode; try {var Module = UnitOfWork.MessageModule.Get (c = c.type = = Messagecontext.channel &AMP;&A mp C.typeno = = TypeCode).                FirstOrDefault (); Content: "One should life" you have a ticket for expressnumbers company, has arrived in the CommunityName mailroom, please open the one should life app "mailroom" to get the pickup code to take the pieces. Click to download Http://a.app.qq.com/o/simple.jsp?pkgname=com.ening.life if (!string.                    IsNullOrEmpty (module.content)) {var Content = module.content; Content = content.                    Replace ("Company", Messagecontext.company); Content = content.                    Replace ("Expressnumbers", messagecontext.expressnumbers); Content = content.                    Replace ("CommunityName", messagecontext.communityname); Content = content.                    Replace ("Id", messagecontext.id); Content = content.                    Replace ("Receivetime", messagecontext.receivetime); Content = content.                    Replace ("Fetchcode", Messagecontext.fetchcode);                messagecontent = content;            } return messagecontent;        } catch (Exception ex) {} return ""; } #endregion}

The Messagecontext class, which is an entity object that the client transmits over the call. There are many dynamic tag variables in the object that are similar to text messages.

public class messagecontext{///        Phone number public        string phone {get; set;}        Send information public        string Message {get; set;}        Signature public        string sign {get; set;}        Channel public        string channel {get; set;}        Contents public        string Content {get; set;}        Pickup code Public        string Fetchcode {get; set;}        Courier Public        string company {get; set;}        Express number Public        string Expressnumbers {get; set;}        Community Name Public        string CommunityName {get; set;}        To part time public        string Receivetime {get; set;}        Ordinal public        string Id {get; set;}        Business code Public        string Servicecode {get; set;}    }

Controller method Externalmerchantsendmessage, which is for external invocation

    External merchant Send information public actionresult externalmerchantsendmessage (messagecontext param) {logger.i            NFO ("[Externalmerchantsendmessage]param:" + param);            BOOL Isauth = Authmodelbusiness.isauth (Param.channel, Param.phone, param.sign); if (!isauth) {return Json (new result<string> () {Result Code = ((int) resultcode.nopermission).            ToString (), resultmsg = "signed or no Access"}, Jsonrequestbehavior.allowget);            } var meaage = messagemodulebusiness.getcontent (param); if (string.                    IsNullOrEmpty (Meaage)) {return Json (new result<string> () { ResultCode = ((int) resultcode.failure).            ToString (), resultmsg = "Send Failed"}, Jsonrequestbehavior.allowget);            } smshelper helper = new Smshelper (); Helper. Sendsms (meaage, parAm.phone); Return Json (New result<string> () {ResultCode = ((int) resultcode.success).        ToString (), resultmsg = "Send Success"}, Jsonrequestbehavior.allowget); }

These are the features that I have implemented before I received the development task. It seems that my task is very simple, but many years of development experience tells me, here need to refactor, if I now do not care, just do a text message template additions and deletions to check the interface, the person behind the maintenance will be crazy.


See what the problem is?


This interface method Externalmerchantsendmessage is for all customers to call, while different customers use different text message templates, different templates, and there are different variable parameters. And now all the variable parameters are encapsulated in the class Messagecontext, the problem is that we can't all determine all the variable parameters all at once, and remain unchanged.


Then, that is, once you need to add a variable parameter, the code in the class Messagecontext must be modified, and the code in the GetContent method is hard-coded and needs to be modified as well. This creates a loop that constantly adds variable parameters, constantly changing the code, and constantly releasing the interface version ....


With plenty of time, I'm naturally a moral integrity ape, so start refactoring.


Before refactoring, it was not all design patterns that came to mind, but the basic principles of object-oriented design. All kinds of design patterns like a variety of military study routines or moves, martial arts people should be like Zhang Mowgli Practice Taiji Sword, first learn all kinds of routines, and then forget all the routines, thus mastery.


Because the moves are dead, people are alive, there are strokes there are flaws, there is no winning moves exist, as if there is no universal design mode, any design mode has shortcomings.


The core idea of object-oriented design is to change the package, then find the change point first. From the above analysis, we have found that the change point, that is, the variable parameters in the text message template, and these variables are sent to the customer by the caller, the parameter variables passed by different customers may not be the same.


Let's take a look at what the customer is delivering. Let's look at the customer invocation code, which has get and post two calls.

function sendmsg () {//var Appparam = "Phone=15914070649&sign=78a7ce797cf757916c2c7675b6865b54&channel=w eijiakeji&content=&fetchcode=1&company=%e9%a1%ba%e4%b8%b0%e5%bf%ab%e9%80%92&expressnumbers=            123456&communityname=%e9%95%bf%e5%9f%8e%e4%b8%80%e8%8a%b1%e5%9b%ad&receivetime=5&id=1231 ";            Get ("/message/externalmerchantsendmessage?" + Appparam, {});                var data = {"Phone": "15914070649", "sign": "78a7ce797cf757916c2c7675b6865b54", "channel": "Weijiakeji",            "Fetchcode": 1, "Company": "%e9%a1%ba%e4%b8%b0%e5%bf%ab%e9%80%92", "Id": "1231"};        Post ('/message/externalmerchantsendmessage ', data); }//webapi Post method function post (URL, data) {$.ajax ({url:url, con                Tenttype: "Application/json", type: "POST", DataType: "JSON", Async:true,             Cache:false,   Data:JSON.stringify (data), success:function (response) {$ (' #response '). Text (json.s                Tringify (response));                }, Error:function (XMLHttpRequest, Textstatus, Errorthrown) {alert (textstatus);        }            });        }; WebApi Get Method function get (URL, data) {$.ajax ({url:url, ContentType                : "Application/json", type: "GET", DataType: "JSON", Async:true,                    Cache:false,//data:json.stringify (data), success:function (response) {                $ (' #response '). Text (json.stringify (response));                }, Error:function (XMLHttpRequest, Textstatus, Errorthrown) {alert (textstatus);        }            }); };

The visible customer is passing a set of key-value pairs, which is a JSON-formatted object. According to the preceding code bool Isauth = Authmodelbusiness.isauth (Param.channel, Param.phone, param.sign), it can be analyzed that there are three parameters that all calling clients must pass over, That is: Channel,phone,sign, while the other parameters are the variable parameters and parameter values of the SMS template.


Then the parameter in the method Externalmerchantsendmessage (Messagecontext param) is a mutable object. Is there a dynamic in the c#4.0 species that is not used to describe mutable objects?

So the first step is to modify the incoming parameter type, which is hard-coded strongly-typed messagecontext, and now does not rely on this class, but dynamically parses, modifying the Externalmerchantsendmessage method code such as

Under

dynamic param = null;                String json = Request.QueryString.ToString ();                    if (Request.QueryString.Count! = 0)//ajax GET request {//compatible with old client call notation, temporarily hard-compiled if (JSON.                    Contains ("param.")) {JSON = json.                    Replace ("Param.", ""); JSON = "{" + JSON. Replace ("=", ":").                Replace ("&", "',") + "'}"; } else//ajax POST request {Request.InputStream.Position = 0;//Remember that you must set the starting bit of the stream here The data JSON = new StreamReader (Request.inputstream) cannot be read to 0.                ReadToEnd ();                } var serializer = new JavaScriptSerializer (); Serializer.                Registerconverters (new[] {new Dynamicjsonconverter ()}); param = serializer. Deserialize (JSON, typeof (object)); 

The purpose of

Dynamicjsonconverter is to convert a JSON string to an object, with the following code:

Using system;using system.collections;using system.collections.generic;using system.collections.objectmodel;using System.dynamic;using system.linq;using system.text;using System.web.script.serialization;public sealed class dynamicjsonconverter:javascriptconverter{public override Object Deserialize (idictionary<string, object> dicti Onary, type type, JavaScriptSerializer serializer) {if (dictionary = = null) throw new Argumentnullex        Ception ("dictionary"); return type = = typeof (object)?    New Dynamicjsonobject (dictionary): null;        } public override Idictionary<string, object> Serialize (object obj, JavaScriptSerializer serializer) {    throw new NotImplementedException (); } public override ienumerable<type> Supportedtypes {get {return new readonlycollection<type> (NE W list<type> (new[] {typeof (Object)})); }} #region Nested Type:dynamicjsonobject private Sealed class Dynamicjsonobject:dynamIcobject {private ReadOnly idictionary<string, object> _dictionary;                Public Dynamicjsonobject (idictionary<string, object> dictionary) {if (dictionary = = null)            throw new ArgumentNullException ("dictionary");        _dictionary = dictionary;            } public override string ToString () {var sb = new StringBuilder ("{");            ToString (SB); Return SB.        ToString ();            } private void ToString (StringBuilder sb) {var firstindictionary = true; foreach (var pair in _dictionary) {if (!firstindictionary) sb.                Append (",");                Firstindictionary = false; var value = pair.                Value; var name = pair.                Key; if (value is String) {sb.                AppendFormat ("{0}:\" {1}\ "", name, value); } else if (value is IDictionary<string, object>) {new Dynamicjsonobject (idictionary<string, object>) value ).                ToString (SB); } else if (value is ArrayList) {sb.                    Append (name + ": [");                    var Firstinarray = true;                            foreach (Var arrayvalue in (ArrayList) value) {if (!firstinarray) Sb.                        Append (",");                        Firstinarray = false; if (Arrayvalue is idictionary<string, object>) New Dynamicjsonobject ((Idictionary<stri Ng, object>) arrayvalue).                        ToString (SB); else if (Arrayvalue is String) sb.                        AppendFormat ("\" {0}\ "", arrayvalue); Else sb.                    AppendFormat ("{0}", arrayvalue); } sb.                Append ("]");            }    else {sb.                AppendFormat ("{0}:{1}", name, value); }} sb.        Append ("}"); }

The above is to remember once. NET code refactoring (above) content, more relevant content please pay attention to topic.alibabacloud.com (www.php.cn)!

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.