vivitにjoinして1ヶ月でやったこと

  • こんにちは、今年の6月に入社したspotチームの名嘉眞です。spotチームはキャンプ場検索サービス(hinata spot)を開発しております。私はspotチームのバックエンド担当として日々Goを書いてます。

  • hinata spot

  • vivit入社前は主にRailsを書いていましたので、Goを業務で書き始めたのは入社してからになります。またGoだけでなく、gRPC、GraphQLも業務で使うのは初めてでした。

この記事はどんな記事?

  • vivitに入社してから1ヶ月の振り返りです。vivitでどんな技術を使っているのか、どんな開発をしているのか知ってもらえると嬉しいです。

joinして1ヶ月で自分がやったことを

入社して2日目ぐらいから、ペアプロしながら処理の流れやサービスの役割を教えてもらいました。

ペアプロVSCodeLive Share で先輩エンジニアが実際にコードを書くところを見ながら説明を受けたり、私が書くのを見てもらいながら行いました。

Live Share だと、どちらかがリモートでもペアプロやろうと思ってすぐにできるのが良いですね。

余談ですが、vivitではVSCodeを使う方が多くて、リポジトリVSCodeのsettings.json を管理しています。もちろん、使うエディタは自由です。(ちなみに私のエディタはvimです)

spotはいくつかのマイクロサービスで構成されています。バックエンドのサービス間はgRPCで通信しており、フロントエンドとバックエンドはGraphQLを使って通信しています。 ちなみにフロントエンドはReact+TypeScriptです。

f:id:shin018:20200720113557j:plain

gRPCの通信方式のうち、いまのところspotでは UnaryServerStreaming を使っています。

基本的には Unary で通信しますが、通信の容量が大きくなるレスポンスを返す場合は、 ServerStreaming を使います。

※gRPCの送受信データサイズの上限が4MBのため

※Unaryは単一のリクエストとレスポンスを返す通信

※ServerStreamingは単一のリクエストに対してstreamレスポンスを返す通信

# example protoファイル
# スポット一覧を取得する、returnsで stream と指定するとServerStreaming方式を定義します
rpc GetSpots(SearchRequest) returns (stream Spot);
# example Goファイル
func (s *spotServer)GetSpots(req *spot.SearchRequest) error {
  for _, spot := range res.Spots {
   // stream.Send でstream方式で送信
    err = stream.Send(spot)
    if err != nil {
      return err
    }
  }

  return nil
}

Goに関しては入社前からプライベートで書いていましたが、業務で通用するレベルかどうか少し不安はありました。 実際にはほぼ問題なかったですが、その理由の1つに、業務で使うGoのライブラリを自分がプライベートでも使ったことがあったということがあるかなと思います。

その1つがgorp です。gorpの特徴として、

  • 構造体へのマッピングが楽ちん
  • SELECT系は SQL を書く
  • EXEC系は SQL を書かなくても良い(書くこともできる)

ということがあります。 このライブラリ自体、難易度が高いということはないですが使ったことがあるということで業務にすんなり入れました。

gorpを導入した方に聞くと、構造体へのマッピングは必要だが、JOIN句やORDER BYなどSELECT文はSQLを書きたいということがあってgorpに決めたとのことでした。

また、vivitの別のチームでは他のライブラリを使っていたりしています。

# example Goファイル
dbmap = &gorp.DbMap{Db: _db, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "utf8mb4"}}
var spot *models.Spot
# selectはsqlで自由に書く
err := dbmap.SelectOne(&spot, "SELECT * FROM spots WHERE id = ?", id)

# insertはDBの該当tableと紐づいた構造体であれば下記のように書ける
err = dbmap.Insert(newSpot)

自分の最初のタスクがキャンプ場のレビュー機能の開発でした。

レビューのCRUD機能と投稿されたレビューをもとにキャンプ場の評価を設定するというものです。 このタスクで、Go、GraphQL、gRPCを使った処理の流れを一貫して実装しました。

記事の冒頭にも書きましたが、自分がGo、GraphQL、gRPCを業務で使ったことが無かったこともあり、新しい技術を使えてめちゃくちゃ楽しくできました。

また、実装に迷うところがあってもペアプロしたり、相談しやすい雰囲気、チームで取り組む感じがあったことも楽しくできた理由になります。

f:id:shin018:20200720113625j:plain

まとめ

この記事を書いている今も新機能の開発をしています。

サービス自体にまだまだ足りない機能が多いこともあり、追加する機能の要件定義からエンジニアも携わり、実装・リリースするので、サービスが成長していくことを感じています。 また改善点もあり、その解決に取り組むのも楽しみです。

この1ヶ月では、Go、GraphQL、gRPCを使うことができましたが、フロントエンドや、インフラまわりにも興味があるのでいろいろチャレンジしていきたいと思います。