【问题标题】:Refactoring Golang avoiding manual fields updating between similar structs重构 Golang 避免在相似结构之间手动更新字段
【发布时间】:2020-10-10 11:21:21
【问题描述】:

我正在使用 GraphQL 和 go-pg

我有很多这样的实体:

type Player struct {
    ID        int
    CreatedAt time.Time `pg:"default:now(),notnull"`
    TeamID    int `pg:",notnull"`
    Team      *Team
    Type      int
    Score     int64 `pg:",notnull"`
    Note      *string
    // and others...
}

type PlayerInput struct {
    TeamID  int
    Type    int
    Score   int64
    Note    *string
    // and others...
}

我有很多次这样的功能:

func (db *postgres) Update(context context.Context, id int, input types.PlayerInput) (*types.Player, error) {

    var actualPlayer types.Player

    newPlayer := graphqlToDB(&input)

    tx, err := db.Begin()
    //handle err

    err = tx.Model(&actualPlayer).Where("id = ?", id).For("UPDATE").Select()
    // handle err and rollback

    actualPlayer.TeamID = newPlayer.TeamID
    actualPlayer.Type = newPlayer.Type
    actualPlayer.Score = newPlayer.Score
    actualPlayer.Note = newPlayer.Note
    // and others...

    _, err = tx.Model(&actualPlayer).WherePK().Update()
    // handle err and rollback

    err = tx.Commit()
    //handle err

    return &actualPlayer, nil
}

func graphqlToDB(input *types.PlayerInput) *types.Player {

    var output = &types.Player{
        TeamID:   input.TeamID,
        Type:     input.Type,
        Score:    input.Score,
        Note:     input.Note,
        // and others...
    }

    if input.Type == "example" {
        output.Score = 10000000
  }

    return output
}

我的项目中的每个实体都有此代码,我想限制/避免冗余代码,特别是:

  1. 每次从 Graphql 输入类型转换

    newPlayer := graphqlToDB(&input)
    
  2. 每次手动更新这些(和其他)字段

    actualPlayer.TeamID = newPlayer.TeamID
    actualPlayer.Type = newPlayer.Type
    actualPlayer.Score = newPlayer.Score
    actualPlayer.Note = newPlayer.Note
    
  3. 每次打开和关闭数据库事务

    tx, err := db.Begin()
    

我是在求月亮吗?

【问题讨论】:

    标签: go design-patterns architecture refactoring


    【解决方案1】:

    我不认为这段代码有异常数量的冗余。

    1. 每次都从 Graphql 输入类型转换

    将结构从外部模型转换为内部模型是一种常见模式,有助于分离关注点。此外,您已经拥有graphqlToDB 函数,它允许您重用其主体中的 10 行代码。这可能是最好的。

    1. 每次手动更新这些(和其他)字段

    在您在此处显示的特定代码段中,actualPlayer 的类型为 types.PlayergraphqlToDB 函数返回一个 *types.Player 对象。

    所以你可以简单地写actualPlayer := graphqlToDB(&input),然后传递指针,比如tx.Model(actualPlayer)。 这样可以节省将 newPlayer 重新映射到 actualPlayer

    1. 每次打开和关闭数据库事务

    如果您需要每次都以事务方式访问数据库,那么您需要每次都打开事务(然后提交/回滚)。这没有冗余。重构可能只会导致可读性下降。

    【讨论】:

      猜你喜欢
      • 2015-07-31
      • 2019-05-16
      • 1970-01-01
      • 2010-10-26
      • 1970-01-01
      • 2020-08-13
      • 2015-08-31
      • 1970-01-01
      相关资源
      最近更新 更多