省エネエンジニア

ゆるっとエンジニアやってます。働きたくない系エンジニア。Android、Webのお仕事やってます。

【Go】リファクタリング

こんにちは。 2017年4月からGoでアプリを開発しておりますが、4月時点では完全にGo初心者でひどいコードを精製してしまったのでリファクタをしたいと思います。

現状

mainパッケージにしたapp.goに全てを書いている状態です。
最悪ですね。

フレームワーク

github.com

Ginを使っています。
超軽量フレームワーク
最低限の機能だけはいっているフレームワークなので、構成なんかは自力でなんとかしなくてはいけない。

調査

Goのアーキテクチャって何がいいんだろうと思って調べてみました。

qiita.com

クリーンアーキテクチャーかぁ…。
とりあえずやってみようと思って途中まで実装してみたのですが、
難しくてやめました。

こういう繊細なやつは私には向いてない。

MVC

せめてMVCくらいにはしたい。
と、思って考えたパッケージ構成はこれです。

└── src
    ├── app.go
    ├── controllers
    ├── database
    │   └──  models
    ├──  utils
    └── templates

役割

app.go

このファイルは一番最初に読み込むmain関数が書いてるファイルです。 中はこんな感じにしました。

package main

// importは省略

func main() {
    router := gin.Default()
    router.GET("/", func(c *gin.Context) {
        controllers.Index(c)
    })
        router.GET("/main", func(c *gin.Context) {
        controllers.Main(c)
    })
    router.Run(":5000")
}

dbの接続なんかもここでやってます。
router的な役割にして、必要なcontrollerを呼び出すようにしています。
controllerでdbが必要な時はここで、dbも渡すようにしています。

controllers

ざっくり、画面や機能に合わせていくつかのファイルに分けています。
中はこんな感じ。

package controllers

// importは省略

func InputedCompany(c *gin.Context) {
    c.HTML(http.StatusOK, "inputed_company.tmpl", gin.H{})
}

func User(c *gin.Context, db *sql.DB) {

    users, err := models.SelectUserAll(aaaaID, db)
    if err != nil {
        fmt.Printf(err.Error())
        c.Redirect(http.StatusMovedPermanently, "/error")
    }

    c.HTML(http.StatusOK, "user.tmpl", gin.H{
        "users": users,
    })
}

modelから画面表示に必要なデータをとってくる。
入力がある場合にはmodelを呼び出して入力をやってもらう。
そして、最後に表示したいテンプレートを呼び出す。

models

package models

// importは省略

// User is personal information
type User struct {
    ID        int
    Name      string
    Mail      string
    Pass      string
}

// SelectUserAll is acquire all user data
func SelectUserAll(db *sql.DB) (users []User, err error) {
    query := "SELECT id, name, mail, pass FROM user;"
    result, err := db.Query(query)
    if err != nil {
        return users, err
    }
    var id int
    var name string
    var pass string
    var mail string
    for result.Next() {
        if err := result.Scan(&id, &name, &mail, &pass); err != nil {
            return users, err
        }
        users = append(users, User{id, name, pass, mail})
    }
    return users, nil
}

こんな感じ。
データをSelect,Insert,Update,Deleteするだけ。

utils

よく使う処理や定数をここにまとめました。 内容は割愛。

やってみて

初期状態がひどすぎるのであれなのですが、 かなりすっきりしたと思います。

私の知識不足でcontrollerがまだ煩雑な感じになってしまっているので、 今後なんとかしたいです。