ボクダイモリ

Life is like a Game

Gin + gormで簡単なWebアプリを作ってみた

自分でサービスを立ち上げたかったので、Go言語で簡単なWebアプリを作ってみた。

https://github.com/anraku/gin-sample

Go言語を選んだのは今一番気になっている言語だから

WebフレームワークはどれがいいのかよくわからなかったのでとりあえずGinを選択。

理由は速度が早そうだから(Martiniという同じWebフレームワークの40倍早いらしい)

 

あとはデータベースも使いたかったのでORMのライブラリもxormとgormを使ってみた。

最初はxormがいいような気がしたが、ドキュメントがあまり整備されていない印象。

また、実際にデータベースアクセスの処理が間違っていた時どのようなSQL文が発行されたのかが

分からずトラブルシューティングが難しいと感じた。

それにgithubの更新が少ないのも気になる。。

 

最終的にはgormの方を選択。ドキュメントもわかりやすく、ちょっとしたCRUDは1行程度でシンプルに書ける。

以下gormのドキュメント

http://jinzhu.me/gorm/

 

全体的に黒いデザインなのもいいね!

Webアプリの概要

とりあえずGinとgormを使って簡単にCRUDができるアプリを作ってみた。

アプリはGOPATHの配下に配置する前提です。

フロントの方はドットインストールの何かの入門で作ったコードを使いました。

また、Ginを使う際は以下のコマンドを実行してGinをインストールする必要がある。

go get github.com/gin-gonic/gin

main.go

func main() {
    router := gin.Default()
    router.LoadHTMLGlob("templates/*") // 事前にテンプレートをロード

    // トップページ
    router.GET("/index", func(c *gin.Context) {
        // データを処理する
        ctrl := controllers.NewPost()
        result := ctrl.GetAllPost()
        // テンプレートを使って、値を置き換えてHTMLレスポンスを応答
        c.HTML(http.StatusOK, "index.tmpl", gin.H{
            "posts": result,
        })
    })
}

最初にrouterを定義してHTMLテンプレートのロードを行う

router.GET("/index", func(c *gin.Context)で/indexへのGETアクセスを処理するための メソッドを作成している。

ctrl := controllers.NewPost()はModelのメソッドにアクセスするためのstructを返し、

result := ctrl.GetAllPost()でデータベースにアクセスし、値を取得している。

 

最後にindex.tmplをレスポンスとして返し、"posts"という名前のパラメータに取得したresultをセットする。

Controller

Controllerは基本データベースから値を取得し、必要であればデータの加工を行ってから 呼び出し元に返すというような実装が良いでしょう。 今回作ったのは簡単なCRUDしかないので、データベースから受け取った値をそのまま呼び出し元に返しています。

以下、Controllerの全文です。

package controllers

import (
    "../models"
)

// Post Model
type Post struct {
}

// Post Modelを返す
func NewPost() Post {
    return Post{}
}

// idに合致する記事の情報を返す
func (c Post) GetId(n int) interface{} {
    repo := models.NewPostRepository()
    post := repo.GetByPostID(n)
    return post
}

// 全記事の情報
func (c Post) GetAllPost() interface{} {
    repo := models.NewPostRepository()
    posts := repo.GetAllPost()
    return posts
}

// 全記事の件名
func (c Post) GetAllHeader() interface{} {
    repo := models.NewPostRepository()
    posts := repo.GetAllHeader()
    return posts
}

// 記事を投稿
func (c Post) CreatePost(header string, body string, author string) bool {
    repo := models.NewPostRepository()
    ok := repo.CreatePost(header, body, author)
    return ok
}

// 記事を更新
func (c Post) UpdatePost(id int, header string, body string) interface{} {
    repo := models.NewPostRepository()
    ok := repo.UpdatePost(id, header, body)
    return ok
}

// 記事を削除
func (c Post) DeletePost(n int) interface{} {
    repo := models.NewPostRepository()
    result := repo.DeletePost(n)
    return result
}

Model

gormを使う際は以下のライブラリをgo getして、importする必要がある

"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"

gormを利用するために以下のようにgormのオブジェクトとデータベースを初期化

var db *gorm.DB

func init() {
  conn, err := gorm.Open("mysql", 
    "root:password@/gin_sample?charset=utf8&parseTime=True&loc=Local")
  if err != nil {
    panic(err)
  }
  db = conn
  //DB Migrate
  if !db.HasTable("posts") {
    db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&Post{})
  }
}

