iT邦幫忙

2024 iThome 鐵人賽

DAY 17
1
IT 管理

30天從版控到code review的實踐指南系列 第 17

Day.17 Code Review:功能邏輯-下篇

  • 分享至 

  • xImage
  •  

今天仍然是功能邏輯的 Code Review 篇,今天用 C# 來撰寫範例。

範例 1:將線段(Geometry)的路徑轉換為 WKT(Well-Known Text)格式,並使用 DbGeometry 物件進行後續處理。


原程式碼:

public static string ConvertPathsToWKT(List<List<List<double>>> path)
        {
            if (path == null || path.Count == 0)
            {
                return string.Empty;
            }

            var lineStringBuilder = new StringBuilder("LINESTRING (");
            var firstPath = path[0];

            for (int i = 0; i < firstPath.Count; i++)
            {
                lineStringBuilder.Append(firstPath[i][0]);
                lineStringBuilder.Append(" ");
                lineStringBuilder.Append(firstPath[i][1]);

                if (i < firstPath.Count - 1)
                {
                    lineStringBuilder.Append(", ");
                }
            }

            lineStringBuilder.Append(")");

            var geometry = DbGeometry.FromText(lineStringBuilder.ToString(), 4326);
            return geometry.AsText();
        }

Code Review 建議:


  1. 加強資料驗證與錯誤處理

    目前程式只檢查了 path 是否為 null 或空,但沒有檢查 path 中是否存在無效資料。例如,每個 List 是否包含至少兩個 x 坐標與 y 坐標。

    建議修改:

    增加對內層數據的驗證,確保每一層的結構和數據完整。

  2. 變數命名改進

    將 firstPath 變數名稱修改為更具描述性的名稱 pathSegment,以提高可讀性和可維護性。

更新後程式碼:


