Go语言高效率Web开发四:分层领域模型和项目结构分层

前文中已出现request模型、domain模型、response模型,本文把增加do模型和repository仓储层,项目结构已见雏形。

阿里巴巴Java开发手册分层领域模型规约:

Query:数据查询对象,各层接收上层的查询请求。注意超过2个参数的查询封装,禁止使用Map类来传输。
DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。 
BO(Business Object):业务对象,可以由Service层输出的封装业务逻辑的对象。 
DO(Data Object):此对象与数据库表结构一一对应,通过DAO层向上传输数据源对象。
VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。(本文忽略)
复制代码

对应模型:

request => Query 
response => DTO 
domain => BO 
do => DO 
复制代码

下文通过几个案例来讲解每个模型在各个代码层如何穿梭和映射

1640683957386.jpg

案例一:获取订单详情(单个对象)
package controller

func (ctr *Order) Get(c *gin.Context) {

   var request request.OrderGet
   if err := c.ShouldB(&request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   order := ctr.repo.Get(c.Request.Context(), request.ID)

   response := new(response.Order)
   mapper.Map(&response, order)
   c.JSON(http.StatusOK, gin.H{"data": response})
}
--------------------------------------------------------------------------------
package repository

func (repo *Order) Get(ctx context.Context, id int) *domain.Order {
   order := &do.Order{ID: 1, UserID: 1, SN: "123456", CreateTime: time.Now()}

   domain := new(domain.Order)
   mapper.Map(&domain, order)
   return domain
}
复制代码
案例二:获取订单列表(对象数组)
package controller

func (ctr *Order) My(c *gin.Context) {

   orders := ctr.repo.My(c.Request.Context())

   response := []*response.Order{}
   mapper.Map(&response, orders)
   c.JSON(http.StatusOK, gin.H{"data": response})
}
--------------------------------------------------------------------------------
package repository

func (repo *Order) My(ctx context.Context) []*domain.Order {
   orders := []*do.Order{
      {ID: 1, UserID: 1, SN: "123456", CreateTime: time.Now()},
      {ID: 2, UserID: 1, SN: "987654", CreateTime: time.Now()},
   }

   domains := []*domain.Order{}
   mapper.Map(&domains, orders)
   return domains
}

复制代码

WechatIMG1462.jpeg

案例三:获取订单列表(查询参数+对象数组)
package controller

func (ctr *Order) List(c *gin.Context) {

   request := new(request.OrderList)
   if err := c.ShouldB(&request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   orders := ctr.repo.List(c.Request.Context(), request)

   response := []*response.Order{}
   mapper.Map(&response, orders)
   c.JSON(http.StatusOK, gin.H{"data": response})
}

--------------------------------------------------------------------------------
package repository

func (repo *Order) List(ctx context.Context, request *request.OrderList) []*domain.Order {
   fmt.Println(request)

   orders := []*do.Order{
      {ID: 1, UserID: 1, SN: "123456", CreateTime: time.Now()},
      {ID: 2, UserID: 1, SN: "987654", CreateTime: time.Now()},
   }

   domains := []*domain.Order{}
   mapper.Map(&domains, orders)
   return domains
}
复制代码

WechatIMG1463.jpeg

案例四:用户注册
package controller

func (ctr *User) Register(c *gin.Context) {
   var request request.UserRegister
   if err := c.ShouldB(&request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   user := new(domain.User)
   user.Register(request.Mobile, request.Password)

   data := ctr.repo.Register(c.Request.Context(), user)

   response := new(response.User)
   mapper.Map(&response, data)
   c.JSON(http.StatusOK, gin.H{"data": response})
}

--------------------------------------------------------------------------------
package domain

type NicknameS struct {}

func (dom *NicknameS) generate(str string) string {
   return str[0:4] + "****" + str[8:11]
}

type PasswordS struct {}

func (dom *PasswordS) generate(str string) string {
   str += dom.salt()
   h := md5.New()
   h.Write([]byte(str))
   return hex.EncodeToString(h.Sum(nil))
}

func (dom *PasswordS) salt() string {
   return "~!@#abc123"
}

type User struct {
   ID          int
   Mobile      string
   Nickname    string
   NicknameS    *NicknameS
   Password    string
   PasswordS    *PasswordS
   HeaderImage string
   Money       int
   CreateTime time.Time
}

func (dom *User) Register(mobile string, password string) {
   dom.Mobile = mobile
   dom.Nickname = dom.NicknameS.generate(mobile)
   dom.Password = dom.PasswordS.generate(password)
   dom.CreateTime = time.Now()
   dom.HeaderImage = dom.DefaultHeaderImage()
}

func (dom *User) DefaultHeaderImage() string {
   return "header.jpg"
}

--------------------------------------------------------------------------------
package repository

func (repo *User) Register(ctx context.Context, user *domain.User) *domain.User {

   do := new(do.User)
   do.ID = 1
   do.Mobile = user.Mobile
   do.Password = user.Password
   do.HeaderImage = user.HeaderImage
   do.CreateTime = user.CreateTime
   // do对象入库

   domain := new(domain.User)
   mapper.Map(&domain, do)
   return domain
}
复制代码

猜你喜欢

转载自juejin.im/post/7049269149608083486
今日推荐