当前位置:网站首页>Declare war on uncivilized code I

Declare war on uncivilized code I

2022-06-21 13:42:00 Guo Mahua

A lot of people talk about technology architecture , But I can't bear to look straight at the code .

June to present , I took over and maintained several projects . I am mainly responsible for some projects , I will optimize and refactor little by little . Some items are hand - made changes . but , Just a little bit of code change ,VS The author will become himself .

I'm afraid of , I'm afraid the people behind me will point at my name and scold ,“ What is it all about !”

I am responsible for the docking of major real estate platforms in the market , The code in this article is developed according to the open document of the platform , It does not involve the company's data business .

I sent a code specification earlier , Some people spit on me , I quietly deleted it , Today I released it again .“ my “ C# Code specification

Among them, the one who has been roast most is :“ A function should preferably not exceed ten lines .”

Some people say : impossible , Few businesses can be written in ten lines !

Let me give some examples of code transformation , To explain why the shorter the function, the better .

You don't need to know anything about it in advance , The code can be clearer than the documentation :

Case a    123 House watching VR Push to real estate platforms such as anjuke  123 Look at the official documents

Code logic before transformation :

1. receive Rabbitmq Message concurrent processing , Get into TryPublishAsync  Method

 2.  High energy warning Horrible TryPublishAsync Method

        public async ValueTask TryPublishAsync(Guid houseId, string houseTypeValue, string houseTypeName, string matchKey, List<string> targetProviderNames,
            IDictionary<string, string> payload = null,
            CancellationToken cancellationToken = default)
        {
            targetProviderNames ??= new();
            var houseTask = await _taskRepository.GetAll()
                .Where(x => x.HouseId == houseId && x.StatusValue == 3)
                .OrderByDescending(x => x.FinishTime)
                .FirstOrDefaultAsync(cancellationToken);
            if (houseTask is null)
            {
                return;
            }
            foreach (var targetProviderName in targetProviderNames)
            {
                if (string.IsNullOrWhiteSpace(targetProviderName))
                {
                    continue;
                }
                var publishLog = new HousePublishLog()
                {
                    HouseId = houseTask.HouseId,
                    CaptureHouseTaskId = houseTask.Id,
                    HouseTypeValue = houseTypeValue,
                    HouseTypeName = houseTypeName,
                    SourceProviderName = houseTask.Provider,
                    CompanyId = houseTask.CompanyId,
                    CityId = houseTask.CityId,
                    TargetProviderName = targetProviderName
                };
                if (targetProviderName == "fangtianxia")
                {
                    try
                    {
                        var captureHouseTaskService = _captureHouseTaskServiceFactory.Create(publishLog.SourceProviderName);
                        var rootToken = await _tokenManager.GetAsync(publishLog.SourceProviderName, null, null, cancellationToken);
                        if (payload is not null && payload.Count is not 0)
                        {
                            string fangTianXiaCommunityName = null, fangTianXiaHouseId = null, fangTianXiaPurposeType = null;
                            payload?.TryGetValue("communityName", out fangTianXiaCommunityName);
                            payload?.TryGetValue("houseId", out fangTianXiaHouseId);
                            payload?.TryGetValue("purposeType", out fangTianXiaPurposeType);
                            if (string.IsNullOrWhiteSpace(fangTianXiaCommunityName))
                            {
                                fangTianXiaCommunityName = houseTask.CommunityName;
                            }
                            if (string.IsNullOrWhiteSpace(fangTianXiaHouseId))
                            {
                                fangTianXiaHouseId = null;
                            }
                            if (string.IsNullOrWhiteSpace(fangTianXiaPurposeType))
                            {
                                fangTianXiaPurposeType = null;
                            }
                            await captureHouseTaskService.PutFangtianxiaInfoAsync(rootToken, new(houseTask.ProviderPackageId, fangTianXiaCommunityName, fangTianXiaPurposeType, fangTianXiaHouseId), cancellationToken);
                        }
                        var notifyResult = await captureHouseTaskService.NotifyAsync(rootToken, new(houseTask.ProviderPackageId, houseTask.CompanyId.ToString(), targetProviderName), cancellationToken);
                        switch (notifyResult.notifyResult)
                        {
                            case 0:
                                publishLog.ErrorMessage = " Not notified ";
                                break;
                            case 1:
                                publishLog.Success = true;
                                publishLog.ErrorMessage = " Successful notification ";
                                break;
                            case 2:
                                publishLog.ErrorMessage = " The customer interface refused ";
                                break;
                            case 3:
                                publishLog.ErrorMessage = " Error in push ";
                                break;
                            default:
                                publishLog.ErrorMessage = $" Unknown notifyResult: {notifyResult}";
                                break;
                        }
                    }
                    catch (OneTwoThreeKanFangApiException e)
                    {
                        houseTask.ProviderTaskCancellationRequestContent = e.RequestContent;
                        houseTask.ProviderTaskCancellationResponseContent = e.ResponseContent;
                        publishLog.ErrorMessage = $" Attempt to publish Internet failed : state: {e.Response?.state}, message: {e.Message}";
                        throw;
                    }
                    finally
                    {
                        await _housePublishLogRepository.InsertAsync(publishLog);
                        await _messageBus.PublishAsync(new TryNotifyResponseMessage
                        {
                            Success = publishLog.Success,
                            ErrorMessage = publishLog.ErrorMessage,
                            HouseId = houseId.ToString()
                        }, cancellationToken: cancellationToken);
                    }
                }
                else if (targetProviderName == "58")
                {
                    try
                    {
                        var captureHouseTaskService = _captureHouseTaskServiceFactory.Create(publishLog.SourceProviderName);
                        var rootToken = await _tokenManager.GetAsync(publishLog.SourceProviderName, null, null, cancellationToken);
                        if ((!string.IsNullOrWhiteSpace(matchKey)) && (matchKey != houseId.ToString()))
                        {
                            await captureHouseTaskService.ChangeAnjukeBianHaoAsync(rootToken, new(houseTask.ProviderPackageId, matchKey), cancellationToken);
                        }
                        var notifyResult = await captureHouseTaskService.NotifyAsync(rootToken, new(houseTask.ProviderPackageId, houseTask.CompanyId.ToString(), targetProviderName), cancellationToken);
                        switch (notifyResult.notifyResult)
                        {
                            case 0:
                                publishLog.ErrorMessage = " Not notified ";
                                break;
                            case 1:
                                publishLog.Success = true;
                                publishLog.ErrorMessage = " Successful notification ";
                                break;
                            case 2:
                                publishLog.ErrorMessage = " The customer interface refused ";
                                break;
                            case 3:
                                publishLog.ErrorMessage = " Error in push ";
                                break;
                            default:
                                publishLog.ErrorMessage = $" Unknown notifyResult: {notifyResult}";
                                break;
                        }
                    }
                    catch (OneTwoThreeKanFangApiException e)
                    {
                        houseTask.ProviderTaskCancellationRequestContent = e.RequestContent;
                        houseTask.ProviderTaskCancellationResponseContent = e.ResponseContent;
                        publishLog.ErrorMessage = $" Attempt to publish Internet failed : state: {e.Response?.state}, message: {e.Message}";
                        throw;
                    }
                    finally
                    {
                        await _housePublishLogRepository.InsertAsync(publishLog);
                        await _messageBus.PublishAsync(new TryNotifyResponseMessage
                        {
                            Success = publishLog.Success,
                            ErrorMessage = publishLog.ErrorMessage,
                            HouseId = houseId.ToString()
                        }, cancellationToken: cancellationToken);
                    }
                }

            }

        }