public static string ConvertPathsToWKT(List<List<List<double>>> path)
{
    if (path == null || path.Count == 0)
    {
        return string.Empty;
    }

    // 將 firstPath 改為 pathSegment,代表單一條路徑
    var pathSegment = path[0];
    var lineStringBuilder = new StringBuilder("LINESTRING (");

    for (int i = 0; i < pathSegment.Count; i++)
    {
        // 檢查每個點是否包含兩個座標(X, Y)
        if (pathSegment[i].Count < 2)
        {
            throw new ArgumentException("Each path point must contain exactly two coordinates (X, Y).");
        }

        lineStringBuilder.Append(pathSegment[i][0]); // X 座標
        lineStringBuilder.Append(" ");
        lineStringBuilder.Append(pathSegment[i][1]); // Y 座標

        if (i < pathSegment.Count - 1)
        {
            lineStringBuilder.Append(", ");
        }
    }

    lineStringBuilder.Append(")");

    var geometry = DbGeometry.FromText(lineStringBuilder.ToString(), 4326);
    return geometry.AsText();

範例 2:刪除線段資訊

原始程式碼:

public static async Task<StatusResponse> DeleteBDLineIndicatorInfo(string cGDOC_PK, int ID, string INDICATIVE_METHOD)
        {
            StatusResponse statusResponse = new StatusResponse();
            BDLINE_INDICATOR_INFO bdLineIndicatorInfoResult = new BDLINE_INDICATOR_INFO();
            switch (INDICATIVE_METHOD)
            {
                case "0":
                    bdLineIndicatorInfoResult = (await GetBDLineIndicatorClassfiedResult(cGDOC_PK)).bdLineIndicatorInfoList_Baseless.FirstOrDefault(x => x.ID == ID);
                    break;

                case "1":
                    bdLineIndicatorInfoResult = (await GetBDLineIndicatorClassfiedResult(cGDOC_PK)).bdLineIndicatorInfoList_Road.FirstOrDefault(x => x.ID == ID);
                    break;

                case "2":
                    bdLineIndicatorInfoResult = (await GetBDLineIndicatorClassfiedResult(cGDOC_PK)).bdLineIndicatorInfoList_Cadas.FirstOrDefault(x => x.ID == ID);
                    break;
            }
              
            if (bdLineIndicatorInfoResult != null)
            {
                try
                {
                    string conStr = ConfigurationManager.ConnectionStrings["HLUPSQLConnStr"].ConnectionString;
                    string deleteSql = @"DELETE FROM BDLINE_INDICATOR_INFO WHERE cGDOC_PK = @cGDOC_PK AND ID = @ID AND INDICATIVE_METHOD = @INDICATIVE_METHOD";

                    using (SqlConnection conn = new SqlConnection(conStr))
                    {
                        await conn.ExecuteAsync(deleteSql, new { cGDOC_PK, ID, INDICATIVE_METHOD });
                    }

                    statusResponse.STATUS = "1";
                    statusResponse.MESSAGE = $"刪除建築指示線資訊成功";
                }
                catch (Exception ex)
                {
                    statusResponse.STATUS = "0";
                    statusResponse.MESSAGE = $"{ex.Message}";
                }
            }

            return statusResponse;
        }
        

Code Review 建議:


  1. 合併重複的 GetBDLineIndicatorClassfiedResult 呼叫、精簡 switch 邏輯

    避免了每個 case 中重複進行非同步操作,提升效能。再根據 INDICATIVE_METHOD 來進行資料選擇。

  2. 加強錯誤處理:即使資料的查詢已經處理過,還是可將為 null 的狀態加入程式碼,提高程式碼的穩定性和可讀性。

更新後程式碼

public static async Task<StatusResponse> DeleteBuildingLineIndicatorInfoByMethod(string cGDOC_PK, int ID, string INDICATIVE_METHOD)
{
    StatusResponse statusResponse = new StatusResponse();
    BDLINE_INDICATOR_INFO bdLineIndicatorInfoResult = new BDLINE_INDICATOR_INFO();

    // 僅呼叫一次 GetBDLineIndicatorClassfiedResult,避免重複的非同步操作
    var bdLineIndicatorResult = await GetBDLineIndicatorClassfiedResult(cGDOC_PK);

    // 根據 INDICATIVE_METHOD 取得相應的資料清單
    switch (INDICATIVE_METHOD)
    {
        case "0":
            bdLineIndicatorInfoResult = bdLineIndicatorResult.bdLineIndicatorInfoList_Baseless.FirstOrDefault(x => x.ID == ID);
            break;

        case "1":
            bdLineIndicatorInfoResult = bdLineIndicatorResult.bdLineIndicatorInfoList_Road.FirstOrDefault(x => x.ID == ID);
            break;

        case "2":
            bdLineIndicatorInfoResult = bdLineIndicatorResult.bdLineIndicatorInfoList_Cadas.FirstOrDefault(x => x.ID == ID);
            break;
            
        default:
            statusResponse.STATUS = "0";
            statusResponse.MESSAGE = "Invalid INDICATIVE_METHOD.";
            return statusResponse;
    }

    if (bdLineIndicatorInfoResult != null)
    {
        try
        {
            string conStr = ConfigurationManager.ConnectionStrings["HLUPSQLConnStr"].ConnectionString;
            string deleteSql = @"DELETE FROM BDLINE_INDICATOR_INFO WHERE cGDOC_PK = @cGDOC_PK AND ID = @ID AND INDICATIVE_METHOD = @INDICATIVE_METHOD";

            using (SqlConnection conn = new SqlConnection(conStr))
            {
                await conn.ExecuteAsync(deleteSql, new { cGDOC_PK, ID, INDICATIVE_METHOD });
            }

            statusResponse.STATUS = "1";
            statusResponse.MESSAGE = "刪除建築指示線資訊成功";
        }
        catch (Exception ex)
        {
     **       statusResponse.STATUS = "0";
            statusResponse.MESSAGE = $"刪除失敗: {ex.Message}";
        }
    }
    // 加強錯誤狀態處理
    else
    {
        statusResponse.STATUS = "0";
        statusResponse.MESSAGE = "未找到相應的資料。";
    }

    return statusResponse;
}

意外地放了颱風假,大家要乖乖待在家裡/images/emoticon/emoticon43.gif


上一篇
Day.16 Code Review:功能邏輯-上篇
下一篇
Day 18. Code Review 程式碼風格-規則篇
系列文
30天從版控到code review的實踐指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言