gorm.DBのオブジェクトをグローバル変数で保持するようにして、実行時にDBへ接続するようにする。 init()はアプリの実行時に呼ばれる。

gormでは

db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&Post{})

のようにDBのマイグレーションを行える。 マイグレーションのコードも書いておけば開発時にテーブル定義をいちいち自分で作る必要がない。 Insertする処理も一緒に書いておくともっと楽ができるだろう。

マイグレーションは定義したstructをAutoMigrateの引数に渡すことで、それに対応するテーブルの作成を行う。 今回定義したstructは以下の通り

// 投稿情報の構造体
type Post struct {
    ID     int            `gorm:"AUTO_INCREMENT;primary_key"`
    Header string         `gorm:"not null;size:255"`
    Body   string         `gorm:"not null;size:13000"`
    Author string         `gorm:"not null;size:30"`
    CreatedAt time.Time   `gorm:"not null"`
}

上記のstructをマイグレーションすることで「posts」というテーブルが作成される。 最後にCRUDの処理をざっと記載する。

// idに合致する記事を取得
func (m PostRepository) GetByPostID(id int) *Post {
    var post Post
    db.Where(Post{ID: id}).Find(&post)
    return &post
}

// 記事を全検索
func (m PostRepository) GetAllPost() []Post {
    var post []Post
    db.Select("*").Find(&post)
    return post
}

// 記事を投稿する
func (m PostRepository) CreatePost(header string, body string, author string) bool {
    post := Post {
        Header: header,
        Body:   body,
    }
    db.Create(&post)
    return true
}

// 記事の件名と本文を更新する
func (m PostRepository) UpdatePost(id int, header string, body string) interface{} {
    post := Post{ID: id}
    db.Model(&post).Updates(map[string]interface{}{
        "Header":header, 
        "Body":  body,
        })
    return true
}

// 記事を削除する
func (m PostRepository) DeletePost(id int) interface{} {
    post := Post{ID: id}
    db.Delete(post)
    return nil
}

まとめ

Gin + gormで割りとすぐにWebアプリが作れた(簡単なものだけど)

ORMライブラリの使い勝手としてはxormよりもgormの方が若干 CRUDの処理がシンプルに書ける印象。

ドキュメントも分かりやすく、CRUDが簡単に実装できたので 好きになりました。

 

また、テーブル名が構造体の名前に依存する(Post構造体にはpostsというテーブルが紐づく)ので、

テーブル名には気をつける必要がある。

 

Gin + gormは思ってたよりも記述量が少なく、記述もシンプルなので

個人的にはWebアプリを作る時にGoを使うという選択肢はありなように感じました。

Nintendo Switchをやってみてよかった事

Nintendo Switchをプレイし始めて1ヶ月くらい経ったので感想を書いてみる。

 

Nintendo Switchのいいところ

 

Switchを買った時はただゼルダがやりたくて買った感じなので、ハード的には全く興味がなかったが

いざプレイしてみるとハードとして優れたものであることを実感できた。

 

 

Switchについて調べればわかることだけども、今回のハードも任天堂らしく画期的な仕様になっていて、それが現代のコンテクストにしっかりマッチしていると感じた。

 

 

そのように感じたNintendo Switchの特徴的な点をいくつか挙げてみる。

 

 

据え置き機でもあり携帯機でもある

 

Switch本体にはディスプレイが付いていて左右にコントローラーが付いたような作りになっており、パッと見大きい携帯機というような感じ。

ゲーム画面は外部出力することができ、左右のコントローラーは自由に着脱できる。

自分は普段家でプレイする時はコントローラーを外して、外部ディスプレイに出力してプレイをしている。

 

 

Switchをプレイして気に入った点は、いつでも開始でき、いつでも終了できること。

本体の電源ボタンを1回押せばスリープになるので、いつもこのように操作している。

例えるとiPadの電源ボタンを押してスリープしたり解除したりするのと似ているのでお手軽だ。

 

 

本体自体もあまり大きくはないので出先にも持っていけると思う(自分はやったことない)。

なので、仕事をしているような忙しい人もプレイしやすいと思うのでゲームが好きな方にはぜひオススメしたい。

 

 

コントローラーが軽く扱いやすい

 

自分は基本コントローラは外してプレイしているのだが、持ってみると本当に軽い。

