快轉到主要內容

程式進化史

·2265 字·5 分鐘·
PolloChang
作者
PolloChang
我是一隻雞

筆記一下這些年我寫的糞 code 的優化流程

一開始寫的
#

被檢測為 CyclomaticComplexity 。程式如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
package work.pollochang.twgcb

import grails.gorm.transactions.Transactional
import grails.web.servlet.mvc.GrailsParameterMap
import org.hibernate.criterion.CriteriaSpecification
import org.hibernate.type.StandardBasicTypes
import work.pollochang.util.PFilterResult
import work.pollochang.util.PFilterType

/**
 * TWGCB 資料處理
 */
@Transactional
class TwGcbService {

    /**
     * 查詢
     * @param params
     * @param filterType
     * @return 查詢結果
     */
    PFilterResult filter(
            GrailsParameterMap params,
            PFilterType filterType = PFilterType.DEFAULT
    ) {
        PFilterResult pFilterResult = new PFilterResult()

        params.max = (params.max ?: '10').toInteger()
        params.offset = (params?.offset ?: '0').toInteger()

        List<Twgcb> twgcbList =  Twgcb.createCriteria().list(params) {
            resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)

            switch (filterType) {
                case PFilterType.QUICK:
                    projections {
                        property('id', 'id')
                        property('twgcbId', 'twgcbId')
                        property('cname', 'cname')
                        property('typeDesc', 'typeDesc')
                    }
                    break
                case PFilterType.FULL:
                    projections {
                        property('id', 'id')
                        property('twgcbId', 'twgcbId')
                        property('cname', 'cname')
                        property('type', 'type')
                        property('explanation', 'explanation')
                        property('instructions', 'instructions')
                        property('defaultValue', 'defaultValue')
                        property('remark', 'remark')
                        property('typeDesc', 'typeDesc')
                    }
                    break
                case PFilterType.VIEW:
                    projections {
                        property('id', 'id')
                        property('twgcbId', 'twgcbId')
                        property('cname', 'cname')
                        property('explanation', 'explanation')
                        property('instructions', 'instructions')
                        property('defaultValue', 'defaultValue')
                        property('remark', 'remark')
                        property('typeDesc', 'typeDesc')
                    }
                    break
                default:
                    projections {
                        property('twgcbId', 'twgcbId')
                        property('cname', 'cname')
                        sqlProjection("(select t.cdesc from bs_select t where t.type = 'twgcb_type' and t.code = this_.type ) typeDesc", ['typeDesc'], [StandardBasicTypes.STRING])
                    }
            }

            if (params?.twgcbId) {
                eq('twgcbId',params?.twgcbId)
            }

            if (params?.type) {
                int type = params?.type as int
                eq('type',type)
            }

            if (params?.id) {
                long id = params?.id as long
                eq('id',id)
            }

            if (params?.cname) {
                ilike('cname', "%${params?.cname}%")
            }

            order('twgcbId', 'asc')
        } as List<Twgcb>

        pFilterResult.domainList = twgcbList
        pFilterResult.totalCount = twgcbList.totalCount?:0

        return pFilterResult

    }
}

第一次優化
#

