令和最初の入社ブログ

令和最初の入社ブログ

この記事は書き手である bannzai が「令和最初の入社ブログってエモいなあ」と思い 令和最初の入社ブログ というタイトルのブログを書きたいがために書く入社ブログである。

個人的なご報告含めて書いていきます。

株式会社DeNAに入社しました

令和最初の日である2019年5月1日から株式会社DeNAに入社しました。と言っても初出社はGW明けなのでまだ働いていないのですが。

DeNA では マンガボックス というサービスに携わります。 今までは iOS アプリの開発で Swift をメインに書いていたのですが、次の職場でのメインポジションは Go を用いた API 開発者をになっていきます。

僕は知り合いからの紹介経由で面接したのでここから募集したわけじゃないのですが、募集内容としてはきっとこれですね。

なんでiOSエンジニア辞めたの?

正確にはおそらく iOS もチョット書くのかな。と思っています。
メインポジションが Go のエンジニアと記載した意図としては、今までもメインは iOS をやりつつ RailsGo 等を使用した開発は業務でやっていました。今回の転職を機に比率が逆転しGoの方が書くことが多くなる。と想定しています。
別に会社からどっちもやってと求められているとかではなく性格的に「なんか違うことしたい」って思うとやりたくなる性格なんですよね。iOSは自分の得意なパートでもあるので勝手に気分転換でやっているだろうなー。って予想です。

で、なんでiOSエンジニア辞めたの? なのですが、理由は全然なくて マンガボックス チームに入ってみたいな。空いているポジションは Go のポジションか。サーバーサイドもたまにはガッツリやってみるか。とかこのくらいのノリです。良く言えばこだわりがなくて、悪くいうといいかげんな理由ですね笑

あとは Goマルチプラットフォームでツールを作るのには最適な手段だと思っているので Go により慣れてツールづくりのスキルも伸ばせるのは楽しみですね。 Go 製の OSS 書いて スター乞食 しにいきたいですね。

転職先の決め手

まず、DeNA という会社に魅力を感じたのが、大きな企業ならではなのですがエンジニアの数が多いところが魅力だな。と思いました。以前は創業間もないスタートアップにいて小さな組織だったのですがその時に初めてエンジニアの数がほとんど居ない環境を味わいました。その時になんだか寂しいな。と思い、その点 DeNA さんは人数も多いのはもちろん社内外で開催している勉強会もあり事業をまたいだ交流等も活発なのがとても印象がよかったです。もう少し具体的に言うと最近Swiftコンパイラ等のコンパイラ部分についての興味がだんだん強くなってきました。そういった社内勉強会みたいなのも最近定期的にやっていると聞きとてもいいな。楽しそうだな。という印象を受けました。あとこれに関連するかわからないのですが、僕が配属するチームでは社外勉強会への参加への金銭面でのサポートおよび周りからの理解もありそうでとても嬉しかったです。

マンガボックス チームに関しては@koooootakeさんとお話する機会があり、チームの雰囲気ややり方を詳しく聞けてこのチームは楽しそう。自分が課題に感じていたことも積極的に行えてすごいチームだ。そう思えました。話してもらった内容はDeNA Tech Confというイベントで話していた内容を話してもらいました。このときは僕はこのトークを聞きそびれていたのですが、逆に当事者に逐一質問もできてあった時にはないができてよかったと思います。

他にも DeNA さんには何人か知り合いが居て特にtarappoには社内全体についてどういう風になっているのかは教えてもらえたと思います。外から見ても余裕のある組織である一方新しい事業も立ち上げたりして活発な組織だなと思っていました。外から見た印象や中での様子・エンジニアとしての動きやすさ。といった部分でも大いに参考にさせてもらいました。

最後に

ネタブログのつもりが割と真面目なことを書いてしまった。。。 (2度目)
本当は 2019/05/01令和最初の入社ブログ を書いて公開しようと思ったのですが平成最後に急にやりたいことができてしまって予定通りに行きませんでした。

これが 令和最初の入社ブログ でありますように。

おしまい\(^o^)/

平成最後の退職ブログ

