需求:是這樣的,要開發一個簡訊發送的模板,不同客戶可能會使用不同的模板,而不同的客戶使用的變數參數也是不同的。
之前為了應急,線上已經完成了一個短信模板發送短信的功能,短信模板表也創建了,而且在表中已經添加了一條記錄。我只要要做一個簡訊模板的增刪改查介面就可以了,看上去我的任務挺簡單的,老司機應該知道,接了個爛攤子。
下圖所示是原來已經創建好了的表
SQL創建腳本如下:
在這之前是已經開發了一個已經開發的API ,也就是說呼叫方(客戶),不會修改程式碼,只能我這邊來修改。雖然極不情願接做了一半的任務,但是沒辦法,不可能給你的開發任務都是從頭開始的。
實體類別代碼如下:
DOT類別:
這是之前的代碼,業務實體類Message呼叫的一個實體對象。物件裡面存在著許多類似簡訊的動態標籤變數。
public class MessageModuleBusiness : GenericRepository<Model.MessageModule> { private UnitOfWork.UnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(); /// 获取模版内容 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 && c.TypeNo == TypeCode).FirstOrDefault(); //Content的内容:【一应生活】您有一件单号为expressNumbers company, 已到communityName收发室,请打开一应生活APP“收发室”获取取件码进行取件。点击下载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 }
控制器方法externalMerchantSendMessage,這是外部呼叫的
public class MessageContext{ /// 手机号码 public string phone { get; set; } /// 发送信息 public string message { get; set; } /// 签名 public string sign { get; set; } /// 渠道 public string channel { get; set; } /// 内容 public string content { get; set; } /// 取件码 public string fetchCode { get; set; } /// 快递公司 public string company { get; set; } /// 快递单号 public string expressNumbers { get; set; } /// 社区名称 public string communityName { get; set; } /// 到件时间 public string receiveTime { get; set; } /// 序号 public string Id { get; set; } /// 业务代码 public string serviceCode { get; set; } }
以上是我接收開發任務之前已經實現了的功能。看起來我的任務挺簡單的,可是多年的開發經驗告訴我,這裡需要重構,如果我現在啥都不管,就只管做一個短信模板的增刪改查界面的話,後面維護的人一定會抓狂。
看出什麼問題沒有?
這個介面方法externalMerchantSendMessage是給所有客戶調用,而不同客戶使用不同的簡訊模板,不同的模板,又存在不同的變數參數。而現在所有的變數參數都封裝在了類別MessageContext中,問題是我們無法一下子把所有的變數參數全部確定下來,並且保持不變。
那麼,也就是說一旦需要加入變數參數,類別MessageContext中的程式碼就必須修改,而且GetContent方法中的程式碼是硬編的,一樣需要跟著修改。這樣就形成了一個循環,不斷加變數參數,不斷改程式碼,不斷發布介面版本.......
時間充裕的情況下,我自然是一個有節操的程式猿,那麼就開始重構吧。
在重構之前,在腦海浮現的並不是各種設計模式,而是物件導向設計的基本原則。各種設計模式就好比各種武學套路或招式,習武之人應該像張無忌練習太極劍一樣,先學會各種套路,然後忘記所有套路,從而融會貫通。
因為招式是死的,人是活得,有招就有破綻,根本沒有必勝招式存在,就好像沒有萬能的設計模式一樣,任何設計模式都存在缺點。
物件導向設計的核心思想就是封裝變化,那麼先找出變化點。從上面的分析中,我們已經發現了變化點,那就是簡訊模板中的變數參數,而這些變數參數都是客戶呼叫方傳過來的,不同客戶傳遞的參數變數又可能是不一樣的。
我們先來看一下,客戶傳遞過來的是什麼?我們看下客戶呼叫程式碼,這裡有Get和Post兩種呼叫方式。
/// 外部商户发送信息 public ActionResult externalMerchantSendMessage(MessageContext param) { logger.Info("[externalMerchantSendMessage]param:" + param); bool isAuth = authModelBusiness.isAuth(param.channel, param.phone, param.sign); if (!isAuth) { return Json(new Result<string>() { resultCode = ((int)ResultCode.NoPermission).ToString(), resultMsg = "签名或无权限访问" }, JsonRequestBehavior.AllowGet); } var meaage = messageModuleBusiness.GetContent(param); if (string.IsNullOrEmpty(meaage)) { return Json(new Result<string>() { resultCode = ((int)ResultCode.failure).ToString(), resultMsg = "发送失败" }, JsonRequestBehavior.AllowGet); } SMSHelper helper = new SMSHelper(); helper.SendSMS(meaage, param.phone); return Json(new Result<string>() { resultCode = ((int)ResultCode.success).ToString(), resultMsg = "发送成功" }, JsonRequestBehavior.AllowGet); }
可見客戶傳遞的是一個鍵值對集合,就是一個JSON格式的物件。根據前面的程式碼 bool isAuth = authModelBusiness.isAuth(param.channel, param.phone, param.sign);,可以分析出有三個參數是所有呼叫客戶都必須傳遞過來的,那就是:channel,phone,sign,而其它的參數就是簡訊模板的變數參數和參數值。
那麼方法externalMerchantSendMessage(MessageContext param)中的參數就是一個可變物件。在C#4.0種存在一個dynamic不正是用來描述可變對象嗎?
那麼第一步修改傳入參數類型,之前是硬編碼的強型別MessageContext,現在不依賴此類,而是動態解析,修改externalMerchantSendMessage方法代碼如
下:
function sendMsg() { //var appParam ="phone=15914070649&sign=78a7ce797cf757916c2c7675b6865b54&channel=weijiakeji&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方法 function Post(url, data) { $.ajax({ url: url, contentType: "application/json", type: "POST", 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); } }); }; //// WebApi Get方法 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); } }); };
DynamicJsonConverter的作用是將JSON字串轉為Object對象,程式碼如下:
dynamic param = null; string json = Request.QueryString.ToString(); if (Request.QueryString.Count != 0) //ajax get请求 { //兼容旧的客户调用写法,暂时硬编了 if (json.Contains("param.")) { json = json.Replace("param.", ""); } json = "{" + json.Replace("=", ":'").Replace("&", "',") + "'}"; } else //ajax Post请求 { Request.InputStream.Position = 0; //切记这里必须设置流的起始位置为0,否则无法读取到数据 json = new StreamReader(Request.InputStream).ReadToEnd(); } var serializer = new JavaScriptSerializer(); serializer.RegisterConverters(new[] { new DynamicJsonConverter() }); param = serializer.Deserialize(json, typeof(object));
以上就是記一次.NET程式碼重構(上)的內容,更多相關內容請關注PHP中文網(www.php.cn)!

如何利用.NET構建應用?使用.NET構建應用可以通過以下步驟實現:1)了解.NET基礎知識,包括C#語言和跨平台開發支持;2)學習核心概念,如.NET生態系統的組件和工作原理;3)掌握基本和高級用法,從簡單控制台應用到復雜的WebAPI和數據庫操作;4)熟悉常見錯誤與調試技巧,如配置和數據庫連接問題;5)應用性能優化與最佳實踐,如異步編程和緩存。

C#在企業級應用、遊戲開發、移動應用和Web開發中均有廣泛應用。 1)在企業級應用中,C#常用於ASP.NETCore開發WebAPI。 2)在遊戲開發中,C#與Unity引擎結合,實現角色控制等功能。 3)C#支持多態性和異步編程,提高代碼靈活性和應用性能。

C#和.NET適用於Web、桌面和移動開發。 1)在Web開發中,ASP.NETCore支持跨平台開發。 2)桌面開發使用WPF和WinForms,適用於不同需求。 3)移動開發通過Xamarin實現跨平台應用。

C#.NET生態系統提供了豐富的框架和庫,幫助開發者高效構建應用。 1.ASP.NETCore用於構建高性能Web應用,2.EntityFrameworkCore用於數據庫操作。通過理解這些工具的使用和最佳實踐,開發者可以提高應用的質量和性能。

如何將C#.NET應用部署到Azure或AWS?答案是使用AzureAppService和AWSElasticBeanstalk。 1.在Azure上,使用AzureAppService和AzurePipelines自動化部署。 2.在AWS上,使用AmazonElasticBeanstalk和AWSLambda實現部署和無服務器計算。

C#和.NET的結合為開發者提供了強大的編程環境。 1)C#支持多態性和異步編程,2).NET提供跨平台能力和並發處理機制,這使得它們在桌面、Web和移動應用開發中廣泛應用。

.NETFramework是一個軟件框架,C#是一種編程語言。 1..NETFramework提供庫和服務,支持桌面、Web和移動應用開發。 2.C#設計用於.NETFramework,支持現代編程功能。 3..NETFramework通過CLR管理代碼執行,C#代碼編譯成IL後由CLR運行。 4.使用.NETFramework可快速開發應用,C#提供如LINQ的高級功能。 5.常見錯誤包括類型轉換和異步編程死鎖,調試需用VisualStudio工具。

C#是一種由微軟開發的現代、面向對象的編程語言,.NET是微軟提供的開發框架。 C#結合了C 的性能和Java的簡潔性,適用於構建各種應用程序。 .NET框架支持多種語言,提供垃圾回收機制,簡化內存管理。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

WebStorm Mac版
好用的JavaScript開發工具

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。