將顯示欄位邏輯拉出
#

  • 更改前
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* 查詢
* @param params
* @param filterType
* @return 查詢結果
*/
PFilterResult filter(
    GrailsParameterMap params,
    PFilterType filterType = PFilterType.DEFAULT
) {

    // 程式碼部份省略

    switch (filterType) {
      case PFilterType.QUICK:
          projections {
              property('id', 'id')
              property('twgcbId', 'twgcbId')
              property('cname', 'cname')
              property('typeDesc', 'typeDesc')
          }
          break
      case PFilterType.FULL:
          projections {
              property('id', 'id')
              property('twgcbId', 'twgcbId')
              property('cname', 'cname')
              property('type', 'type')
              property('explanation', 'explanation')
              property('instructions', 'instructions')
              property('defaultValue', 'defaultValue')
              property('remark', 'remark')
              property('typeDesc', 'typeDesc')
          }
          break
      case PFilterType.VIEW:
          projections {
              property('id', 'id')
              property('twgcbId', 'twgcbId')
              property('cname', 'cname')
              property('explanation', 'explanation')
              property('instructions', 'instructions')
              property('defaultValue', 'defaultValue')
              property('remark', 'remark')
              property('typeDesc', 'typeDesc')
          }
          break
      default:
          projections {
              property('twgcbId', 'twgcbId')
              property('cname', 'cname')
              sqlProjection("(select t.cdesc from bs_select t where t.type = 'twgcb_type' and t.code = this_.type ) typeDesc", ['typeDesc'], [StandardBasicTypes.STRING])
          }
    }

    // 程式碼部份省略

}
  • 更改後
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* 查詢
* @param params
* @param filterType
* @return 查詢結果
*/
PFilterResult filter(
    GrailsParameterMap params,
    PFilterType filterType = PFilterType.DEFAULT
) {

    // 程式碼部份省略

    switch (filterType) {
        case PFilterType.QUICK:
            Closure projection = (Closure) quickProjection.clone()
            projection.delegate = delegate
            projection()
            break
        case PFilterType.FULL:
            Closure projection = (Closure) fullProjection.clone()
            projection.delegate = delegate
            projection()
            break
        case PFilterType.VIEW:
            Closure projection = (Closure) viewProjection.clone()
            projection.delegate = delegate
            projection()
            break
        default:
            Closure projection = (Closure) defaultProjection.clone()
            projection.delegate = delegate
            projection()
    }

    // 程式碼部份省略

}

/**
  * 快速顯示欄位
  */
private Closure quickProjection =  {
}

/**
  * 完整顯示欄位
  */
private Closure fullProjection =  {
}

/**
  * 檢視單筆資料欄位
  */
private Closure viewProjection =  {
}

/**
  * 預設顯示欄位
  */
private Closure defaultProjection =  {
}

將查詢條件修飾
#

  • 更改前
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 查詢
* @param params
* @param filterType
* @return 查詢結果
*/
PFilterResult filter(
    GrailsParameterMap params,
    PFilterType filterType = PFilterType.DEFAULT
) {

    // 程式碼部份省略

    if (params?.twgcbId) {
        eq('twgcbId',params?.twgcbId)
    }

    if (params?.type) {
        int type = params?.type as int
        eq('type',type)
    }

    if (params?.id) {
        long id = params?.id as long
        eq('id',id)
    }

    if (params?.cname) {
        ilike('cname', "%${params?.cname}%")
    }

    // 程式碼部份省略

}
  • 更改後
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 查詢
* @param params
* @param filterType
* @return 查詢結果
*/
PFilterResult filter(
    GrailsParameterMap params,
    PFilterType filterType = PFilterType.DEFAULT
) {

    // 程式碼部份省略

    params.each { key, value ->
        if(value){
            switch (key) {
                case 'twgcbId':
                    eq('twgcbId', value)
                    break
                case 'type':
                    eq('type',value as int)
                    break
                case 'id':
                    eq('id', value as long)
                    break
                case 'cname':
                    ilike('cname', "%${value}%")
                    break
            }
        }
    }

    // 程式碼部份省略

}

完整程式碼如下

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package work.pollochang.twgcb

import grails.gorm.transactions.Transactional
import grails.web.servlet.mvc.GrailsParameterMap
import org.hibernate.criterion.CriteriaSpecification
import org.hibernate.type.StandardBasicTypes
import work.pollochang.util.PFilterResult
import work.pollochang.util.PFilterType

/**
 * TWGCB 資料處理
 */
@Transactional
class TwGcbService {