平成最後の退職ブログ

この記事は書き手である bannzai が「平成最後の退職ブログってエモいなあ」と思い 平成最後の退職ブログ というタイトルのブログを書きたいがために書く退職ブログである。

株式会社Asobicaを辞めました。

2018年1月から創業したスタートアップ 株式会社Asobica平成最後の日 である 2019/04/30 をもって退職する事になりました。
最終出社という点では有給消化やGWもありもっと前に終わっているのですが、平成最後の日 であるこの日が正式な退職日となります。 Asobica やそこで開発しているサービスである fever についてはおそらく知名度はさほど高くはなく、ナニソレ感があるかもしれませんがここで事業内容を説明する気はないので、興味がある方はggってください。とはいえ少し驚いたのが国内ではあまり開拓されていない領域でありながら案外サービスが知られているな。って驚いたことも数回あったのでもしかしたらご存知の方はいるかも知れませんね。

何をやっていたの

さて、私が Asobica, ひいては fever というサービス開発で行ってきたことをつらつらと書いていきます。
ちなみにAsobica に転職する前は違う会社に居ました。その時の退職ブログをnoteの方に書いてあるので良かったらどうぞ。(若い頃の俺こんな事書いてたんだ)
株式会社マネーフォワードを退職して新しい環境でチャレンジします

このブログでも軽く書いてあるのですが働き方としてはリモートワークで開発に集中できる環境でした。 コミュニケーションも週に1度出社してそこで取っていきました。僕は基本オンラインベースでコミュニケーションを取っていくってスタンスで働いていきました。 技術スタックについてはサービスに関してのことを広くやっていきました。

まあスタートアップあるあるなのですが、技術者で言うと一つのことをガッツリ深掘りする。というよりはメイン(iOS)はあるけど、必要であれば他の部分も適宜手伝いないし主軸となって開発する。と言った具合の環境でした。しかし、なんでもやる。というよりは僕だったら技術部分に関しては手広く手を付ける。ビジネスサイドや法律周りもウォッチはしていましたが、他のメンバーがそれを担ってくれていました。iOSアプリについてはデザイナーが居ない状態だったため僕の裁量に大体任されていたってiOSアプリのフロント部分を作っていきました。

まだ導入事例が少ないときにGraphQLを使用してのAPI設計やクライアントアプリの実装を共にでき。Goを使ってのサーバーサイドアプリケーションの設計、Dockerを用いた開発。といった内容をチャレンジさせてもらってとても技術的に楽しめた1年でした。
一人でこなす量や範囲が広い分普段そんなにやってなかったことを業務レベルでやれたことはとても良かったです。

僕は技術者として技術やコーディングを楽しみたいと考えています。
その点でいうと Asobica では比較的自分のペースでやらせてもらえたし、上述したように技術に対しての裁量は任せてもらえて満足しています。

なんで辞めたの

これがすべてではないのですが、あえて創業期間もないスタートアップにジョインしたという点に注目してお話します。
まず Asobica に入った大きなきっかけの一つに fever という当時はエッジが効いていたサービス内容に惹かれた部分がありました。 しかし、何度かサービスの方針が変わったりとか諸々の事情ピボットを繰り返しました。本来想定していたサービスとは表面上は結構異なる部分が出てきて少し寂しさを覚えてしまった部分があります。表面上 と言ったのはサービスとして解決したい課題は CEO の中ではブレずにチャレンジをしていったとは思うのでこういう言葉を使用しています。

また小さな組織の楽しさの一つに相談事をパッと相談してパッと決める。決めた内容はもちろん敬意含めて記録しておくのですが、小さい組織故に大掛かりなMTGを開く機会も必要なく、それでいて全体の状況をなんとなくでも把握して置けるのはとてもやりやすく自分も何か思いついた時に発言できるのはとても良いものだ。と思っていました。

ただ、これは僕にも原因はあると思うのですが、ほとんど僕はフルリモートで働いていてコーディング等にはとても集中できたのですが、いかんせん社内で直接会話したような決定事項に付いて追いつくことができていませんでした。これは創業間もない会社にフルリモートの社員と出勤する社員がいるなかで求めすぎた要件だったかも知れないな。と今では思っています。会社にフルリモートを受け入れるくらい情報格差が生まれない仕組みを作ることができればよかったのですが、ここは少し後悔していますね。