3. It's not over yet. , The above is just the business process code , The specific docking code is the following paragraph :

        public async ValueTask<NotifyHouseTaskResponseDto> NotifyAsync(TokenDto rootToken, NotifyHouseTaskRequestDto request, CancellationToken cancellationToken = default)
        {
            var options = _oneTwoThreeKanFangProviderOptionsAccessor.Value;
            var notifyConfigId = request.channel switch
            {
                "58" => options.AnJuKe?.NotifyConfigId,
                "fangtianxia" => options.FangTianXia?.NotifyConfigId,
                _ => default(string),
            };
            if (string.IsNullOrWhiteSpace(notifyConfigId))
            {
                throw new AppException(" Not configured notifyConfigId");
            }
            string payload = "{}";

            if (string.IsNullOrWhiteSpace(request.payloadType))
            {
                payload = [email protected]"{
   {""type"":""{request.payloadType}""}}";
            }
            using var http = _httpClientFactory.CreateClient(nameof(OneTwoThreeKanFangCaptureHouseTaskService));
            var response = await http.V2_houseTask_AddNewNotifyTaskByPackageID(
                options.ApiEndpoint,
                rootToken.token,
                notifyConfigId,
                request.packageId,
                logger: _logger,
                cancellationToken: cancellationToken
            );
            if (response is null)
            {
                throw new AppException(" Failed to request house source data package push ");
            }
            return new(response.id, response.notifyResult ?? -1, response.notifyConfigId, response.houseTaskId);
        }

        public async ValueTask<PutFangtianxiaInfoResponseDto> PutFangtianxiaInfoAsync(TokenDto rootToken, PutFangtianxiaInfoRequestDto request, CancellationToken cancellationToken = default)
        {
            var options = _oneTwoThreeKanFangProviderOptionsAccessor.Value;
            var notifyConfigId = options.FangTianXia?.NotifyConfigId;
            if (string.IsNullOrWhiteSpace(notifyConfigId))
            {
                throw new AppException(" Not configured notifyConfigId");
            }
            using var http = _httpClientFactory.CreateClient(nameof(OneTwoThreeKanFangCaptureHouseTaskService));
            var response = await http.V2_houseTask_PutFangtianxiaInfo(
                options.ApiEndpoint,
                rootToken.token,
                request.packageId,
                request.communityName,
                request.houseId,
                request.purposeType,
                logger: _logger,
                cancellationToken: cancellationToken
            );
            if (response is null)
            {
                throw new AppException(" Failed to modify anjuke number ");
            }
            return new(response?.AdditionalData);
        }