    /**
     * 查詢
     * @param params
     * @param filterType
     * @return 查詢結果
     */
    PFilterResult filter(
            GrailsParameterMap params,
            PFilterType filterType = PFilterType.DEFAULT
    ) {
        PFilterResult pFilterResult = new PFilterResult()

        params.max = (params.max ?: '10').toInteger()
        params.offset = (params?.offset ?: '0').toInteger()

        List<Twgcb> twgcbList =  Twgcb.createCriteria().list(params) {
            resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)

            switch (filterType) {
                case PFilterType.QUICK:
                    Closure projection = (Closure) quickProjection.clone()
                    projection.delegate = delegate
                    projection()
                    break
                case PFilterType.FULL:
                    Closure projection = (Closure) fullProjection.clone()
                    projection.delegate = delegate
                    projection()
                    break
                case PFilterType.VIEW:
                    Closure projection = (Closure) viewProjection.clone()
                    projection.delegate = delegate
                    projection()
                    break
                default:
                    Closure projection = (Closure) defaultProjection.clone()
                    projection.delegate = delegate
                    projection()
            }

            params.each { key, value ->
                if(value){
                    switch (key) {
                        case 'twgcbId':
                            eq('twgcbId', value)
                            break
                        case 'type':
                            eq('type',value as int)
                            break
                        case 'id':
                            eq('id', value as long)
                            break
                        case 'cname':
                            ilike('cname', "%${value}%")
                            break
                    }
                }
            }

            order('twgcbId', 'asc')
        } as List<Twgcb>

        pFilterResult.domainList = twgcbList
        pFilterResult.totalCount = twgcbList.totalCount?:0

        return pFilterResult

    }

    /**
     * 快速顯示欄位
     */
    private Closure quickProjection =  {
        projections {
            property('id', 'id')
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            property('typeDesc', 'typeDesc')
        }
    }

    /**
     * 完整顯示欄位
     */
    private Closure fullProjection =  {
        projections {
            property('id', 'id')
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            property('type', 'type')
            property('explanation', 'explanation')
            property('instructions', 'instructions')
            property('defaultValue', 'defaultValue')
            property('remark', 'remark')
            property('typeDesc', 'typeDesc')
        }
    }

    /**
     * 檢視單筆資料欄位
     */
    private Closure viewProjection =  {
        projections {
            property('id', 'id')
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            property('explanation', 'explanation')
            property('instructions', 'instructions')
            property('defaultValue', 'defaultValue')
            property('remark', 'remark')
            property('typeDesc', 'typeDesc')
        }
    }

    /**
     * 預設顯示欄位
     */
    private Closure defaultProjection =  {
        projections {
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            sqlProjection("(select t.cdesc from bs_select t where t.type = 'twgcb_type' and t.code = this_.type ) typeDesc", ['typeDesc'], [StandardBasicTypes.STRING])
        }
    }
}

第二次優化
#