とはいえ、学べることや後悔したこともあり次に活かそう。と考えていたり、自分はどういう組織だと動きやすいのか。と言った点がより言語化もできるような体験もできました。 Asobica で経験したことを次に活かしたいと思います。

最後に

ネタブログのつもりが割と真面目なことを書いてしまった。。。
平成最後にやること多くて少し中途半端な終わり方ですが今後のこともどこかのタイミングで書いていこうと思います。

bannzai 先生の次回作にご期待下さい。

おしまい(^o^)/

平成最後のライブラリ

平成最後のライブラリ

みなさん今日で平成も終わりですね。というわけで 平成最後のライブラリ を作ったので紹介します。

EraCalculator

EraCalculator というライブラリを作りました。 機能は例えば 平成 をもし他の元号 大化 などで表した時に何年表記になるかを計算してくれる内容になっています。 大化 は645年始まりで 平成 は 1989年始まりなので 1989 - 645 = 1344 ですね。これを 1 足した結果を 大化 1345年 としています。

let converted = EraType.平成.convert(to: EraType.大化)
print(converted.eraType) // 大化
print(converted.year) // 1345年
print(converted) // 大化 1345年

なんでこんなの作ったの

アヒージョ作ろうと思ってたら f:id:bannzai:20190430225802p:plain

別の世界線にいる 狂気のマッドサイエンティスト を喜ばせることになりました。 f:id:bannzai:20190430225949p:plain

最後に

意外と新しい元号の発表盛り上がりましたね。 完全にこれにあやかったネタライブラリだったのですが、急ピッチで作る感覚がハッカソンみたいで楽しかったです。 これ書いて一つ知れたことは元号めっちゃあるやん。ということでした。興味があれば覗いてください。250個くらいあります。 ここから見れます。

え?需要があるかどうか?無いと思いますよ?何言ってるんですか?

需要は無いでしょうがスターはほしいです。

スターください

おしまい\(^o^)/

🍵を作りました

🍵を作りました

表題の通りOchaを作りました。
この記事ではOchaを紹介したいと思います。

Ochaについて

OchaはSwiftで作ったライブラリです。 しかし、iOSmacOSのライブラリじゃなくてPCで動くプログラムになってます。 Ochaは指定した(1以上の)ファイルの変更を検知するプログラムです。 Ochaでできることはファイルの変更・保存・削除をもとに自分の任意のプログラムを走らせることができる。そういった役割のプログラムです。 たとえばファイル保存した時にインデントを整える。ファイル消した時に Delete file << FILE_PATH >>の形式のコミットメッセージでgit add, git commit する。 といったことの実現を補助するためのライブラリになっています。

使い方

Ochaの使い方を簡単に紹介します。 まず、FileSystemのイベント監視をするためのクラス。 Watcher クラスを作成します。この時に監視したいファイルパスも渡してあげましょう。

let watcher = Watcher(paths: [pathString])

次にFileSystemのイベントを検知を開始したい時にstartメソッドを呼んであげましょう。このstartメソッドの最後の引数のclosureはイベントを検知した時に実行されます。

watcher.start { (events) in ... }

具体例

上述したような ファイル消した時にDelete file << FILE_PATH >>の形式のコミットメッセージでgit add, git commitする。を実際に動かしている例をOchaリポジトリExampleとして載せています。

Exampleとして書かれているコードを下に載せます。こちらを見てもっと具体的な書き方を把握してみましょう。

import Foundation
import Ocha
import SwiftShell
import PathKit

print("You can confirm `Ocha.GitCommitExample` when removed file. Try rm -rf Package.swift and conform git history(e.g git show. You can got new commit for it message of 'Delete file [Package.swift] path'. ")

let path = Path(
    #file.components(separatedBy: "/")
        .dropLast() // main.swift
        .dropLast() // GitCommitExample
        .dropLast() // Sources
        .joined(separator: "/")
)
let pathString = path.absolute().string
main.currentdirectory = pathString

