백엔드 개발 C#.Net 튜토리얼 .NET 코드 리팩터링 기억하기(1부)

.NET 코드 리팩터링 기억하기(1부)

Feb 06, 2017 pm 02:37 PM

요구 사항: 문자 메시지 전송을 위한 템플릿을 개발하려면 고객마다 서로 다른 템플릿을 사용할 수 있으며 고객마다 사용하는 변수 매개변수도 다릅니다.


긴급 상황을 대비해 온라인으로 문자 메시지를 보낼 수 있는 문자 메시지 템플릿 기능도 완성되었으며, 새로운 기록도 추가되었습니다. 테이블로. 문자 메시지 템플릿을 추가, 삭제, 수정, 확인하는 인터페이스만 만들면 되는데, 숙련된 운전자라면 이 일이 꽤 간단한 것 같습니다.


아래 그림은 원래 생성된 테이블입니다.

.NET 코드 리팩터링 기억하기(1부)

SQL 생성 스크립트는 다음과 같습니다.

.NET 코드 리팩터링 기억하기(1부)

이전에 고객이 전화할 수 있도록 문자 메시지를 보내는 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; }
    }
로그인 후 복사

외부 호출을 위한 컨트롤러 메소드 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의 두 가지가 있습니다.

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);에 따르면 모든 통화 고객이 통과해야 하는 세 가지 매개변수, 즉 채널, 전화, 서명이 있음을 분석할 수 있습니다. , 기타 매개변수는 SMS 템플릿의 가변 매개변수와 매개변수 값입니다.


그런 다음 externalMerchantSendMessage(MessageContext param) 메소드의 매개변수는 변수 객체입니다. C# 4.0에는 변경 가능한 개체를 설명하는 데 사용되는 동적 요소가 없나요?

그런 다음 첫 번째 단계는 하드 코딩된 강력한 유형의 MessageContext였던 수신 매개변수 유형을 수정하는 것입니다. 이제 이 유형에 의존하지 않고 externalMerchantSendMessage 메소드 코드를 다음과 같이 수정합니다. :

:

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));
로그인 후 복사

DynamicJsonConverter는 JSON 문자열을 Object 개체로 변환하는 데 사용됩니다. 코드는 다음과 같습니다.

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> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (dictionary == null)
            throw new ArgumentNullException("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>(new 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<string, 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("}");
        }
로그인 후 복사

위는 .NET 코드 재구성의 내용입니다. (1부) 더 많은 관련 내용을 주목해 주세요. PHP 중국어 사이트(www.php.cn)!


본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C++ 개발에서 코드 중복 문제를 해결하는 방법 C++ 개발에서 코드 중복 문제를 해결하는 방법 Aug 22, 2023 pm 05:30 PM

C++ 개발에서 코드 중복 문제를 해결하는 방법 코드 중복이란 프로그램을 작성할 때 여러 위치에 유사하거나 반복되는 코드가 있음을 의미합니다. 이 문제는 코드를 유지 관리하고 읽기 어렵게 만들 뿐만 아니라 코드의 크기와 복잡성을 증가시킵니다. C++ 개발자의 경우 코드 중복 문제를 해결하는 것이 특히 중요합니다. C++는 강력한 프로그래밍 언어이지만 쉽게 코드 중복으로 이어질 수도 있기 때문입니다. 코드 중복 문제의 근본 원인은 불합리한 디자인과 코딩 습관에 있습니다. 이 문제를 해결하려면 다음 측면에서 시작할 수 있습니다. 함수 및 클래스 사용: C

PHP 개발: 코드 리팩토링 및 최적화를 위해 Rector 사용 PHP 개발: 코드 리팩토링 및 최적화를 위해 Rector 사용 Jun 16, 2023 am 08:38 AM

시간이 흐르고 요구 사항이 변경됨에 따라 프로젝트의 코드는 쉽게 쓸모가 없어지고 유지 관리 및 확장이 어려워질 수 있습니다. PHP 개발에서 리팩토링은 코드 품질과 개발 효율성을 향상시키는 데 필요한 작업 중 하나로 간주됩니다. 이 과정에서 Rector 도구를 사용하면 코드 재구성 및 최적화 작업을 크게 단순화할 수 있습니다. Rector는 PHP 개발자가 코드 재구성 및 최적화를 자동화하여 개발자가 비즈니스 개발 및 기능 구현에 더 집중할 수 있도록 도와주는 오픈 소스 PHP 코드 재구성 도구입니다. 통과하다

C#의 취업 전망은 어떻습니까? C#의 취업 전망은 어떻습니까? Oct 19, 2023 am 11:02 AM