また、コントローラーが2つに別れるところがSwitchの特徴の1つであるが、これが個人的には

プレイのしやすさに繋がっていると感じている。

 

 

どういうことかというと通常のコントローラーであれば両手の位置が固定されるが、Switchの場合は両手の位置が自由になる。

例えば両肘を椅子の肘掛けに置きながらプレイするということも可能だ。

自分はいつもこのスタイルでやっている。

 

 

面白いゲームタイトルがある

 

てゆうかゼルダがある。それだけで買う価値があると思っている。

オープンワールド嫌いという方もぜひやってみてほしい。オープンワールドに対する価値観が変わるかもしれない。

 

 

まとめ

  • Switchは気軽にプレイしやすいので忙しい人にもオススメ
  • コントローラー軽いし2つに別れてたりするがそれがいい
  • ゼルダ最高

はてなブログからWordPressに移行しました

はてなブログからWordPressに移行してみました。

移行元のサイト

http://anrakusan.hateblo.jp/

 

 

もっと自分のブログをカスタマイズしたくなったので先週あたりから始めてやって現在やっと

そこそこ整備出来てきたところです。

 

 

今現在出来ているのは

といったところ。

 

 

ここまであるのに平日の空き時間をちょっとずつ使って1週間くらい。

長かったけども1からサイトを構築してきたので勉強になった。

 

 

このサイトを立ち上げるまでにちょっと遠回りしたりもして、躓いたので

そのことについてちょっと書いてみようと思います。

 

最初はHeroku + WordPressで構築するつもりだった

 

Herokuはhobby-devなら月額7$で運用でき、独自ドメインが無料で使える。

なにより設定することが少なく楽。

 

 

また、hobby-devプランからSSL証明書の利用が無料になるというニュースも聞いていたので、

もうHerokuしかないと思っていた。

 

↓がそのニュース記事

https://getpocket.com/a/read/1707614130

 

 

Herokuアカウントはすでに持っていたので、Heroku + WordPressの導入自体は簡単だった。

以下の公式のREADME.mdを見ながらやれば途中まではできる。

https://github.com/mhoofman/wordpress-heroku

 

 

ただwp-config.phpにHerokuのDBの情報を設定する処理がないのでこのままだと立ち上がらない。

その点だけ気をつければ問題なくWordPressの起動はできる。

 

 

自分が躓いたのはこの後で、何か設定しようとするとWordPressが壊れてしまう。

例えば、

 

壊れてしまったら仕方ないのでGitを使ってHerokuにファイルをデプロイし直すのだが、

それをやる度に最初からやり直しになる。(これで結構時間食った…)

 

 

よく見たらバージョン古すぎ…。Githubのソースも2年ほど更新がされていなかった😲

 

更新がされていないことにもっと早く気付ければorz

まぁやってしまったものは仕方ない😅

 

 

なのでこれだとまともにブログを運用できないので環境を見直し。

色々調べた結果、さくらVPSを使うと良さそうな気がした。

 

 

さくらVPS上にWordPress環境を構築

 

結局ブログサイトはさくらVPS上に構築することにした。

OSはCentOS7で運用していて、nginx + PHP + MySQLで構築しています。

ちなみにさくらのプランは1Gバイト、2コアのプランです。

 

 

さくらVPSではインストールするOSを選べてその中にWordPress環境に特化したKUSANAGI

というのがあったのだけれど、できれば1から自前で構築したかったので、

あえてCentOS7を選択しました。

おかげでnginxやSSL証明書周りを詳しく学べました😄

 

 

ちなみに環境構築は以下のサイトが参考になります。

https://runble1.com/centos7-wordpress-kusanagi/

よく分からないところはちょくちょく公式のドキュメントを見たりしてれば構築できました。

 

 

構築してみた感想ですが、とにかく動作が早くて素晴らしい!!👏

WordPressも最新のバージョンを使っているので、壊れるということもないですね。

 

 

また、さくらVPSにすることでHerokuでできなかったことがいくつかできるようになりました。

  • FTPでファイルを共有できる
  • サーバのWordPressのソースを直接編集してそのまま結果を反映できる
  • WordPressのソースをGitでバージョン管理できる

 

 

おかげで自由にブログをカスタマイズしたりできそうです。

これだけできて月額1000円くらいなのでさくらVPS契約して良かったです。

 

 

今後やりたいこと

 