let watcher = Watcher(paths: [pathString])
watcher.start { (events) in
    let removedEventPaths = events
        .filter { $0.flag.contains(.removedFile) }
        .map { $0.path }
    removedEventPaths.forEach { path in
        main.run(bash: "git add \(path)")
        main.run(bash: "git commit -m \"Delete file \(path)\"")
    }
}

RunLoop.current.run()

なんとなく何がやりたいかは読めるのではないかと思います。後半のwatcher.startの内容を少し整理しながら見ていきましょう。
先程も説明したようにFileSystemを監視したいタイミングでwatcher.startを呼びます。
次にCLIrm -f Package.swift を実行します。この時に消すファイルは Package.swift である必要はありませんが、Watcherに渡しているディレクトリ配下である必要があります。ちなみにFinder上からのGUI上からの削除はゴミ箱の移動扱いになり、削除とはまた違う扱いになるためこのExampleはうまく機能しません。
rm -f Package.swiftを行ったにstartの最後の引数であるclosureが実行されます。この時にどのようなイベントが発生したか、どのファイルが対象か。といった情報を詰め込んだ構造体が引数として渡ってきます。このeventsをもとにどういったことを行いたいかを記述していきます。今回だとファイルが削除された場合にgit add << FILE_PATH >>, git commit -m "Delete file << FILE_PATH >>を実行をしたいです。
Eventにはflagがあり、これを用いてremovedFileのイベント対象となったファイルパスを取得しています。 そしてこのファイルパスの配列を用いてgitコマンドを実行する流れになっています。

モチベーション

Ochaを作ったモチベーションは主にファイル保存時に特定のコードフォーマッタかけたいなあ。かけれたらいいな。
ブログをローカルで書いているときにコミットメッセージはどうでもいいからファイル保存時にコミットとりあえず積んで安心感を得たい。ちょうどいいタイミングでsquash等を行ってきれいなログにする運用にしたい。などなど思ったのがきっかけでした。
Swiftのライブラリという点では、僕はSwiftを書くEditorとしてXcodeを使っているのですが、Xcodeではファイルイベントに応じてスクリプトを実行するような機能は用意されていません(僕の知る限りでは)。Compileの前後等のタイミングでScriptを挟めたりするのですが、このタイミングだとやりたいことに対してタイミングが遅いと感じる場合もあると思います。

そういった課題を感じたためOchaというライブラリを作りました。

なぜ 🍵 なのか

Watcher(監視者) の響きを日本語にしたときの アナグラム になっています。
うぉっちゃー → おっちゃー → おちゃ

以上。

技術について

Ochaの技術については本ブログでは紹介しません。代わりに(?)Ochaで使用されている技術の解説本を技術書典6で販売します。 SwiftKotlin愛好会というサークルで執筆者の一人としてSwiftでどのようにFileSystemを監視するか。と言ったことをOchaのコードベースに書いていきます。

サークル名: SwiftKotlin愛好会
URL: https://techbookfest.org/event/tbf06/circle/71750003

興味がある方は是非お越しください。複数人での共著なのでSwift・Kotlinネタが他にも載っている一冊となります。

素敵なロゴを描いてもらいました

OchaのREADMEを見るとわかるのですが素敵なロゴが載っています。
井上乃彩 / Noa Inoueさんに描いていただきました。とても可愛くて素敵なロゴをいただきました。見るたびに少し見とれてしまいます。 経緯を話すと Ochaにロゴが欲しい & 最近デザインツールを個人で触っていて他の人はどういう情報を元に作るんだろう。と気になりそれで声をかけて関わっていただきました。本当に素敵で感謝です。

噂のロゴです。

f:id:bannzai:20190405032805p:plain

まとめ

