编程规范123.docx
目录
6. 【规则3】单个函数圈复杂度最好不要超过10,禁止超过15。
7. 【规则4】单行语句不能过长,如不能拆分需要分行写。一行最多120个字符。
9. WALI构建提供代码检查报告:代码量、代码覆盖率、圈复杂度等
12. 项目完成组织开发代码评审,架构,产品,测试多个维度评价:
目前各域代码重复COPY:
已经有general-common公共工程,网站管理在使用、对齐
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"`
}
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 目录的一个很好的概述,以及什么时候使用它们是有意义的。
6. 【规则3】单个函数圈复杂度最好不要超过10,禁止超过15。
7. 【规则4】单行语句不能过长,如不能拆分需要分行写。一行最多120个字符。
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. 而且有与上版本的对比报告
不应在一个工程中包括多个服务的代码,每个领域应该组织本领域的公共代码包。
12. 项目完成组织开发代码评审,架构,产品,测试多个维度评价:
开发介绍,敏捷的一个流程;
(结对编程是两个人同时一个模块)
1、概念:什么是圈复杂度,有什么影响;
2、工具:需要有工具定期扫描,谁负责管理;
3、标准:统一代码标准;
4、整改:如何整改,可落地执行的方案;
5、培训:需要对开发团队全员培训,工具可能后面要交由运维进行管理维护,
需要对运维人员进行工具使用的培训。
对复杂度基本可以分为以下几个级别:
· 1 - 10 程序简单,风险小
· 11 - 20 更复杂,中等风险
· 21 - 50 复杂、高风险
· 50 不可测试的代码,非常高的风险
go install github.com/fzipp/gocyclo/cmd/gocyclo@latest
gocyclo -top 5 .\core
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
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
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