基本はてなブログの時のように書きたいことを書いていきます。

ブログのカスタマイズについては今後も記事を書いていくかも。

 

 

あと余裕があったらアフィリエイトとかにも手を出してみたい。

その前にまず人に読まれるブログにしないといけませんが😣

 

まとめ

 

ブログを効率良く運用するにあたってさくらVPS + WordPressコスパ的に優れた選択だと思います。

 

サイト立ち上げもすでに出来ている環境を利用するのではなく、1から環境を構築していったので、

サービスを立ち上げるのに必要な知識も身につけられました😄

 

 

ということで個人的にはさくらVPSWordPress立てるのおすすめ!使っていてとても気持ちいい😄

 

 

Heroku + WordPressはおすすめしません😓

今後はどんどんブログ更新していきますー!

 

 

それではよい1日を〜

 

Nintendo Switch買った!

昨日地元にあるケーズデンキに置いてあったので購入。やったぜ! やはり田舎なのか人がいないせいか普通に置いてありましたね。 新宿や渋谷を探し回っても見つからなかったのでホントに見つかった良かったです。

任天堂ハードって毎回出す度にデザインとか操作性で色々言われることが多い印象なんですが、 今回このSwitchを触ってみた感想としては結構いいんじゃないかと思います。 Switchの立ち位置としてはWiiUの後継機ということになるんでしょうが、実物は据え置き機というよりかは サイズが大きい携帯機といった感じ。大画面でプレイしたければディスプレイに繋げればいいし、外でさくっと やりたければ携帯機として遊べる。
個人的には場所を選ばずスキマ時間で遊びやすくなっていると思うのですごく好印象。
また、コントローラー部分を付け外しできるし、すごく軽いので扱いやすい。
操作性についてはまだあまりプレイしていないのでなんとも言えませんが、悪くはない気はしています。 夏に出るスプラトゥーン2とかは問題なくプレイできそうです。

ちなみにソフトはゼルダを買いました。
ゼルダ風のタクト以来プレイしていないし、今作は評判がものすごくいいので楽しみです。
プレイ後の感想とかもブログに書くかも。

nodebrewを使ってNode.jsをインストール

仕事でnodeを使っているので勉強がてら触ってみる。

まずは環境構築から

開発環境

  • ツールのバージョン
    Homebrew 1.1.11

nodebrewのインストール

nodeのバージョンを管理したいのでnodebrewを使ってnodeをインストールすることにする。
まずはnodebrewをbrewを使ってインストール

$ brew install nodebrew
$ nodebrew -v
nodebrew 0.9.6

nodeのインストール

前述した通り、nodebrewを使ってnodeをインストール

$ nodebrew install-binary stable

上記のコマンドで最新の安定版がインストールできるはずだが、Failed to create the fileというようなエラーが出てインストールに失敗する(エラーログは取り忘れた) これはインストールするためのディレクトリがないために発生している。なので、まずはインストールするためのディレクトリを作成する。

$ mkdir ~/.nodebrew
$ mkdir ~/.nodebrew/src

ディレクトリを作成した後にもう一度インストールを実行すると問題なくnodeがインストールされる

nodeが使えるように設定

インストールしたnodeを実行できるようにnodebrewからnodeのバージョンを選択する

$ nodebrew use stable
$ nodebrew ls
v7.7.3
current: v7.7.3

また、nodeにPATHを通すために以下のように.bash_profileにPATHを追加

$ echo 'export PATH=$PATH:/Users/xxxx/.nodebrew/current/bin' >> ~/.bash_profile

ターミナルを再起動してからnodeを実行

$ node
> console.log('Hello Node.js!')
Hello Node.js!

環境構築おわり。

作業の工数を見積もるときの3つのポイント

自分は今年で3年目のエンジニアになるが、未だに作業工数の見積もりは難しく思う。

今までいくつかのプロジェクトにアサインされてきた。その中で、自分はPGとしてコーディングをしたり、 SEとして設計書作成をしていたが、共通しているのはそのタスクには期限があるということ。
そしてその期限をもって、プロジェクトの全タスクはスケジューリングされている。
タスクには期限を設ける必要があるため、そのタスクについていくつか考えなければならないことがあるだろう。

「そのタスクの成果物は?」
「そのタスクの完了にはどのくらい時間がかかるの?」
「そのタスクはいつ終わる?」