SwiftはまだAppleプラットフォーム、特にGUIアプリケーション開発に頻繁に用いられる開発言語と言えるでしょう。
Ochaも実はCocoa依存なのでmacOS上でのみ動くコマンドラインツールなのですが、それでも普段開発しているようなiOSアプリ等の開発とは毛色が違います。今回はFileSystemを監視する。というテーマのライブラリを作りました。Ochaは単体では機能せず処理内容は自分で記述する必要があります。が、 Ocha自体は小さなライブラリとなっておりExampleもシンプルで比較的応用例も浮かびやすいのかな。と思っています。普段GUIアプリケーションを開発している方でもCLIツール作成して便利なツールを作りたい方はOchaを利用するのも是非ご検討してください。

このライブラリが便利!最高!クール!ロゴかわいい!と思ったそこの貴方へ

スターください 🍵

おしまい \(^o^)/

connpass で勉強会を主催している皆様へ

connpass で勉強会を主催している皆様へ

connpass で勉強会を主催している皆様へ、運営しているconnpassのグループに対する 参加, キャンセル, お問い合わせ のアクションがあった場合にSlackに通知するGAS(Google Apps Script)を書いてOSSにしたのでご報告申し上げます。

https://github.com/bannzai/connpass-notification

なぜつくったのか

僕はDXELという勉強会の主催をやっており、connpassを使って参加者の募集を行っています。connpassでイベントの運営メンバーだと参加者の 参加キャンセルお問い合わせ などのアクションが発生した場合にメールで通知を受け取ることができます。しかし、(僕は)メールってあまり見ないし、connpassのこういった内容はGmailのラベルを付けてGmailからの通知の対象から外してしまっていたりしています。
とはいえ、こういった動きがあった場合状況をなんとなく把握したいな。お問い合わせもSlackのpublicなチャンネルに通知されれば自分ができない場合も誰かが対応してくれるだろう。 そういった要望が内外であったのでconnpass-notificationをつくりました。

connpass-notification

connpass-notification は比較的汎用的に作りました。
なので、connpassで会を主催する方でそれ専用のSlackのworkspaceがある方には使えるツールになっているかと思います。このツールを使いたいモチベーションはおそらく僕と一緒なようなモチベーションを持って導入するのだろうと予想しています。このツールを使える人の前提があります。

  • Gmailアドレスを使用してconnpassのアカウントを作っている。
    • たぶんFacebookログインでFacebookアカウントの登録メアドが Gmail とかの場合でも大丈夫。他のSNSアカウントでも同じことが言える。
  • Slack使っている。
    • イベント専用の Slack の workspace があるとなおよし

上記が必須条件かと思います。

つけくわえるとするならconnpass-notification は汎用的に使っていると言いましたが、自分たちが使っている GmailSlack に対する設定を行う必要があります。また、 このツールを実際に稼働させるためにGoogleが提供している clasp というツールも用います。

これらの手順はgithubに手順書としてREADMEに記載があります。
設定に関しては Configureセクション
ツールの稼働に関してはDeployセクション に記載してあります。
こちらを見ながら自分で動かせる人である。そういう人が身の回りにいる。必要があります。

実際に動かしている感じ

下の画像は運営しているイベントへの 参加キャンセル が発生した場合のSlackです。

この画像は運営しているイベントへの お問い合わせ が発生した場合のSlackです。

絵文字や色についてはEventsで定義してあるのでこちらもカスタマイズしたい場合は自由に変更できます。よくみるとところどころリンクがあるので、仮にユーザーページ見たいな(あまりないとは思うけど)とか、送られてきた Gmail のリンク開いてメッセージの全文みたいな。ってなった場合は比較的楽にアクセスできると思います。本文を流すことも考えたのですが、最初はコンパクトな通知で運用していこうと思ってこうしています。課題に感じたら本文も流そうかと。

DXELでの運用形式

設定

READMEのConfigureを見るとわかるのですが、設定ファイルに各アクション(参加・キャンセル・お問い合わせ)に対してそれぞれ別のChannelに通知ができるような設定ファイルになっています。もちろん同じチャンネルにも通知ができます。