I believe that no one knows what they are writing at a glance , I am also , Like a child who can't describe clearly .

So I clenched my teeth and reread 123 House viewing document , Rewrote VR Push content .

Code logic after transformation :

1. receive MQ Message concurrent processing

  Here to MQ The message body is greatly simplified , A large number of useless fields have been deleted , And the field name is modified , More in line with   The overall logic of the project .

 2. Will be huge and bloated TryPublishAsync Method is split into vrPushService, And provide release VR To the function of anjuke and SouFun , See above .

The original TryPublishAsync Functions are extremely bloated , Here we will disassemble them one by one :

  1. VR package Id Query for : Put it in MQ Query in the message receiving method , And call... As a parameter VRPushService Related methods .
  2. logging : 123 The backstage provides log query function , Delete directly .
  3. Token obtain : There is no need to act public Methods provided externally , Hidden as a private method in VRPushService among .
  4. establish VR Push some related predecessor tasks : There is no need to act public Methods provided externally , Hidden as a private method in VRPushService among .
  5. establish VR Push task

Above contents , The original code relied on at least three services to provide , And actually use factory methods to get related business processing classes , This over encapsulates , What is the point of using dependency injection ?

There's no show here Token The code of the acquisition and the predecessor task implements , Can't bear to look straight ahead. .