将来の結果を予測するのは難しい。だが見積もりは重要だ。
なぜならいつ終わるのか分からなければ、次のタスクをいつ振ればいいのか決めようがないから。

つい先日、プロジェクト内のPMに見積もりについていい事を聞けたので、ここでまとめてみる。 見積もりのポイントは次の3つ

  • タスクは細かく分割する
  • 工数はフィボナッチ数列を使って見積もる
  • 工数が分かるタスクで相対的に測る

1つずつ章ごとに分けてまとめてみる

タスクは細かく分割する

タスクの見積もりは難しい。それが大きなタスクであればなおさらだ。 タスクは細かく分けるほど正確な工数を見積もれるのだから、タスクを分けるのは重要なことだ。

個人的にはタスクは最大でも3日で終わるような規模にするべきだと考えている。
でないと自分の今持っているタスクを十分に見える化することができない。

例えば「実装」というタスクを振られたとして、その作業をどのように分けるべきか。

実装といってもコーディングして終わり、ではないだろう。コーディングが終わったら動作確認をしたり、 バグがあればまたコーディングに戻り、動作確認が終わればリポジトリにコミットして次はソースレビュー。
レビューで指摘を受けてまたコードを修正、動作確認、…という流れになるはず。
なのでタスクを分割すると以下のような感じ。

  • コーディング
  • ソースチェック
  • 動作確認
  • リポジトリにコミット
  • ソースレビュー
  • レビュー指摘箇所の修正
  • 修正後の動作確認
  • 修正後のソースコミット
  • 修正後のソースレビュー

このように作業に分割すれば見積もりはしやすくなるだろう。
また、ソースレビューは自分の作業だけでは完結せず、レビューが行われるまでは待ちの状態になる。
その点も考慮してスケジュールを組まないと余裕を持って期限内に終わらない可能性が出てしまう。
タスクが十分に分割されていれば、正確に見積もりができ予定通りに作業を完了させられるように なるのではないだろうか。

工数はフィボナッチ数列を使って見積もる

フィボナッチ数列とは1,1,2,3,5,〜と続く数列で、ある値はその前とその前の前の数を足し合わせた値になる。 フィボナッチ数列に登場する値を使うと相手に工数が伝わりやすくなるとのこと。 例えば

1人日:すぐに終わりそう
3人日:そこそこ時間かかるね
5人日:結構かかるな〜
8人日:え!かかりすぎじゃない!?
13人日:何かがおかしい

ポイントとしては5人日以上かかる想定であれば、そのタスクの見積もりは妥当ではないということ。
前の章でも述べたが、タスクは小さく区切るべきであり5人日かかるタスクというのはそもそもタスクの分割が 不十分である。従ってそのようなタスクがあれば、またタスクを分ける作業に戻るべきだろう。 また、1人日、3人日、5人日というような見積もりだけだとかなりざっくりしているが、さくっと相手に 作業時間を伝えることができる。
自分は見積もりに結構時間を使ってしまうタイプなので、この方法を活用して楽出来ればなーとか考えてます。

工数が分かるタスクで相対的に測る

あるタスクの作業量を伝える時、単純に何人日かかると言っても伝わりにくい場合は、 すでにある実績と比較して伝えるとわかりやすいらしい。
例えば、
「以前こういう作業にこれぐらい時間がかかり、今回の作業は誰々さんが実施するので〜倍の何時間かかります」
というような感じ。
この方法なら割と簡単に時間をかけずに工数を見積もれる気がしますね。

自分は実績をものさしにして見積もりをするということはしなかったですが、今後は実績はちゃんと計測して 将来の見積もりに役立てるようにしたいなー。

まとめ

ポイントとしては以下の通り。
1.細かくタスクを分ける
2.フィボナッチ数列でざっくり見積もる
3.タスクは他の作業と比べて相対的に測る

今回はPMとの飲み会でいい話が聞けたので、まとめてみた。
これらのポイントを抑えれば見積もりもきっと上手くなると思うので、これからはちょっと意識してみます。

Android4.3以前の標準ブラウザはplacefolderをサポートしていない

placeholderのcssをどうやって古いAndroidのブラウザにも対応させようかで詰まってたけど、 そもそも対応してなかったというオチ

http://caniuse.com/#search=placeholder

リンク先の通り、Android4.3以前のバージョンはplaceholderをサポートしていない。 もっと早くにこの線で調査すればよかったorz

caniuse便利だね