function settings(): _Settings {
  return {
    'appName': 'Gmail',
    'searchWord': 'from: no-reply@connpass.com',
    'registerWebHookURL': 'https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ',
    'registerNotificationChannel': '#registerOrCancel-channel',
    'cancelWebHookURL': 'https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ',
    'cancelNotificationChannel': '#registerOrCancel-channel',
    'contactWebHookURL': 'https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ',
    'contactNotificationChannel': '#contact-channel'
  }

registerXXXXcancelXXXXcontactXXXX がそれぞれ 参加キャンセルお問い合わせ に対応しています。
別チャンネルにした場合は個別に WebHook URL を用意したりすればおkです。

DXELではお問い合わせだけは別チャンネルにしています。 参加・キャンセルはそんなに重要じゃないというかなんとなく流れて把握できればいいな。とは思うのですが、お問い合わせは見逃しにくい状態が好ましいなと思い(僕が勝手に)そうしました。お問い合わせは公開日に一気に登録や開催前にキャンセルが発生する傾向にあるわけでもないので、自分の未読管理もしやすく専用チャンネルによってメンバーもそこには注目しやすくなるはずです。

自動化

connpass-notificationGoogle Apps Script(GAS) で作成しました。 細かく言うなら clasptypescript を使用して作ったものを gs に変換して使っているといった具合です。 GAS には一定間隔で定期実行してくれる設定があるのでWebページからその設定を行います。DXEL では無料プランの枠に留まる数分程度の間隔で適当にやっているのでリアルタイムの通知とまでいえるほどの頻度では実行はしていないです。 とはいえ、普段よく使っている Slack に自動で流れてるのはとても嬉しいですね。

注意点

connpass-notification の細かい注意点として Slack に通知された Gmail のメール(正確にはスレッド)は既読状態にしています。
つまり、たとえば Gmail のサービスでメールを実際開いてなくても Slack に通知されたあとだとすでに読んだ状態になっているので未読のものでフィルタリングとかかけている場合はひっかからなくなります。
connpass-notification では、等間隔で定期実行するユースケースを想定して設計してあります。 通知までの原理は単純でGmail の検索にひっかかったものを Slack に通知します。その場合に前回通知したものからの差分で更新ということができたら理想なのですが、やれるかどうかいまいちわからなかったので、メールの既読・未読で判断することにしています。 未読のものは通知する必要があって、既読のものは通知がする必要がない。と言った判断基準にしています。

何かいい案(というかそういう機能がある)場合は GitHubissue や、 bannzaiTwitterアカウントとかにでも連絡していただけると嬉しいです。

最後に

connpass-notificationDXEL でも使い始めたばかりです。実際良かったよ。と言った話はまだできないのですが、同じような要望がある方はぜひ使ってください。
PR・issue 等もお待ちしております。

僕が一番欲しいのはスターなので、スターください

おしまい \(^o^)/

gqlgenでTypeにプロパティを追加してみよう

gqlgenでTypeにプロパティを追加してみよう

前回ではgqlgenでサーバーをlocalhostに立ち上げて、GraphQL Playgroundから実際に Query が実行されるところまで確認できました。

今回は一度コード生成された後にGraphQLのインタフェースを変えたい場合どう実装していくのか書いていこうと思います。

gqlgenSchema first でGraphQLなAPIを作るためのライブラリです。
schema.grpahqlを編集してGoのコードを再生成するところまで確認していきましょう。

前回

まず前回までのまとめなのですが、下記のQueryを実行すると Todo.id の一覧が取得できたことまで確認しました。

Query

query {
  todos {
    id
  }
}

Response

{
  "data": {
    "todos": [
      {
        "id": "1"
      },
      {
        "id": "2"
      },
      {
        "id": "3"
      }
    ]
  }
}

今回はこの Todotitle というプロパティを足していきたいと思います。

schema.graphqlの編集

初めに schema.graphql を編集していきましょう。今回は Todo にプロパティを追加していくので下記のスキームに注目します。

type Todo {
  id: ID!
  text: String!
  done: Boolean!
  user: User!
}

上の type Todo から始まるものはレスポンスの形式を表しています。 ID! 型の idString! 型の text というプロパティがあるといった具合ですね。これは gqlgen generate の後に models_gen.go にコードが吐き出されます。 今のままの Todo では id,text,done,user の4つのフィールドはレスポンスとして返せますが title は返すことができません。title を返せるようにするためにまず schema.graphql を編集して Todotitle を追加しましょう。

type Todo {
  id: ID!
  text: String!
  done: Boolean!
  user: User!

  title: String! # ここが追加
}

Scehma first を謳っているgqlgenではスキーマファイルと実装するGraphQLのインtらフェースが合うように開発を進めていきます。
先ほど、titlte: String! の部分を追加しました。続いてこのschemaの情報をGo のコードに反映させていきます。

Goのコードを生成する

前回ではgqlgen initした結果、ExmapleのGoのコードが作成されました。
追加したフィールドをGoに反映させたい場合はgqlgen generateを実行します。

$ gqlgen generate

ちなみに短縮して gqlgen とだけ打って実行しても構いません。

$ gqlgen

実行後 generated.go, models_gen.goが変更されていれば成功です。
特に models_gen.goの中身を確認してみましょう。
TodoTitle というプロパティが追加されていることが確認できると思います。

 type Todo struct {
    ID    string `json:"id"`
    Text  string `json:"text"`
    Done  bool   `json:"done"`
    User  User   `json:"user"`
    Title string `json:"title"`
 }

次に前回と同様にresolver.goTodos メソッドを編集していきましょう。

func (r *queryResolver) Todos(ctx context.Context) ([]Todo, error) {
    return []Todo{
        Todo{
            ID:    "1",
            Title: "First",
        },
        Todo{
            ID:    "2",
            Title: "Second",
        },
        Todo{
            ID:    "3",
            Title: "Third",
        },
    }, nil
}

これで完了です。GraphQL Playgroundから結果を確認してみましょう。

$ go run ./server/server.go

サーバーが立ち上がったあら下記のQueryを貼り付けて実行してみましょう。

{
  todos {
    id
    title
  }
}
{
  "data": {
    "todos": [
      {
        "id": "1",
        "title": "First"
      },
      {
        "id": "2",
        "title": "Second"
      },
      {
        "id": "3",
        "title": "Third"
      }
    ]
  }
}

画面はこのような具合になっていると思います。

終わりに

今回はプロパティの追加するというユースケースを通して gqlgen の機能を使い Schema first で実装をしていきました。

GitHubにここまでの内容を公開しています。
https://github.com/bannzai/gqlgen-demo

branchは fix/add/field となっています。前回からの差分としてPRを一つ作ってあります。
https://github.com/bannzai/gqlgen-demo/pull/2

この記事がいいと思ったら、GitHubのスターください

おしまい \(^o^)/

gqlgenでGraphQLサーバーを立ててみる

gqlgenとは

gqlgenとはGraphQLのSchemaベースでGraphQLサーバーの開発を進めるためのライブラリです。最近ではでmercariがmercari tech conf 2018のサーバーのプログラムをGraphQLで書いていて、「お」と目を見張りました。今回はそんな gqlgen の導入部分を記載していきたいと思います

なおGraphQL自体についてはこの記事では割愛します。
GraphQLについて知りたい方は公式のページがあるのでこちらをご覧いただければと

本題に入る前に

導入部分を書く前にこの記事を書いた時点でのgqlgenの情報を載せておきます。
この記事を書く時点での最新のtree
この記事を書く時点での公式のドキュメント

本題

最新のドキュメントはここから確認できます。本記事でもこちらを参考にしながら話を進めます。が、多少割愛してまずはGraphQLとして機能するサーバーを立ち上げることを目標にします。Getting Startedをまず見ていきましょう。

まずライブラリのインストールです。 dep等のパッケージマネージャーを使っている人は適宜変えてください。

$ go get -u github.com/99designs/gqlgen github.com/vektah/gorunpkg

さて、インストールが終わったら gqlgen init を実行してしまいましょう。あらかじめ用意しておいてGitリポジトリを使っている前提で git statusでどんなファイルができたか確認します。

$ gqlgen init
Exec "go run ./server/server.go" to start GraphQL server
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        generated.go
        gqlgen.yml
        models_gen.go
        resolver.go
        schema.graphql
        server/

gqlgen initの実行により下記のファイルたちが作られました。 それぞれの役割を簡単に記述していきます。

  • schema.graphql
    • GraphQLのスキーマを書く
    • 書かれたスキーマgqlgen generate を経て各 .go ファイルに Golangのコードとして内容が記載される
  • generated.go
    • gqlgen generateでこのファイルの中にGraphQLの処理に必要な処理が吐かれる
    • schema.graphqlで記載したスキーマ情報やそれに沿ったResolverTypeの情報
  • gqlgen.yml
    • gqlgen generateの際にプロダクションによってカスタマイズしたい場合に記載する設定ファイル
    • 何が設定できるかはここを参照
  • models_gen.go
    • gqlgen generateの際にGraphQLのType等を Golangstruct が書かれる
    • schema.graphqlに記載されたものからコードが作られる
    • Resolver 以外のものがここに吐き出されると思ってもらえたらいいかも。 Type,Input,Scalar,Enum and so on...
  • resolver.go
    • gqlgen generateの際にGraphQLのQueryMutationの処理を書くためのResolverが用意される。
    • Resolverは各Query(or Mutation)を処理するためのメソッドを持っている。それを処理する役割と捉えてもらえると。他のフレームワークやライブラリでもこの用途でResolverという名前で出てくる。
    • Type が 1つ以上のfieldを持つ場合もここに吐き出される。
  • server/server.go
    • go run ./server/server.go でサーバーを試せるようになっている

さて、これで実はデモを試す最低限の準備はできてしまいました。
gqlgen init の時点でExampleに必要なSchemaやそれに沿ったGolangのコードが生成されています。
Todoという例でドキュメントには書かれています。今の状態でこれと同じものができています。便利。

ではローカルホストにサーバーを立ち上げ、 http:localhost:8080 にアクセスします。

$ go run ./server/server.go

下記のようなページが立ち上がれば成功です。

これはGraphQL PlaygroundCDNを利用して立ち上げています。GraphQL PlaygroundGraphQL IDEという立ち位置みたいですね。このツールでQueryをインタラクティブに確認することができます。
というわけで下記のQueryを書いて動作を確認してみます。

query {
  todos {
    id
  }
}

結果がjsonで帰ってきたのが右側の画面を見て確認できると思います。
しかし、実行してみると何やらエラーが出ています。エラーが起きずに正しくデータが取得できている場合はdataの項目にtodosの結果が返ってきて、errorsの方はフィールド自体が存在しないはずです。

なぜエラーが返ってきたのかなのですが、gqlgenではQueryを処理する役割のResolverのコードが生成された時点ではpanicを呼ぶコードが埋め込まれています。当たり前のことなのですが、GraphQLのインタフェースを通った後の内部の処理はその都度書く必要が出てきます。gqlgenではコード生成されたタイミングで下記のようなテンプレなコードが埋め込まれています。これは resolver.go を見て確認することができます。

func (r *queryResolver) Todos(ctx context.Context) ([]Todo, error) {
    panic("not implemented")
}

では、ここに[]Todo 型の値を返すようにコードを下記のように変更してあげましょう。

func (r *queryResolver) Todos(ctx context.Context) ([]Todo, error) {
    return []Todo{Todo{ID: "1"}, Todo{ID: "2"}, Todo{ID: "3"}}, nil
}

雑ですが、配列で3つの要素を返してあげています。
$ go run ./server/server.go を再度実行してみて動作を確認してみましょう。先ほど遠同じQueryを投げてみます。 下記のように表示されていれば成功です。

終わりに

これで gqlgen を導入して GraphQLサーバーを立ち上げるところまでできました。次回は実際にschema.grpahqlを編集してgqlgen generateでコード生成をするといったことも書けたらと思っています。

GitHubにここまでの内容を公開しています。
https://github.com/bannzai/gqlgen-demo

branchは introduction/gqlgen となっています
https://github.com/bannzai/gqlgen-demo/tree/introduction/gqlgen

この記事がいいと思ったら、GitHubのスターください

おしまい \(^o^)/