2016-06-28 9 views
2

Problem: Es gibt eine Liste von Tabellen zugeordneten Schlüsseln. Es ist notwendig, CRUD für jede Tabelle + einige funktionale auf den Besonderheiten der Tabelle (Seitenumbruch, etc.) zu implementieren. Probleme: in jeder der funktionalen Implementierung für jede Tabelle dupliziert Etwa 50% des Codes. Frage: Wie sind die Besonderheiten der Sprache, der Optimierung/Refactoring/Verwendung ähnlicher Codemuster?Golang. Refactoring || Muster || jede Lösung

Beispiel Codeteil

//------------------------------------------------------------------ 
// user 
//---------------------------------------------------------------------- 
func (d *Database) UserCreate(email, password, username string, role int) *Answer { 
    //variables 
    answer := d.initCall("UserCreate") 
    user := new(User) 
    //check exist user 
    if userExist := d.DB.Find(&User{}, &User{Email:email}).Error; userExist == nil { 
     answer.AnswerJSON.ErrorAnswer.Message = "[usercreate] user already exist" 
     answer.AnswerJSON.Result = nil 
     answer.AnswerJSON.Status = false 
    } else { 

     userinfo := UserInfo{Data:time.Now()} 
     session := Session{Data:time.Now()} 
     cook := Cook{} 

     //make support tables object 
     //userinfo object 
     userinfo.Password = password 
     userinfo.Username = username 
     //cook object 
     cook.SessionID = session.ID 
     cook.Cookie = d.cookgeneratenew("somesaltforcooksgenerate") 
     cook.Status = true 
     cook.Lastconnect = time.Now() 
     cook.CountConnect += 1 

     //user object 
     user.Email = email 
     user.Session = session 
     user.UserInfo = userinfo 
     user.Cook = cook 
     user.Role = int64(role) 

     //make request + //serizlizations to json answer 
     if err := d.DB.Create(user).Error; err != nil { 
      answer.AnswerJSON.ErrorAnswer.Message = err.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Result = user 
      answer.AnswerJSON.Status = true 
     } 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) UserDelete(userid int64) *Answer { 
    answer := d.initCall("UserDelete") 
    user := new(User) 
    //check exists 
    if userExists := d.DB.Find(user, "ID = ?", userid).Error; userExists == nil { 
     if userDelete := d.DB.Delete(user).Error; userDelete != nil { 
      answer.AnswerJSON.ErrorAnswer.Message = userExists.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Status = true 
      answer.AnswerJSON.ErrorAnswer = nil 
     } 
    } else { 
     answer.AnswerJSON.ErrorAnswer.Message = userExists.Error() 
     answer.AnswerJSON.Status = false 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) UserRead(userid int64) *Answer { 
    answer := d.initCall("UserRead") 
    user := new(User) 
    if userExists := d.DB.Find(user, "ID = ?", userid).Error; userExists != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = userExists.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     if rel := d.DB.Model(user).Related(&user.Session).Error; rel != nil { 
      answer.AnswerJSON.Result = nil 
      answer.AnswerJSON.ErrorAnswer.Message = rel.Error() 
      answer.AnswerJSON.Status = false 
     } else if rel = d.DB.Model(user).Related(&user.UserInfo).Error; rel != nil { 
      answer.AnswerJSON.Result = nil 
      answer.AnswerJSON.ErrorAnswer.Message = rel.Error() 
      answer.AnswerJSON.Status = false 
     } else if rel = d.DB.Model(user).Related(&user.Cook).Error; rel != nil { 
      answer.AnswerJSON.Result = nil 
      answer.AnswerJSON.ErrorAnswer.Message = rel.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Result = user 
      answer.AnswerJSON.ErrorAnswer = nil 
      answer.AnswerJSON.Status = true 
     } 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) UserReadAll() *Answer { 
    answer := d.initCall("UserReadAll") 
    users := []User{} 

    if usersGet := d.DB.Find(&users).Error; usersGet != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = usersGet.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     for _, user := range users { 
      d.DB.Model(user).Related(&user.Session) 
      d.DB.Model(user).Related(&user.UserInfo) 
      d.DB.Model(user).Related(&user.Cook) 
     } 
     answer.AnswerJSON.Result = users 
     answer.AnswerJSON.ErrorAnswer = nil 
     answer.AnswerJSON.Status = true 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) UserUpdate(userid int64, uu *UserUpdateStruct) *Answer { 
    answer := d.initCall("UserUpdate") 
    user := new(User) 

    if userExists := d.DB.Find(user, "ID = ?", userid).Error; userExists != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = userExists.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     //get relevating struct info 
     d.DB.Model(user).Related(&user.Session) 
     d.DB.Model(user).Related(&user.UserInfo) 
     d.DB.Model(user).Related(&user.Cook) 

     //update columns 
     if uu.Email != "" { 
      user.Email = uu.Email 
     } 
     if uu.Avatar > 0 { 
      user.UserInfo.Avatar = uu.Avatar 
     } 
     if uu.Birthday != "" { 
      user.UserInfo.Birthday = uu.Birthday 
     } 
     if uu.Location != "" { 
      user.UserInfo.Location = uu.Location 
     } 
     if uu.Male != "" { 
      user.UserInfo.Male = uu.Male 
     } 
     if uu.Password != "" { 
      user.UserInfo.Password = uu.Password 
     } 
     if uu.Role > 0 { 
      if roleErr := d.DB.Find(&Role{}).Error; roleErr != nil { 
       //role not found 
       fmt.Printf("[userupdate] role not found `%d`\n", uu.Role) 
      } else { 
       user.Role = uu.Role 
      } 
     } 

     //update 
     if errUpdate := d.DB.Save(user).Error; errUpdate != nil { 
      answer.AnswerJSON.ErrorAnswer.Message = errUpdate.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Result = user 
      answer.AnswerJSON.ErrorAnswer = nil 
      answer.AnswerJSON.Status = true 
     } 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) UserPaginate(page, countPage int) *Answer { 
    answer := d.initCall("UserPaginate") 
    result := []*User{} 
    if errPag := d.DB.Limit(countPage).Offset((page * countPage) - countPage).Find(&result).Error; errPag != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = errPag.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     for _, user := range result { 
      d.DB.Model(&user).Related(&user.Session) 
      d.DB.Model(&user).Related(&user.UserInfo) 
      d.DB.Model(&user).Related(&user.Cook) 
     } 
     answer.AnswerJSON.Result = result 
     answer.AnswerJSON.ErrorAnswer = nil 
     answer.AnswerJSON.Status = true 
    } 
    d.serilize(answer) 
    return answer 
} 
//------------------------------------------------------------------- 
// category 
//-------------------------------------------------------------------- 
func (d *Database) CategoryCreate(name string) *Answer { 
    //variables 
    answer := d.initCall("CategoryCreate") 
    cat := new(Category) 
    //check exist user 
    if catExist := d.DB.Find(&Category{}, &Category{Name:name}).Error; catExist == nil { 
     answer.AnswerJSON.ErrorAnswer.Message = "[categorycreate] category already exist" 
     answer.AnswerJSON.Result = nil 
     answer.AnswerJSON.Status = false 
    } else { 
     cat.Name = name 
     //make request + //serizlizations to json answer 
     if err := d.DB.Create(cat).Error; err != nil { 
      answer.AnswerJSON.ErrorAnswer.Message = err.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Result = cat 
      answer.AnswerJSON.Status = true 
     } 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) CategoryDelete(catid int64) *Answer { 
    answer := d.initCall("CategoryDelete") 
    cat := new(Category) 
    //check exists 
    if catExists := d.DB.Find(cat, "ID = ?", catid).Error; catExists == nil { 
     if catDelete := d.DB.Delete(cat).Error; catDelete != nil { 
      answer.AnswerJSON.ErrorAnswer.Message = catExists.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Status = true 
      answer.AnswerJSON.ErrorAnswer = nil 
     } 
    } else { 
     answer.AnswerJSON.ErrorAnswer.Message = catExists.Error() 
     answer.AnswerJSON.Status = false 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) CategoryRead(catid int64) *Answer { 
    answer := d.initCall("CategoryRead") 
    cat := new(Category) 
    if catExists := d.DB.Find(cat, "ID = ?", catid).Error; catExists != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = catExists.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     if rel := d.DB.Model(cat).Related(&cat.Post).Error; rel != nil { 
      answer.AnswerJSON.Result = nil 
      answer.AnswerJSON.ErrorAnswer.Message = rel.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      for x, p := range cat.Post { 
       d.DB.Model(&p).Related(&p.Comment) 
       d.DB.Model(&p).Related(&p.PostSeo) 
       cat.Post[x] = p 
      } 
      answer.AnswerJSON.Result = cat 
      answer.AnswerJSON.ErrorAnswer = nil 
      answer.AnswerJSON.Status = true 
     } 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) CategoryReadAll() *Answer { 
    answer := d.initCall("CategoryReadAll") 
    cats := []Category{} 

    if catsGet := d.DB.Find(&cats).Error; catsGet != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = catsGet.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     //categorys 
     for _, cat := range cats { 
      d.DB.Model(cat).Related(&cat.Post) 
      //get relete POST 
      for x, p := range cat.Post { 
       d.DB.Model(&p).Related(&p.Comment) 
       d.DB.Model(&p).Related(&p.PostSeo) 
       cat.Post[x] = p 
      } 
     } 
     answer.AnswerJSON.Result = cats 
     answer.AnswerJSON.ErrorAnswer = nil 
     answer.AnswerJSON.Status = true 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) CategoryUpdate(catid int64, name string) *Answer { 
    answer := d.initCall("CategoryUpdate") 
    cat := new(Category) 

    if catExists := d.DB.Find(cat, "ID = ?", catid).Error; catExists != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = catExists.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     //get relevating struct info 
     d.DB.Model(cat).Related(&cat.Post) 

     //update columns 
     if name != "" { 
      cat.Name = name 
     } 
     //update 
     if errUpdate := d.DB.Save(cat).Error; errUpdate != nil { 
      answer.AnswerJSON.ErrorAnswer.Message = errUpdate.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Result = cat 
      answer.AnswerJSON.ErrorAnswer = nil 
      answer.AnswerJSON.Status = true 
     } 
    } 
    d.serilize(answer) 
    return answer 
} 
func (d *Database) CategoryPaginate(page, countPage int) *Answer { 
    answer := d.initCall("CategoryPaginate") 
    result := []*Category{} 
    if errPag := d.DB.Limit(countPage).Offset((page * countPage) - countPage).Find(&result).Error; errPag != nil { 
     answer.AnswerJSON.ErrorAnswer.Message = errPag.Error() 
     answer.AnswerJSON.Status = false 
    } else { 
     for _, cat := range result { 
      d.DB.Model(&cat).Related(&cat.Post) 
      //get relete POST 
      for x, p := range cat.Post { 
       d.DB.Model(&p).Related(&p.Comment) 
       d.DB.Model(&p).Related(&p.PostSeo) 
       cat.Post[x] = p 
      } 
     } 
     answer.AnswerJSON.Result = result 
     answer.AnswerJSON.ErrorAnswer = nil 
     answer.AnswerJSON.Status = true 
    } 
    d.serilize(answer) 
    return answer 
} 

Antwort

2

Ich kann sehen Sie viel Redundanz in Ihrem Code haben. Vor ein paar Monaten hatte ich ein ähnliches Problem und habe eine gute Antwort. Schauen Sie sich hier an: How to return dynamic type struct in Golang?.

Grundsätzlich werden Sie gleichen drei Funktionen (Hinzufügen/Bearbeiten/Löschen/count) wie folgt aus (ich weiß nicht, was db sind Sie ich NoSQL Rethinkdb verwenden verwenden, aber das Prinzip ist gleich):

func (c Main) Get(modelname string) interface{} { 

    //your query here for getting stuff from model name and return interface 

    rows, err := rethink.Table(modelname).OrderBy(rethink.Asc("sortNo")).Run(c.DB) 
    if err != nil { 
     log.Println(err) 
     return nil 
    } 

    if (modelType == "brand") { 

     var brands []*models.Brand 
     rows.All(&brands) 

     return brands 

    } 
    //rest of your models here or use some switch 
}) 

Normalerweise setze ich alle meine Funktionen, die Sachen mit Datenbank in irgendeinem Helfer tun (das ist meistens wegen der Tests).

Ich denke, das ist gute Richtungen, weil wie Sie Code ist leicht zu pflegen und Sie werden nur Hilfsfunktionen ändern, statt zu Millionen Fiktionen gehen, die hinzufügen/löschen/aktualisieren für jedes Modell tun.

+0

+1 ich das in seinem Kopf kreiste Konzept mag, kann er angeben es nicht. Sie haben dieser Idee eine perfekte Form gegeben. Vielen Dank. – Spouk

+0

Es ist auch ein relativ gebräuchliches Idiom, das Ziel als ein Schnittstellenargument zu der Funktion in ähnlicher Weise wie "io.Read()" und "sql.Scan()" zu übergeben. Wenn Ihre 'Get()' Funktion ein Argument 'dest interface {}' akzeptiert, das ein Zeiger sein muss, kann es dieses 'dest' direkt an Ihre' rows.All() 'übergeben (oder die Basis' sql.Scan() ', oder' sqlx.Get() ', etc), ohne zu wissen, um welchen Typ es sich überhaupt handelt, und ohne einen spezifischen Codeblock in' Get() 'für jeden Domänenmodelltyp zu haben. – Kaedys

0

Ich habe diese Idee in den Code implementiert. Es ist großartig geworden.

Refaktorierungscode

//------------------------------------------------------------------------ 
// REFACTORING 
//----------------------------------------------------------------------- 
func (d *Database)Create(model string, params interface{}) *Answer { 
    //variables 
    answer := d.initCall("Create") 
    tableType := d.Mapper[model] 
    var (
     errorExists interface{} 
     flag bool 
    ) 

    //logic switch types 
    switch tableType.(type) { 
    case User: 
     params := params.(UserUpdate) 
     if errorExists = d.DB.Find(&User{}, &User{Email:params.Email}).Error; errorExists == nil { 
      flag = false 
     } else { 
      flag = true 
      //variables 
      user := new(User) 
      userinfo := UserInfo{Data:time.Now()} 
      session := Session{Data:time.Now()} 
      cook := Cook{} 

      //make support tables object 
      //userinfo object 
      userinfo.Password = params.Password 
      userinfo.Username = params.Username 
      //cook object 
      cook.SessionID = session.ID 
      cook.Cookie = d.cookgeneratenew("somesaltforcooksgenerate") 
      cook.Status = true 
      cook.Lastconnect = time.Now() 
      cook.CountConnect += 1 

      //user object 
      user.Email = params.Email 
      user.Session = session 
      user.UserInfo = userinfo 
      user.Cook = cook 
      user.Role = int64(params.Role) 

      //assign ready model for create 
      tableType = user 
     } 

    case Category: 
     params := params.(CategoryUpdate) 
     if errorExists = d.DB.Find(&Category{}, &Category{Name:params.Name}).Error; errorExists == nil { 
      //set logic switcher 
      flag = false 
     } else { 
      //set logic switcher 
      flag = true 

      //speciffic functional 
      cat := new(Category) 
      cat.Name = params.Name 

      //assign ready model for create 
      tableType = cat 
    } 
    default: 
     fmt.Printf("Wrong type table\n") 
    } 

    //call function create model 
    if flag { 
     if err := d.DB.Create(tableType).Error; err != nil { 
      answer.AnswerJSON.ErrorAnswer.Message = err.Error() 
      answer.AnswerJSON.Status = false 
     } else { 
      answer.AnswerJSON.Result = tableType 
      answer.AnswerJSON.Status = true 
     } 
    } else { 
     answer.AnswerJSON.ErrorAnswer.Message = "object already exist" 
     answer.AnswerJSON.Result = nil 
     answer.AnswerJSON.Status = false 
    } 
    //make answer 
    d.serilize(answer) 
    return answer 
} 
+0

einfach weiter lernen, los geht's :) – pregmatch