Transformed VRPushService.cs  No more than ten lines per function , Logic is clearly visible

    public class VRPushService : IVRPushService
    {
        private readonly IOptions<OneTwoThreeKanFangProviderOptions> _option;
        public VRPushService(IOptions<OneTwoThreeKanFangProviderOptions> option)
        {
            _option = option;
        }

        /// <summary>
        /// VR Push fangtianxia 
        /// </summary>
        /// <param name="packageId"></param>
        /// <param name="listingId"></param>
        /// <param name="communityName"></param>
        /// <param name="purposeType"></param>
        /// <returns></returns>
        public async Task<ResultDto> PushFTXAsync(string packageId, string listingId, string communityName, string purposeType)
        {
            var token = await GetTokenAsync();
            var preResult = await FTXPreTask(token, packageId, listingId, communityName, purposeType);
            if (preResult.State != 200)
                throw new Exception($"{preResult.Msg}-{preResult.Payload}");
            return await CreateTask(token, packageId, _option.Value.FangTianXia.NotifyConfigId);
        }

        /// <summary>
        /// VR push 58 Anju 
        /// </summary>
        /// <param name="packageId"></param>
        /// <param name="listingCode"></param>
        /// <returns></returns>
        public async Task<ResultDto> Push58Async(string packageId, string listingCode)
        {
            var token = await GetTokenAsync();
            var preResult = await _58PreTask(token, packageId, listingCode);
            if (preResult.State != 200)
                throw new Exception($"{preResult.Msg}-{preResult.Payload}");
            return await CreateTask(token, packageId, _option.Value.AnJuKe.NotifyConfigId);
        }

        /// <summary>
        /// VR Internet push 
        /// </summary>
        /// <param name="token"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public async Task<ResultDto> CreateTask(string token, string packageId, string notifyconfigId)
        {
            var content = new Dictionary<string, string>
            {
                { "packageId",packageId},
                { "notifyconfigId",notifyconfigId},
                { "forcePush", "true"}
            };
            return await PostAsync(token, $"{_option.Value.ApiEndpoint}/v2/houseTask/AddNewNotifyTaskByPackageID", content);
        }

        /// <summary>
        /// 58VR Push predecessors 
        /// </summary>
        /// <param name="token"></param>
        /// <param name="packageId"></param>
        /// <param name="listingCode"></param>
        /// <returns></returns>
        private async Task<ResultDto> _58PreTask(string token, string packageId, string listingCode)
        {
            var content = new Dictionary<string, string>
            {
                { "packageId", packageId},
                { "anjukeBianHao", listingCode},
            };
            return await PostAsync(token, $"{_option.Value.ApiEndpoint}/v2/houseTask/putAnjukeBianHao", content);
        }

        /// <summary>
        ///  Fangtianxia VR Push predecessors 
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        private async Task<ResultDto> FTXPreTask(string token, string packageId, string listingId, string communityName, string purposeType)
        {
            var content = new Dictionary<string, string>
                {
                { "packageId", packageId},
                { "communityName", communityName},
                { "purposeType", purposeType},
                { "houseId", listingId}
            };
            return await PostAsync(token, $"{_option.Value.ApiEndpoint}/v2/houseTask/PutFangtianxiaInfo", content);
        }

        private async Task<ResultDto> PostAsync(string token, string url, Dictionary<string, string> content)
        {
            using var httpClient = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Post, url)
            {
                Content = new FormUrlEncodedContent(content)
            };

            httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", token);
            var response = await httpClient.SendAsync(request);

            return await response.Content.ReadFromJsonAsync<ResultDto>();
        }

        private async Task<string> GetTokenAsync()
        {
            using var httpClient = new HttpClient();
            var result = await httpClient.GetFromJsonAsync<ResultDto>($"{_option.Value.ApiEndpoint}/v2/Authorization/GetAccessToken?" +
                $"AuthKey={_option.Value.Account}&AuthValue={_option.Value.Password}&ClientEdtion=ps_1.0.0");

            return result.Entity<TokenDto>().Token;
        }
    }

  Transformation completed , And online . alas , Heart tired !

原网站

版权声明
本文为[Guo Mahua]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202221433592085.html