優化 projection 程式片段
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 查詢
* @param params
* @param filterType
* @return 查詢結果
*/
PFilterResult filter(
    GrailsParameterMap params,
    PFilterType filterType = PFilterType.DEFAULT
) {

    // 程式碼部份省略

    switch (filterType) {
        case PFilterType.QUICK:
            Closure projection = (Closure) quickProjection.clone()
            projection.delegate = delegate
            projection()
            break
        case PFilterType.FULL:
            Closure projection = (Closure) fullProjection.clone()
            projection.delegate = delegate
            projection()
            break
        case PFilterType.VIEW:
            Closure projection = (Closure) viewProjection.clone()
            projection.delegate = delegate
            projection()
            break
        default:
            Closure projection = (Closure) defaultProjection.clone()
            projection.delegate = delegate
            projection()
    }

    // 程式碼部份省略

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

/**
* 查詢
* @param params
* @param filterType
* @return 查詢結果
*/
PFilterResult filter(
    GrailsParameterMap params,
    PFilterType filterType = PFilterType.DEFAULT
) {

    // 程式碼部份省略

    Closure projection = getProjectionClosure(filterType)
    if (projection) {
        projection.delegate = delegate
        projection()
    }

    // 程式碼部份省略

}


/**
  * 依 定義查詢種類 回傳查詢顯示欄位
  * @param filterType 定義查詢種類
  * @return 查詢顯示欄位
  */
private Closure getProjectionClosure(PFilterType filterType) {

    switch (filterType) {
        case PFilterType.QUICK:
            return quickProjection
        case PFilterType.FULL:
            return fullProjection
        case PFilterType.VIEW:
            return viewProjection
        default:
            return defaultProjection
    }

}

完整程式碼如下

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package work.pollochang.twgcb

import grails.gorm.transactions.Transactional
import grails.web.servlet.mvc.GrailsParameterMap
import org.hibernate.criterion.CriteriaSpecification
import org.hibernate.type.StandardBasicTypes
import work.pollochang.util.PFilterResult
import work.pollochang.util.PFilterType

/**
 * TWGCB 資料處理
 */
@Transactional
class TwGcbService {

    /**
     * 查詢
     * @param params
     * @param filterType
     * @return 查詢結果
     */
    PFilterResult filter(
            GrailsParameterMap params,
            PFilterType filterType = PFilterType.DEFAULT
    ) {
        PFilterResult pFilterResult = new PFilterResult()

        params.max = (params.max ?: '10').toInteger()
        params.offset = (params?.offset ?: '0').toInteger()

        List<Twgcb> twgcbList =  Twgcb.createCriteria().list(params) {
            resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)

            Closure projection = getProjectionClosure(filterType)
            if (projection) {
                projection.delegate = delegate
                projection()
            }

            params.each { key, value ->
                if(value){
                    switch (key) {
                        case 'twgcbId':
                            eq('twgcbId', value)
                            break
                        case 'type':
                            eq('type',value as int)
                            break
                        case 'id':
                            eq('id', value as long)
                            break
                        case 'cname':
                            ilike('cname', "%${value}%")
                            break
                    }
                }
            }

            order('twgcbId', 'asc')
        } as List<Twgcb>

        pFilterResult.domainList = twgcbList
        pFilterResult.totalCount = twgcbList.totalCount?:0

        return pFilterResult

    }

    /**
     * 依 定義查詢種類 回傳查詢顯示欄位
     * @param filterType 定義查詢種類
     * @return 查詢顯示欄位
     */
    private Closure getProjectionClosure(PFilterType filterType) {
        switch (filterType) {
            case PFilterType.QUICK:
                return quickProjection
            case PFilterType.FULL:
                return fullProjection
            case PFilterType.VIEW:
                return viewProjection
            default:
                return defaultProjection
        }
    }

    /**
     * 快速顯示欄位
     */
    private Closure quickProjection =  {
        projections {
            property('id', 'id')
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            property('typeDesc', 'typeDesc')
        }
    }

    /**
     * 完整顯示欄位
     */
    private Closure fullProjection =  {
        projections {
            property('id', 'id')
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            property('type', 'type')
            property('explanation', 'explanation')
            property('instructions', 'instructions')
            property('defaultValue', 'defaultValue')
            property('remark', 'remark')
            property('typeDesc', 'typeDesc')
        }
    }

    /**
     * 檢視單筆資料欄位
     */
    private Closure viewProjection =  {
        projections {
            property('id', 'id')
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            property('explanation', 'explanation')
            property('instructions', 'instructions')
            property('defaultValue', 'defaultValue')
            property('remark', 'remark')
            property('typeDesc', 'typeDesc')
        }
    }

    /**
     * 預設顯示欄位
     */
    private Closure defaultProjection =  {
        projections {
            property('twgcbId', 'twgcbId')
            property('cname', 'cname')
            sqlProjection("(select t.cdesc from bs_select t where t.type = 'twgcb_type' and t.code = this_.type ) typeDesc", ['typeDesc'], [StandardBasicTypes.STRING])
        }
    }

}