초보자이든 숙련된 전문가이든 C#을 마스터하면 경력을 쌓는 길이 열릴 것입니다.

여러 .NET 오픈 소스 AI 및 LLM 관련 프로젝트 프레임워크 공유 여러 .NET 오픈 소스 AI 및 LLM 관련 프로젝트 프레임워크 공유 May 06, 2024 pm 04:43 PM

오늘날 인공지능(AI) 기술 개발은 본격화되고 있으며, 다양한 분야에서 큰 잠재력과 영향력을 보여주고 있습니다. 오늘 Dayao는 여러분에게 몇 가지 참고 자료를 제공하고자 4개의 .NET 오픈 소스 AI 모델 LLM 관련 프로젝트 프레임워크를 공유할 것입니다. https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel은 OpenAI, Azure와 같은 대규모 언어 모델(LLM)을 통합하도록 설계된 오픈 소스 소프트웨어 개발 키트(SDK)입니다.

PHP 시작하기: 코드 리팩토링 PHP 시작하기: 코드 리팩토링 May 26, 2023 pm 04:21 PM

리팩토링은 PHP 코드를 작성할 때 매우 중요한 프로세스입니다. 애플리케이션이 성장함에 따라 코드 기반이 점점 커지고 읽고 유지 관리하기가 어려워집니다. 리팩토링은 이 문제를 해결하고 코드를 더욱 모듈화하고 체계화하고 확장 가능하게 만드는 것입니다. 코드를 리팩터링할 때 다음 측면을 고려해야 합니다. 코드 스타일 코드 스타일은 매우 중요한 포인트입니다. 코딩 스타일을 일관되게 유지하면 코드를 더 쉽게 읽고 유지 관리할 수 있습니다. PHP 코딩 표준을 따르고 일관성을 유지하십시오. PHP와 같은 코드 스타일 검사 도구를 사용해 보세요.

Java 개발: 코드 리팩토링 및 품질 평가 수행 방법 Java 개발: 코드 리팩토링 및 품질 평가 수행 방법 Sep 21, 2023 am 09:57 AM

Java 개발: 코드 리팩토링 및 품질 평가 소개: 소프트웨어 개발 과정에서 코드 리팩토링은 코드 품질과 유지 관리성을 향상시키는 중요한 수단 중 하나입니다. 코드를 리팩토링하면 코드를 더욱 우아하고 간결하며 이해하고 수정하기 쉽게 만들 수 있습니다. 하지만 리팩토링은 단순히 코드를 수정하는 것이 아니라 합리적이고 체계적인 사고가 필요한 과정입니다. 이 기사에서는 코드 리팩토링을 수행하는 방법을 소개하고 특정 코드 예제를 통해 이를 설명합니다. 또한 코드 품질을 평가하는 방법과 평가가 중요한 이유에 대해서도 논의합니다. 무거운 코드

Go 언어 반환 값 유형 추론 및 코드 리팩토링 Go 언어 반환 값 유형 추론 및 코드 리팩토링 Apr 30, 2024 am 08:06 AM

Go 언어 반환 값 유형 추론은 함수 반환 값 유형을 자동으로 추론하여 코드를 단순화하고 가독성을 향상시킵니다. 반환 값 형식은 생략할 수 있으며 컴파일러는 함수 본문의 실제 반환 값을 기반으로 자동으로 형식을 추론합니다. 명시적인 유형 선언을 제거하기 위해 기존 코드를 리팩터링하는 데 사용할 수 있습니다. 예를 들어 정수 배열의 합계를 계산하는 계산 토탈 함수는 funccalculateTotal(items[]int){}로 리팩터링될 수 있습니다.

코드 리팩토링 연습에 Go 언어를 사용하는 방법 코드 리팩토링 연습에 Go 언어를 사용하는 방법 Aug 02, 2023 am 10:05 AM

코드 리팩토링 연습을 위해 Go 언어를 사용하는 방법 소개: 소프트웨어 개발 과정에서 우리는 종종 코드 리팩토링 문제에 직면합니다. 코드 리팩토링은 코드 품질과 유지 관리성을 향상시키기 위해 기존 코드를 최적화하고 재구성하는 것을 의미합니다. 이 글에서는 코드 리팩토링 연습을 위해 Go 언어를 사용하는 방법을 소개하고 해당 코드 예제도 함께 제공됩니다. 1. 코드 리팩토링의 원칙 코드 리팩토링에 앞서 리팩토링이 원활하게 진행되도록 몇 가지 원칙을 명확히 할 필요가 있습니다. 다음은 몇 가지 중요한 코드 리팩토링 원칙입니다. 코드 기능의 일관성 유지: 리팩토링 후

See all articles