最佳体验请使用Chrome67及以上版本、火狐、Edge、Safari浏览器 ×

创建银行
创建开票

    编程规范123.docx

    作者:雷建明@芯速配 阅读24 2024/09/29 07:04:33 文章 原创 公开


    目录

    1. 跨域Rpc对接

    2. 复杂的结构体定义:

    3. 项目内公共代码、私有代码目录命名建议

    4. 【建议1】单个文件长度不超过500行。

    5. 【建议2】单个函数长度不超过50行。

    6. 【规则3】单个函数圈复杂度最好不要超过10,禁止超过15。

    7. 【规则4】单行语句不能过长,如不能拆分需要分行写。一行最多120个字符。

    8. 【建议5】函数中缩进嵌套必须小于等于3层

    9. WALI构建提供代码检查报告:代码量、代码覆盖率、圈复杂度等

    10. 代码分层按工程包依赖

    11. 测试代码与代码覆盖率

    12. 项目完成组织开发代码评审,架构,产品,测试多个维度评价:

    13. 代码圈复杂度

    13.1. 问题提出:

    13.2. 圈复杂度标准

    13.3. 安装圈复杂度分析工具

    13.4. CMS圈复杂度

    13.5. Order圈复杂度

    13.6. General圈复杂度

    13.7. HUB 圈复杂度

    13.8. CONTACT圈复杂度

     

     

    1. 跨域Rpc对接

    目前各域代码重复COPY:

    image.png 

    已经有general-common公共工程,网站管理在使用、对齐

     

    2. 复杂的结构体定义:

    ES一般是多个表组成的结构,字段较多,目前ES的形式就是一张宽表、不是聚合根的形式,

    可读性太差!

    type CmsColumnEs struct {
        ColumnId int64 `json:"column_id"`
        /*    */
        ShopId int64 `json:"shop_id"` //商圈
        /*    */
        EditorId int64 `json:"editor_id"` //栏目经理
        /*    */
        AdEditorId int64 `json:"ad_editor_id"` //广告经理
        /*    */
        PublisherSpuId int64 `json:"publisher_spu_id"`
        /*    */
        LayoutId int64 `json:"layout_id"`
        /*    */
        SpuCategShopCategId int64 `json:"spu_categ_shop_categ_id"` //类型A
        /*    */
        ParentId int64 `json:"parent_id"` //上级栏目

        /*    */
        Name string `json:"name"` //栏目名称
        /*    */
        Code string `json:"code"`
        /*    */
        Slug string `json:"slug"`
        /*    */
        Description string `json:"description"` //描述
        /*    */
        Path string ` json:"path"`
        /*    */
        IsVirtual bool `son:"is_virtual"`

        IsFixed bool `json:"is_fixed"`
        /*    */
        IsDefault bool `json:"is_default"`
        /*    */
        Domain string `json:"domain"`
        /*    */
        ResourceName string `json:"resource_name"`
        /*    */
        Active bool `json:"active"` //状态
        /*    */
        ListOrder int32 ` json:"list_order"`
        /*    */
        SeoTitle string `json:"seo_title"`
        /*    */
        SeoTag string ` json:"seo_tag"`
        /*    */
        SeoDescription string `json:"seo_description"`
        /*    */
        Topic string `json:"topic"`
        /*    */
        CreatedAt time.Time `json:"created_at"`
        /*    */
        CreatedBy int64 `json:"created_by"`
        /*    */
        UpdatedAt time.Time `json:"updated_at"`

        UpdatedAtInt int64 `json:"updated_at_int"` //更新时间

        VisitCount int32 ` json:"visit_count"` //访问量

        ReadCount int32 ` json:"read_count"` //阅读次数

        LikeCount int32 `json:"like_count"` //点赞次数

        ContentCount int32 `json:"content_count"` //

        CollectCount int32 `json:"collect_count"` //收藏次数

        ShareCount int32 `json:"share_count"` //分享次数

        CommentCount int32 `json:"comment_count"` //评论次数

        KeywordId []int64 `json:"keyword_id"` /*关键词*/

        ReplyCount int32 `json:"reply_count"` //应答次数

        ParentName string `json:"parent_name"` //上级栏目
        /*    */
        UpdatedBy int64 `json:"updated_by"`
        /*    */
        DeletedAt time.Time `json:"deleted_at"`
        /*    */
        DeletedBy                         int64              `json:"deleted_by"`
        Banner                            string             `json:"banner"`
        ContentList                       string             `json:"content_list"`
        Sidebar1                          string             `json:"sidebar1"`
        Sidebar2                          string             `json:"sidebar2"`
        Sidebar3                          string             `json:"sidebar3"`
        Sidebar4                          string             `json:"sidebar4"`
        Sidebar5                          string             `json:"sidebar5"`
        Sidebar6                          string             `json:"sidebar6"`
        AdvertisingBanner                 int64              `json:"advertising_banner"`
        AdvertisingContent                int64              `json:"advertising_content"`
        AdvertisingNewest                 int64              `json:"advertising_newest"`
        AdvertisingHot                    int64              `json:"advertising_hot"`
        AdvertisingRecommend              int64              `json:"advertising_recommend"`
        AdvertisingNotice                 int64              `json:"advertising_notice"`
        AdvertisingContentDetails         int64              `json:"advertising_content_details"`
        AdvertisingContentDisplayPage     int64              `json:"advertising_content_display_page"`
        LayoutTypeId                      int64              `json:"layout_type_id"`
        EditorIdName                      string             `json:"editor_id_name"`
        IsPlatform                        bool               `json:"is_platform"`
        AdEditorName                      string             `json:"ad_editor_name"`
        AdvertisingBannerName             string             `json:"advertising_banner_name"`
        AdvertisingContentName            string             `json:"advertising_content_name"`
        AdvertisingNewestName             string             `json:"advertising_newest_name"`
        AdvertisingHotName                string             `json:"advertising_hot_name"`
        AdvertisingRecommendName          string             `json:"advertising_recommend_name"`
        AdvertisingNoticeName             string             `json:"advertising_notice_name"`
        AdvertisingContentDetailsName     string             `json:"advertising_content_details_name"`
        AdvertisingContentDisplayPageName string             `json:"advertising_content_display_page_name"`
        ColumnName                        string             `json:"column_name"`
        ContentName                       string             `json:"content_name"`
        ContentType                       int32              `json:"content_type"`
        PublishingAt                      *time.Time         `json:"publishing_at"`
        AuthorMemberId                    int64              `json:"author_member_id"`
        AuthorMemberName                  string             `json:"author_member_name"`
        ContentId                         int64              `json:"content_id"`
        SubAction                         int32              `json:"sub_action"`
        PublishingId                      int64              `json:"publishing_id"`
        CmsSlideSlotS                     []CmsSlideSlotItem `json:"cms_slide_slot"`
        LayoutName                        string             `json:"layout_name"`
        UserId                            int64              `json:"user_id"`
        Type                              int32              `json:"type"`
        IsFirst                           bool               `json:"is_first"`
        IsUnified                         bool               `json:"is_unified"`
        Option                            string             `json:"option"`

        //栏目投稿数
        ContributionCount int32 `json:"contribution_count"`
        //栏目发布数
        PublishCount int32 `json:"publish_count"`
        //栏目转发数
        ReprintCount int32 `json:"reprint_count"`
        //栏目上传数
        CirculateCount int32 `json:"circulate_count"`
        //栏目广告数
        AdvertCount int32 `json:"advert_count"`
        //消息数量
        MsgCount      int32  `json:"msg_count"`
        ContentLayout string `json:"content_layout"`
        ColumnLayout  string `json:"column_layout"`
    }

     

    建议

    type CmsColumnEs struct {

    ColumnEs

    ContentEs

    ColumnStat
     }

    type ColumnEs struct {

       ColumnId int64 `json:"column_id"`
       
        ShopId int64 `json:"shop_id"` //商圈
       
        EditorId int64 `json:"editor_id"` //栏目经理
    。。。
     }

    type ContentEsstruct {

     ContentId                         int64              `json:"content_id"`
        SubAction                         int32              `json:"sub_action"`
        PublishingId                      int64              `json:"publishing_id"`
        CmsSlideSlotS                     []CmsSlideSlotItem `json:"cms_slide_slot"`
        LayoutName                        string             `json:"layout_name"`
        UserId                            int64              `json:"user_id"`
        Type                              int32              `json:"type"`
    。。。
     }

    type ColumnStatstruct {

      //栏目投稿数
        ContributionCount int32 `json:"contribution_count"`
        //栏目发布数
        PublishCount int32 `json:"publish_count"`
        //栏目转发数
        ReprintCount int32 `json:"reprint_count"`
        //栏目上传数
        CirculateCount int32 `json:"circulate_count"`
        //栏目广告数
        AdvertCount int32 `json:"advert_count"`
        //消息数量
        MsgCount      int32  `json:"msg_count"`
     }

     

     

    3. 项目内公共代码、私有代码目录命名建议

     

    Pkg:公共

    Internal:私有

     

    如果你认为代码可以导入并在其他项目中使用,那么它应该位于 /pkg 目录中。如果代码不是可重用的,或者你不希望其他人重用它,请将该代码放到 /internal 目录中。你会惊讶于别人会怎么做,所以要明确你的意图!

     

    /internal

    私有应用程序和库代码。这是你不希望其他人在其应用程序或库中导入代码。请注意,这个布局模式是由 Go 编译器本身执行的。注意,你并不局限于顶级 internal 目录。在项目树的任何级别上都可以有多个内部目录。

    你可以选择向 internal 包中添加一些额外的结构,以分隔共享和非共享的内部代码。这不是必需的(特别是对于较小的项目),但是最好有有可视化的线索来显示预期的包的用途。你的实际应用程序代码可以放在 /internal/app 目录下(例如 /internal/app/myapp),这些应用程序共享的代码可以放在 /internal/pkg 目录下(例如 /internal/pkg/myprivlib)。

     

    /pkg

    外部应用程序可以使用的库代码(例如 /pkg/mypubliclib)。其他项目会导入这些库,希望它们能正常工作,所以在这里放东西之前要三思:-)注意,internal 目录是确保私有包不可导入的更好方法,因为它是由 Go 强制执行的。/pkg 目录仍然是一种很好的方式,可以显式地表示该目录中的代码对于其他人来说是安全使用的好方法。由 Travis Jeffery  撰写的 I'll take pkg over internal 博客文章提供了 pkg 和 internal 目录的一个很好的概述,以及什么时候使用它们是有意义的。

     

    4. 【建议1】单个文件长度不超过500行。

    5. 【建议2】单个函数长度不超过50行。

    6. 【规则3】单个函数圈复杂度最好不要超过10,禁止超过15。

    7. 【规则4】单行语句不能过长,如不能拆分需要分行写。一行最多120个字符。

    8. 【建议5】函数中缩进嵌套必须小于等于3层

    func saveActivityAttachment(attachs []*proto.AttachmentSimple, actId int64, operateType string) error {
        var (
           delList []int64
           addList []proto.AttachmentCreateRequest
        )

        if 0 >= len(attachs) {
           return nil
        }

        // 查询附件
        s := &Service{}
        out := &proto.AttachmentQueryResult{}

        if "edit" == operateType {
           if err := s.AttachmentQuery(context.Background(), &proto.AttachmentQueryRequest{
              ObjectId:   actId,
              ObjectType: entity.Activity{}.TableName(),
              PageSize:   50,
              Current:    1,
           }, out); nil != err {
              log.Error("[saveActivityAttachment]获取附件信息失败", err)
              return err
           }
        }
    五层
        if 0 < len(out.Data) {
           mapsAtt := make(map[string]bool)
           for _, item := range out.Data {
              tag := false
              for _, atta := range attachs {
                 if item.Ipfs == atta.Ipfs {
                    if item.Name == atta.Filename {
                       // 完全相同,不处理
                       tag = true
                       mapsAtt[atta.Ipfs] = true
                       break
                    }

                    delList = append(delList, item.Id)
                    tag = true
                    break
                 }
              }

              if tag {
                 continue
              }

              // 没找到
              delList = append(delList, item.Id)
           }

           for _, item := range attachs {
              if _, ok := mapsAtt[item.Ipfs]; ok {
                 continue
              }

              // 新增
              addList = append(addList, proto.AttachmentCreateRequest{
                 ObjectId:   actId,
                 ObjectType: entity.Activity{}.TableName(),
                 Ipfs:       item.Ipfs,
                 Filename:   item.Filename,
              })
           }
        } else {
           for _, item := range attachs {
              addList = append(addList, proto.AttachmentCreateRequest{
                 ObjectId:   actId,
                 ObjectType: entity.Activity{}.TableName(),
                 Ipfs:       item.Ipfs,
                 Filename:   item.Filename,
              })
           }
        }

        for _, item := range addList {
           req := &proto.AttachmentUploadRequest{
              ObjectId:     item.ObjectId,
              ObjectType:   item.ObjectType,
              FileBytes:    utils.ParseInt(item.FileSize),
              Filename:     item.Filename,
              Type:         item.Type,
              Ipfs:         item.Ipfs,
              CreatedBy:    item.CreatedBy,
              ObjectShopId: item.ObjectShopId,
              ShopMemberId: item.ShopMemberId,
           }
           result := &proto.Attachment{}
           err := s.AttachmentUpload(context.Background(), req, result)
           //_, err := attachmentRepo.Create(item)
           if err != nil {
              log.Error("[saveActivityAttachment-err] 创建附件失败,err:%s", err)
              return err
           }
        }

        if 0 < len(delList) {
           if err := s.AttachmentBatchDelete(context.Background(),
              &proto.IDsRequest{IDs: delList}, &proto.Empty{}); nil != err {
              log.Error("[AttachmentBatchBatchDelete-err]删除附件失败", err)
              return err
           }
        }

        return nil
    }

     

    9. WALI构建提供代码检查报告:代码量、代码覆盖率、圈复杂度等

    9.1. 检查代码总量,新增,变更

    9.2. 检查代码圈复杂度

    9.3. 检查代码测试覆盖率

    9.4. 而且有与上版本的对比报告

     

    10. 代码分层按工程包依赖

    不应在一个工程中包括多个服务的代码,每个领域应该组织本领域的公共代码包。

    image.png 

     

    11. 测试代码与代码覆盖率

     

    12. 项目完成组织开发代码评审,架构,产品,测试多个维度评价:

    开发介绍,敏捷的一个流程;

    (结对编程是两个人同时一个模块)

     


    13. 代码圈复杂度

    13.1. 问题提出:

    1、概念:什么是圈复杂度,有什么影响;
    2、工具:需要有工具定期扫描,谁负责管理;
    3、标准:统一代码标准;
    4、整改:如何整改,可落地执行的方案;
    5、培训:需要对开发团队全员培训,工具可能后面要交由运维进行管理维护,

    需要对运维人员进行工具使用的培训。

    13.2. 圈复杂度标准

    对复杂度基本可以分为以下几个级别:

    · 1 - 10 程序简单,风险小

    · 11 - 20 更复杂,中等风险

    · 21 - 50 复杂、高风险

    · 50 不可测试的代码,非常高的风险

     

    13.3. 安装圈复杂度分析工具

    go install github.com/fzipp/gocyclo/cmd/gocyclo@latest

    gocyclo -top 5 .\core

     

    13.4. CMS圈复杂度

    480 com_ichub_icd_cms_shop_service file_shop_pb_content_proto_init icd\cms-proto\shop\content.pb.go:21109:1 =》

    复杂度, 结构名, 函数名, 文件, 代码起始行、列

    53 controller (*CmsContentController).Detail cms-shop\controller\cmsContentController.go:1218:1
    27 controller (*CmsSlideItemController).List cms-shop\controller\cmsSlideItemController.go:359:1
    26 controller (*CmsSlideSlotController).List cms-shop\controller\cmsSlideSlotController.go:361:1
    18 controller (*CmsContentController).List cms-shop\controller\cmsContentController.go:933:1
    17 controller (*CmsContentController).PromulgateList cms-shop\controller\cmsContentController.go:779:1
    15 middleware sanitize cms-shop\middleware\sanitize.go:68:1
    15 controller (*ReplyController).List cms-shop\controller\replyController.go:268:1
    14 graphql_object (*CmsColumnObj).BuriedPointData cms-shop\graphql-object\CmsColumnObj.go:1011:1
    14 controller (*CmsQuestionnaireController).TestPaper cms-shop\controller\cmsQuestionnaireController.go:207:1
    14 controller (*CmsContentController).Down cms-shop\controller\cmsContentController.go:1763:1
    14 controller (*CmsContentController).ForwardList

     

    13.5. Order圈复杂度

    289 handler (*Handler).OrderEdit commerce-order-srv\handler\order.go:6708:1
    152 handler (*Handler).orderEditApprove commerce-order-srv\handler\order.go:8536:1
    95 handler (*Handler).fulfillmentItemConfirm commerce-order-srv\handler\fulfillment_item.go:88:1
    93 handler (*Handler).createFulfillmentItem commerce-order-srv\handler\subscribe.go:785:1
    91 handler (*Handler).lineItemUpdate commerce-order-srv\handler\line_item.go:2210:1
    90 handler (*Handler).platformBuyPayment commerce-order-srv\handler\order_payment_oper.go:171:1
    84 handler (*Handler).orderPayment commerce-order-srv\handler\order.go:3181:1
    70 handler (*Handler).createOrder commerce-order-srv\handler\order.go:150:1
    60 handler (*Handler).createFulfillmentForReturn commerce-order-srv\handler\subscribe.go:1564:1
    58 handler (*Handler).orderEditReturn commerce-order-srv\handler\order.go:9622:1
    58 handler (*Handler).receiveMatchOrderLineCreate commerce-order-srv\handler\fulfillment_item.go:1568:1
    54 handler (*Handler).ServiceLineItemPreview commerce-order-srv\handler\service_order.go:903:1
    51 handler (*Handler).draftLineItemToOrder commerce-order-srv\handler\line_item.go:764:1
    49 handler (*Handler).orderCompletion commerce-order-srv\handler\order.go:1257:1
    49 handler (*Handler).calculateLineItemGrossProfit commerce-order-srv\handler\line_item.go:1600:1
     
      

     

    13.6. General圈复杂度

    112 esentity MetricsDashBoardChartQuery general-srv\esentity\metrics_user.go:505:1
    104 handler (*Service).MigrationSupplyReport general-srv\handler\supply_report.go:254:1
    97 handler (*Service).MigrationServiceDayReport general-srv\handler\service_report_day.go:29:1

     

     


    声明:本网站部分内容来源于网络,版权归原权利人所有,其观点不代表本网站立场;本网站视频或图片制作权归当前商户及其作者,涉及未经授权的制作均须标记“样稿”。如内容侵犯了您相关权利,请及时通过邮箱service@ichub.com与我们联系。
     0  0

    微信扫一扫:分享

    微信里点“+”,扫一扫二维码

    便可将本文分享至朋友圈。

      
    
    
    分享
     0
      验证