.NET コードのリファクタリングを思い出す (パート 1)

黄舟
リリース: 2017-02-06 14:37:00
オリジナル
1151 人が閲覧しました

要件: これは、テキスト メッセージを送信するためのテンプレートを開発する場合に当てはまります。異なる顧客は異なるテンプレートを使用する可能性があり、異なる顧客によって使用される変数パラメーターも異なります。


緊急用にテキストメッセージを送信するためのテキストメッセージテンプレート機能がオンラインで完成し、テキストメッセージテンプレートテーブルも作成され、テーブルに新しいレコードが追加されました。テキスト メッセージ テンプレートを追加、削除、変更、確認するためのインターフェイスを作成するだけで済みます。経験豊富なドライバーであれば、私が混乱したことになることがわかるはずです。


下の図は、最初に作成されたテーブルを示しています

.NET コードのリファクタリングを思い出す (パート 1)

SQL作成スクリプトは次のとおりです:

.NET コードのリファクタリングを思い出す (パート 1)

これに先立って、顧客が呼び出すためのSMSを送信するためのAPIインターフェースが開発されました。つまり、呼び出し元 (顧客) はコードを変更せず、私だけがコードを変更できます。中途半端な仕事を引き受けるのは非常に抵抗があるのですが、開発業務はすべて一からやり直すしかありません。


エンティティクラスのコードは次のとおりです:

.NET コードのリファクタリングを思い出す (パート 1)

DOTクラス:

.NET コードのリファクタリングを思い出す (パート 1)

これは前のコードです。ビジネスエンティティクラスのMessageModuleBusiness.csコードは次のとおりです:

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
}
ログイン後にコピー

MessageContextクラス、これはクライアントによって送信され、呼び出すエンティティ オブジェクトです。オブジェクトにはテキスト メッセージに似た多くの動的タグ変数があります。

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; }
    }
ログイン後にコピー

外部呼び出し用のControllerメソッドexternalMerchantSendMessage

    /// 外部商户发送信息
        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);
        }
ログイン後にコピー

上記は開発タスクを受け取る前に実装した関数です。私のタスクは非常に単純であるように見えますが、長年の開発経験から、今は何も気にせず、SMS テンプレートを追加、削除、変更、確認するためのインターフェイスを作成するだけであれば、これをリファクタリングする必要があることがわかります。将来の保守担当者は間違いなく発狂するでしょう。


何か問題はありますか?


このインターフェイス メソッド externalMerchantSendMessage はすべての顧客に対して呼び出され、顧客ごとに異なる SMS テンプレートが使用され、テンプレートごとに異なる変数パラメーターが使用されます。現在、すべての変数パラメーターが MessageContext クラスにカプセル化されています。問題は、すべての変数パラメーターを一度に決定して変更せずに維持することができないことです。


つまり、変数パラメーターを追加する必要がある場合は、MessageContext クラスのコードを変更する必要があり、GetContent メソッドのコードはハードコーディングされているため、それに応じて変更する必要があります。これによりサイクルが形成され、変数パラメーターが常に追加され、コードが常に変更され、インターフェイスのバージョンが常にリリースされます...


十分な時間があれば、私は自然に規律あるプログラマーなので...リファクタリングを始めましょう。


リファクタリングの前に頭に浮かぶのは、さまざまな設計パターンではなく、オブジェクト指向設計の基本原則です。さまざまなデザインパターンは、さまざまな武術のルーチンや動きのようなもので、武術家は太極拳の剣を練習する張無忌のように、まずさまざまなルーチンを学び、その後、すべてのルーチンを忘れて習得する必要があります。


なぜなら、動きは死んでいるからです、人は生きているのです。すべての動きには欠点があります。普遍的なデザインパターンがないのと同じように、どんなデザインパターンにも欠点があります。


オブジェクト指向設計の中心的な考え方は、変更をカプセル化することなので、最初に変更点を見つけます。上記の分析から、SMS テンプレート内の可変パラメータである変化点を発見しました。これらの可変パラメータは顧客の呼び出し元によって渡され、異なる顧客によって渡されるパラメータ変数は異なる可能性があります。


まず見てみましょう、顧客から何が渡されるのでしょうか?顧客呼び出しコードを見てみましょう。Get と Post という 2 つの呼び出しメソッドがあります。

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(&#39;/Message/externalMerchantSendMessage&#39;, 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) {
                    $(&#39;#response&#39;).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) {
                    $(&#39;#response&#39;).text(JSON.stringify(response));
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus);
                }
            });
        };
ログイン後にコピー

顧客が渡すのは、JSON 形式のオブジェクトであるキーと値のペアのコレクションであることがわかります。前のコード bool isAuth = authModelBusiness.isAuth(param.channel, param.phone, param.sign); によると、すべての発信顧客が渡す必要がある 3 つのパラメーター、つまり、channel、phone、sign があることが分析できます。 , その他のパラメータは、SMS テンプレートの可変パラメータとパラメータ値です。


メソッド externalMerchantSendMessage(MessageContext param) のパラメータは変数オブジェクトです。 C# 4.0 には、可変オブジェクトを記述するために使用されるダイナミックはありませんか?

次に、最初のステップは、受信パラメータのタイプを変更することです。以前は、ハードコーディングされた厳密に型指定された MessageContext でしたが、現在はこのタイプに依存せず、externalMerchantSendMessage メソッドのコードを次のように変更します。 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("=", ":&#39;").Replace("&", "&#39;,") + "&#39;}";
                }
                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 コードの再構築の内容です (パート 1)。 PHP 中国語 Web サイト (www.php.cn)!

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!