Androidエンジニアからベンチャー企業でサーバーサイドエンジニアに転向して半年経って分かったこと

8/20入社だったので2/20でUbieに入社して半年になりました。つまりサーバサイドエンジニアに転向して半年経ちました。

以前の記事でこんなこと書いたので、続編を書いてみようと思います。

半年くらい働けば、きっと悪いところももっと見えてくるはずなので、来年落ち着いたらまた続編を書いていきたいと思います。

Ubie, incに入社しました。 - shiraji’s diary

今月のツイートを冷静に眺めてみるとそこまで自社に関してのツイートしていないし、恋は盲目状態から解放されているようなので、冷静に自分のことを分析してみようと思います。

サーバーサイドにキャリアチェンジしてどうだったか?

サーバサイドにキャリアチェンジしたのが正解だったかどうかに関してはまだわかっていません。これに関しては結論が当分出ないような気がしています。ただ、以前のエントリーにも書いてありますが、元々AndroidアプリもUIのことより通信だったり、パフォーマンスだったりを主に見ていたため、AOSPの辛さがなくのびのびKotlinを書けるという環境は本当に楽しいです。今後、多くのネイティブアプリエンジニア達がサーバサイドに目を向けるようになってきた時にサーバサイドKotlinというのは一つの可能性でもあるし、ガンガン発信していって、サーバサイドKotlinのプレゼンス高めていきたいという想いがあります。

新しいチャレンジ

新しいチャレンジとしてはGraphQLに手を出し始めたのは自分にとって大きな出来事でした。

shiraji.hatenablog.com

shiraji.hatenablog.com

GraphQLといえばGo、Rubyなどといった言語を使うのが主流な気がしますが、JVM言語でも可能性あるのでは?というところまで自分の中で良い印象を持っています。さらにここにKotlinならではの良さを追加出来ないか?と模索しているところです。

Androidアプリ開発と比較しての設計

設計に関しては、Androidアプリのように活発な動きはなく、特にAPIの作成の時などはシンプルな構成になります。ただし、Androidアプリでの経験が活きないか?と言われるとそれは間違っていて、Androidアプリで利用したDIやクリーンアーキテクチャなどは元々サーバサイドにあったものですし、そのまま利用することが出来ています。

開発環境

今まではAndroid Studioを使っていましたが、IntelliJ IDEAに乗り換えています。Android StudioIntelliJを両方使ったことある人であれば、わかると思いますが、特に使い勝手は変わらず、多くのサーバサイドKotlinサポート機能が乗っていて、そこの乗り換えコストはほぼ0です。(自分はIntelliJ IDEAでプラグインを開発していたという経験もあるので、生存バイアスかかってるかもしれませんが。。。)

さらにCoroutineやテストツール(JUnit5やmockkなど)など馴染みがあるツールをそのまま利用できる事もあり、サーバサイド辛いなーと感じることが少ないです。

サーバサイドエンジニアとしての課題

自分が今課題と感じているのが、自分自身、結構ネイティブアプリの開発に注力しすぎてしまったため、ネイティブアプリのライブラリなどの知識は深くなっていますが、昨今のウェブの開発スタイルにまだ馴染めていません。UbieではGCPを主に使っていますが、GCPにどんな機能があるのかを完全に把握しておらず、実装しようとして、あれ?その機能GCPにあるのでは?というツッコミを受けたことがあります。その機能がどういうものなのか?などの把握はそこまで時間がかからないのですが、自分の引き出しの少なさにちょっとがっかりしています。

サーバサイドの進化はネイティブ開発に比べ遅い!と勝手に思って7,8年前までのサーバサイド開発のスタンスでいたのですが、これは完全に間違いでした。

Androidアプリエンジニアとしての不安

Androidアプリ開発の一線から退いて半年経ち、一番の不安は、最新のライブラリのキャッチアップが出来ないことです。例えば、JetPackの存在は知っていますし、コードはある程度眺めています。しかし、仕事でJetPackを使っていないですし、経験がありません。今年のGoogle IOでまた新しいものが発表された時、それに対して何かしら自分がアクションを起こせるかどうかは正直不明です。そのため、もしAndroidアプリエンジニアとしてカムバックしなくてはならない時、何かしらキャッチアップ期間がないと厳しそうだなーという感じています。

実際、今サーバサイドエンジニアにカムバックしたといえばカムバックした訳で、このキャッチアップに時間を使っているというのも不安です。半年経った今でもまだサーバサイドエンジニアですと胸張って言えないような感じなので、キャッチアップって結構時間かかるなーという印象を持っています。

ベンチャー企業に入ってどうだったか?

今までいくつかの企業で働いていて、上場してない企業としてはUbieは2社目です。それ以外の会社は全て上場していて、多くのユーザーを抱えている企業でした。1社目は10人くらいで、今回は現在20人くらいなのでほぼ変わらない規模です。こういう会社に入ると感じるのは自分の稼働が会社へダイレクトに良くも悪くも影響を与える事です。変なバグを出してしまったりすれば会社は潰れるかもしれませんし、逆に素晴らしい機能を出せば一気に会社が大きくなる可能性があります。自分が会社を動かしているかも?という錯覚すら覚えて喜べます。1社目で感じていたのですが、こういう感覚が好きなエンジニアには小さい会社ありだなーと改めて思いました。

f:id:shiraji:20181220164930j:plain
アイキャッチ画像がなかったから、無駄に、自分のデスクのマスコットのアー写置いておく。

ルール

新しい会社にはよくあることですが、ルールが決まっていないかったり、そもそもなかったりします。必要であれば社員みんなで議論して、即ルールを制定しています。

こういうことは小さな会社だから出来る自由さ、フットワークの軽さがあって、すごくいいなーと感じています。

働き方

働き方は今までよりワークライフバランスを特に意識するようになりました。これはリモートワークがいつでも自由に出来る状況*1であることが起因しているのですが、やろうと思えば、深夜でも早朝でも土日でもプライベートの時間を削って仕事が出来る状況になっています。 自分のプライベートのGitHubアカウントを会社でも使っているので、GitHubの通知を見ようとすると会社の通知とOSSの通知を同時に受け取ってしまえます。さらに言うと、自分の会社の出社時間が10:00-17:30でだいたい多くの人より早く帰っており、家で足りない稼働分(30分)働いています。そのためそのまま流れで気づいたら仕事してたみたいな状況に陥りがちです。会社の今のフェーズはできるだけ多くのリソースを割いて、サービスをどんどん良くしていくというのはわかっています。しかし今まだ設立1年半のこのタイミングでエンジニアがいっぱい残業してしまうと今後入ってくる人もそういうのを会社は期待してしまうし、それは健全ではないと思っているので、自分1人だけでもワークライフバランスを特に意識しています。

タスク

任されているタスクは結構自分から手を挙げたものが多いです。

  • サーバサイドKotlinの実装
  • DBテーブルの設計・実装
  • 協力会社との連携処理の設計・実装
  • SREの細かいタスクのサポート
  • bot作成(これはほぼ遊びか?)

今フロントエンジニアの質がものすごく充実しているように見えます。結構勉強出来そうな環境です。しかし、今の自分がフロントで足引っ張るより、サーバサイドや人が足りていないSREで足引っ張った方が会社のためになるでしょという判断をしたため、SREエンジニアの修行させてもらっています。手取り足取り @sakajunquality から知見吸えているのですごく良い判断したなーって思っています。

時間の使い方

これまでの会社と一番違う部分は実は時間の使い方なんじゃないかと思っています。今までの会社ではリーダーだったり、外部の方とのやりとりだったり、雑多な管理だったり、採用だったりと、そこまでまとまったの時間を開発に割いていませんでした。(これだけ読むとダメじゃんー!って思われるかもしれませんが、自分はこれはこれで実は結構好きだし、楽しかったです。)

今の会社では毎週以下のような時間割でやっています。

  • 会議(3時間15分 *2 )
  • その他、定期的ではない会議や採用周り、週平均2時間くらい
  • 残り週30時間以上は開発

この定期的な会議の多くは出社推奨日の水曜にまとめています。そのため、結構まとまった時間開発することが出来ています。ただ、これでも自分の会社の滞在時間の制限があるため、週1以上は必ずリモートで仕事をし、より長く開発に時間を割けるように工夫しています。

初めての経験

Ubieに入って初めての経験がいくつかありました。

OKR/KPT

スクラムなどは経験あったのですが、今まで業務でOKRやKPTを実際にやったことがありませんでした。OKRは今期から本格的に実施することになり、会社から本を買ってもらい、みんなで勉強して実施するようになりました。KPTは良かったことを褒め合う機会と問題の共有・対処の検討などをしっかりやれるのが気に入ってます。

アウトプットする人が多い

今まで自分より登壇する回数が多い同僚と働いたことがなかったです。Ubieでは社外へのアウトプットを推奨しており、エンジニアはもちろんのこと、デザイナーや医師、Bizもアウトプットする機会があればどんどんアウトプットしています。これがすごく刺激的で、自分ももっとアウトプットしたい!という気持ちが湧いてきます。

名前

これは入社時からだけど、会社で初めて「しらじ」って呼ばれてる。呼ばれすぎてて、社外の方と話すときに、自分のことを本名で呼ばれたりするとドキっとするようになってしまった。。。

引っ越し

先日Ubieは引っ越しをしました。新しい場所は三越前駅徒歩10秒です。

goo.gl

今までも席替えやビルの部屋が変わるなどは毎年1,2回のペースで経験してましたが、オフィスの場所が変わる引っ越しは初めての経験でした。新しい環境で働くのはいつもワクワクなので、引っ越してもそこまで変わらないだろうなーって思ったのですが、引っ越して駅から近くなって、オフィスも広くなって、会社の成長をモロに実感出来たのがすごく嬉しかったです。ベンチャー企業の醍醐味だなーこれ。と感じています。このオフィスも2年以内に引っ越す予定なので、次はもっと大きな場所で働けるようにがんばろー!って気分になれました。

最後に

Androidエンジニアからのキャリアチェンジですが、SREにも手を出してますし、今のところうまく進んでいる気がします。会社の成長を感じられるのが本当に嬉しい日々です。

さて、こんなUbieですが、引き続き、いろんな職種を募集しています。

speakerdeck.com

随時オフィス見学やUbie Dayなど社外の方を呼んで来てもらうようなイベントもやっていますので、興味あれば、TwitterでメンションやDM下さい。

*1:最大週2で、出社推奨日もあります

*2:1時間チーム内KPT, 30分全体KPT, 30分採用定例, 1時間エンジニア定例, 15分業務委託の方と1on1

DroidKaigi2019に参加しました

DroidKaigi2019に参加することが出来たので、感想を書いておきます。

聴講したセッション

1日目

  • ウェルカムトーク
  • マルチモジュールなプロジェクトでテストはどう変わる?
  • マルチモジュールプロジェクトでのDagger2を用いたDependency Injection
  • Server-side Kotlin for Frontend: 複雑なAndroidアプリ開発に対するアプローチ
  • PWAでここまで出来る
  • Exploring the Android Transform API
  • Fireside chat && 懇親会

2日目

  • build.gradle.ktsに移行しよう
  • 夕飯

ウェルカムトーク

動画カッコ良かった。あとで納品されたのが当日9:30頃でめっちゃヒヤヒヤしたという話をtnjさんがしてて、ウケた。

それと、mhidakaさんのマイクがなんか変な音がしてて、聴きづらく、少し我慢してたのですが、誰も反応してないし、意を決してツイートしたら即対応してもらえた。(実際は自分のツイート起因なのかは不明だけど、嬉しかったので、そういうことにしておこうw)

マルチモジュールなプロジェクトでテストはどう変わる?

登壇者のテストが好きだというのがにじみ出ているようなトークでした。本当にテスト好きなんだなこの人!ってワクワクして聴かせてもらいました。 内容としては、DeNAさんのものなのかわからなかったですが、テストの方針やモジュールをどのようにテストするのか?とPITの紹介という感じでした。 わかりやすく噛み砕いてくれて、かなり参考になりました。スライドがシンプルで良かったです。

前半部分の方針の説明だったのですが、もう少し具体例が欲しかったかなと思いました。 方針の説明だから仕方ないのですが、それでもコードなどを示しつつ、方針と噛み合わせてくれたらさらに深く理解出来たと思います。 PITの説明に入ったら、具体的になって、その内容の面白さに会場がすごく盛り上がっていた印象を受けました。あれは本当に良かった。

マルチモジュールプロジェクトでのDagger2を用いたDependency Injection

去年に引き続き、kgmyshin さんのマルチモジュールのお話。 去年マルチモジュールの初歩的な話をしてもらい、今回具体的な実行編って感じの二部構成!って感じで勝手に感動してました。 スライドがすごく特徴的で、うまく手書きと図を使われており、流石だー!と感じました。

また、概要説明->実コード->概要説明->実コードと本当に素晴らしい流れで、めちゃめちゃわかりやすかったです。 いやーやっぱkgmyさんすごいなーと終わった時に改めて思いました。

Server-side Kotlin for Frontend: 複雑なAndroidアプリ開発に対するアプローチ

マイクロサービスを自社で導入しており、今後拡大した時にどうなるのか?BFFはどういう助けになるのか?が知りたくて聴講しました。 FiNCさんの過去の話からBFF採用するまでなどのお話でした。辛い辛い辛いーそうだよねそうだよね!という感じで結構感情移入しちゃって聴けました。 これは完全に自分の責任なのですが、遅れて入ってきたため、後ろの席で聴いたこと+登壇直前にツイートしてもらったスライド公開が残念ながら出来ていなかったこと+スライドの文字が多かったこと と不運が重なってしまい、スライドをめくった時にスライドを読むことに注力せざるを得ず、話を聞き逃すことが若干ありました。。。 なので、登壇後に直接いくつか質問させてもらいました。丁寧に回答頂き、なるほどーって結構な回数言わせてもらいました。(今スライド見返すと回答が書いてあったので完全にアホな質問ばかりだったかもしれません。。。)

FiNCさんはFin Techってネタは爆笑しました。(FiNCさんはヘルス事業の会社です。)

PWAでここまで出来る

自社が、PWAにベットしているので、あんまり説明も読まずにタイトルだけで聴講決めました。 今年のDroidKaigiで一番バズったのでは?と思う誤発注のDiverseさん所属の方の登壇でした。 DiverseさんがAndroidのFlutterエンジニア募集してると聴いておー!Flutterここまできたかーと驚きました。

PWAの基本的な紹介があり、その後TikTokさんに似たPWAサイトを作ると言う話でした。 PWAのGoogle Playでの公開方法の説明は実は初めて知って、おおおお!!!って驚きがありました。 作ってるものは本当に良かったし、話の内容もすんなり入ってきたし、面白いなーって聴けたのですが、一つだけ悲しいこと言っちゃうとコードの文字が小さくて全然読めなかった・・・。一つ前の時間で質問していて、席が後ろになったのが敗因でした。。。

ちなみに次の日に自分が同じ部屋で登壇するということもあり、参考にさせてもらいました。

実はこの登壇者の SAMUKEI さんとは2日目にホールで自分の登壇の質問待ちでボケーっと座っていたら、見つけてもらい、話しかけてもらえました。 最初赤髪の人と目が合ったー!こっち近づいてくるー!やばいー!!!とちょっとドキドキしたのですが、話してみるとすごく気さくな方で話やすく、楽しかったです。話終わった後に、あれ?そういえばあの人PWAの登壇者だったじゃん。って思い出して、あーPWAの話もっとすれば良かったと後悔しました。またどこかでお話しさせてください。

DroidKaigi2019ではDiverseさん面白い人多いと言う印象になりました。きっと来年はmini usb -> type cの誤発注してくれるでしょう!

Exploring the Android Transform API

これに関して言うと、自分にとって今年のDroidKaigiで一番楽しかったです。あまりに楽しすぎて、感想なんて要らない、みんなとにかくこのトークの動画を観るんだ!です。 簡単に説明するとAndroidでは使えないJava9のメソッド List.of をTransform APIで作り、Androidで動かしてしまおうと言うハッキーなお話です。まじで動くところまでライブコーディングしてます。動画が待ち遠しい。

Understanding Kotlin Coroutines: コルーチンで進化するアプリケーション開発

次に mhidaka さんの 「Understanding Kotlin Coroutines: コルーチンで進化するアプリケーション開発」を聴こうとしたのですが、早めに行ったと思ったのに、立ち見になっており、立ち見できる体力なかったので、泣く泣く諦めました。mhidakaさん人気すぎるんだよ。。。

Fireside chat && 懇親会

Fireside chatを聞こう早めに乗り込んだのですが、ちょっと遠く、声が聞こえませんでした。なので、会場入ってすぐに無理して聴くのを諦め、近くにいた方達と話していました。あの会場でのFireside chatは厳しいと思います。

懇親会はある程度知ってる方と話した後、新規の方との交流開拓のため、結構ぷらぷら歩いていました。

ただ、歩いてる時に話しかけられることはやっぱりない。
↓
テーブルに止まると話しかけてもらえる。
↓
でもテーブルに止まるには何か止まる理由が必要。
↓
テーブルに皿なら置ける
↓
食事・デザート・飲み物を持ちまくる。

ということでかなり食べてしまったような気がします。。。自分から話しかけるの無理なので、どうにか出来ないものか・・・。初めての人ともいっぱい話したいんだ。おかしな性格だ。

この懇親会でPixivの方にAndroidの勉強になるお話をしてくれたら、扇子くれるというイベント?やってました。こういうの話しかけるきっかけになるので良いですね!

inside.pixiv.blog

食事で並んでいたら見かけたので、「Find Pull Requestプラグインを作りました。」と言ったら、ポカーンとされて、完全に滑ってしまったわ。辛い。ってなったのだけど、別のPixivの方が「お世話になってます。」って言ってくれて扇子出してもらいました。めっちゃ嬉しかったです。

ステッカー以外のノベルティ特に反応しない息子くんもこれは気に入ったようで、返してくれません

f:id:shiraji:20190209121332j:plain
自分の登壇のMVP

Pixivの方に伺ったのですが、この扇子、Droidくんが入っているのですが、Googleさんに権利関係で連絡したとのことで、Pixivさんやっぱりサービス特性上、著作権周りもしっかりされているんだなーと感心しました。

build.gradle.ktsに移行しよう

二日目は登壇があり、自分のセッションより前のセッションは何も聴かず、自分の登壇後はすんごい倦怠感に襲われ、セッション聴くのを諦め控え室で引きこもってました。 体力が回復しつつあったので、去年に続き、tnj さんのgradleの話を聴きました。 build.gradle.ktsへの移行方法をプロジェクト作り、一つずつ手順を教えてくれました。 また、スライドには置換で活躍する正規表現も逐次記述しており、これがあれば簡単にbuild.gradle.ktsに移行できそうと言う印象を受けました。 こう言うビルドの話大好物なので、本当に楽しかったです。

2日目、控え室でtnjさんを見つけて、Android Studio 3.3.1当日リリースの被害を受けたということで記念に写真撮ってもらいました。

特に登壇の影響なくて良かった、いや良くなかった。バグが直ってないとtnjさんが混乱してる姿が面白すぎました。

夕飯

控え室でのんびりしてたら、gfxさんがご飯どうですか?って誘ってくれました。それなら!とこの会に興味ありそうな方にも声かけて、最終的に6人でご飯食べに行かせてもらいました。結構色々な話が出来て、本当に楽しかったです。

あの中で圧倒的に自分のスキルが一番低かっただろうなーって思い知ったので、もっと技術磨かなきゃって感じでした。


さて、ここからは話変わって、自分の登壇の話になります。

登壇

今回は2日目の14:00~でした。登壇の話を書く前にCfSの話から書こうと思います。

CfS

DroidKaigiのCfSがオープンになったということで、募集要項を確認しました。

droidkaigi.jp

なんか色々カテゴリがありますが、一番重要であろう点はここかな?と理解しました。

応募に当たって以下の3点を満たしていると採択されやすくなります。

Android specific: Android 固有であること
Expertise: よく知られている情報ではなく、専門性があること
Innovation: いままでに可能でなかったことを可能にしていること、革新性があること

この三つを満たしている物をCfSに書けば通るだろうと。

  • JetPackを本番で使ったことがなく、最新のAndroid開発周りでExpertiseとInnovationを満たすのは難しそう。
  • Kotlinはもう当たり前なのでチャンスあるとしたら、Coroutineだろうけど、自分より専門性高い人が多い分野だし、競合も多そう。
  • そうなるとAndroid Studioプラグイン開発かなー?と思ったけど、これは以前NGだったし、どこのカンファレンスでも需要がないのか今まで一度も通ったことがない。

今回やっぱり無理かなーと諦めていたら、同僚がJetBrainsのIDE使っていて、あれ?この設定使ってないの?ということが偶然あって、お?そういえば普段使われていないようなAndroid Studioの設定発掘したら面白いかも?とひらめきました。

そこからちょっとPreferencesを上から全部見ていって、設定を変えることにより、どうなるのか?を調べていきました。 そしたら、知っているもの含め、10個くらい面白そうな設定が出てきたので、一人で語りながら設定変えて実演してみたら、30分くらいに収まったので、うし、これでいくか!とCfS書きました。

CfSの書き方は特に奇抜なことはせずに全部書き出しました。

2014年末からAndroid Studio v1.0.0が出てから、ほとんどの方がAndroid Studioを使ってAndroidアプリの開発をしていると思います。
IntellijをベースにしたAndroid Studioでは非常に多くの機能が存在しています。しかしあまりにも多いため、埋もれてしまっている便利な機能があるのではないのでしょうか?
このセッションでは、Android Studioの隠れた便利な機能を紹介して、Android Studioを使った開発をより快適に出来るようにお手伝いしたいと思います。

以下の知識がある方を想定しています。
* Android StudioでAndroidアプリの開発をしたことがある
* Android Studioの設定をあまり変えたことがない
* 複数人での開発を主にしている
* セッション中にすごいと思ったら「おー!」って言ってくれる

このセッションでは以下の設定の話をする想定です。独断と偏見で大半の方が触らないであろうと思った設定を中心に説明します。
* 自分専用のアクションリストを作ってみる
* !=をカッコ良く
* 通知周り
* File Color
* Kotlinのファイルフォーマット忘れ防止
* 急に別の言語書きたくなった時のストレス発散方法
* JSON書きやすくする
* Run Configurationや.ideaの共有
* Layout Editor
* Pluginのインストールの強制

しっかり話す内容全部書き出したので、当日の齟齬は無かったはず。

これでCfS通らなかったら、Ubie, incに入社しました。 - shiraji’s diaryにも書いてあるとおり、Android開発から遠ざかっていますし、そろそろDroidKaigi卒業かなとも思ってました。その後、CfS通過連絡を受けて、まだまだDroidKaigiは自分を必要としてくれてたー!って結構喜びました。

登壇前

登壇前に、音声が出るのか不安だったため、運営の方たちに確認したところ、色々調整してもらい、ランチ時間にRoom1を使わせてもらえることになりました。 あの時間にRoom1にいた人たちは「なんだこいつ?」って感じだったと思います。申し訳なかったです。ランチ中にいきなり現れて、息子の動画とAndroid Studio喋らせてるヤツいたらそりゃそうなりますわ。。。

登壇時

twitter.com

意識していた「ライブ感」が本当にうまくできるのか?がすごく心配で、それが緊張を引き起こしてました。本当にみんな「おー!」って言ってくれるかな?って。音声チェックの時のように何こいつ?みたいな反応にならないかな?って。でも運営の人たちが緊張をほぐしてくれたので、だんだん調子が出てきました。

Macを見ずに俺を見ろ

この発言みんな笑ってくれたのが本当に助かりました。これで完璧に吹っ切れることが出来たと思います。きっと「おー!」の練習しっかりやってくれると。

ただMac見なくていいとは言いましたけど、まさかその時間でOS更新しようとするツワモノが現れるとは想像してませんでした。面白すぎる。DLは家でしてきたんですよね?

「おー!」の練習

そして、本番。すっごく盛り上がってくれました。やはりかわいいは正義だ。

その後、自己紹介中に「おー!」って言われたのは全く想定してなくて面白かったです。もうこの時には緊張なんて全くなく、全力で楽しんでいました。いい雰囲気でした。

Android Studioがしゃべった!

この辺、ライブ感満載で最高です。

Kotlinのスタイル設定

Kotlin Repositoryがこれを導入していたので、この設定は知っていたんです。でもこれが盛り上がるってことはみんなKotlinのコントリビュート環境整備してないってことなので実は寂しい!!!

コンディション設定してたのに間違って消しちゃうやつ!

この設定見つけた時すごく興奮した覚えがあります。というかこれ本当にデフォルトにしてほしい!

Inject Language

Inject Language自体が理解するの難しい機能で、それを説明して、その特定の不便さを説明して、それを解消する設定の説明っていう周りくどい感じだったんですよね。。。それを takahirom さん的確に説明してくれていて、さすがー!って思いました。

Prefer XML editor

推し

Notification出過ぎ

再起動中祈ったのに、結局いっぱい出てくれちゃって、あー!もー!!!って感じでした。練習ではもう一回再起動したりしてたのですが、なんか会場盛り上がっちゃったから、このままでいいかーって感じで流しちゃいましたwライブって感じ。

ツイートしてる暇がなかった

狙い通りです!

予約投稿

Twitterへの予約投稿は身内?であるたろうさんが反応してくれてました。本当にテレビの副音声みたいな機能に出来たらなーって思ってたので、嬉しい。

副音声ツイートは SocialDog さんを使わせてもらいました。TweetDeckで当初やる予定だったのですが、投稿予定だったツイートを確認する術がわからなかったため、選定出来ませんでした。

Room1がトレンド入り

登壇直後にハッシュタグ #Room1 がトレンド入りをしたと連絡もらいました。記念にスクショ撮っておきました。

f:id:shiraji:20190210042632p:plain

トレンドのロジックを全く理解していないのですが、Room1はそもそも各時間一番人が入るし、直前があのMotionLayoutのお話だし、いまいち何かを達成した感がないです。(そもそもTwitterじゃなくて俺を見てくれ!って話だったわけで・・・)

入れなかった方がいた・・・

開始直前まであのRoom1が満員になるなんて想像してなかったです。1部屋に入っていい人数って法律で決まっていると思うので、運営の方たちも自分もどうしようもできないので、ごめんなさい!としか言えないです。希望者全員に聴いて欲しかった。ライブ感をものすごく押し出していたので、furusinさんや他にもし会場入れなかった人がいらっしゃったなら、配慮が足りてなかったかもしれないです。本当に申し訳ないです。。。

登壇後

登壇後、良く見るすごい人たちが集まってきて「どうやって設定共有するの?」という質問を受けました。みんな同じ疑問を持っていたようです。

話を登壇中に戻すと、当初全ての説明が終わっても5分残っていたら、11個目の説明をしようと考えていました。10個目の説明の「Required Plugins」を話始めたタイミングで残り5分を切っており、さらにNotificationが出過ぎハプニングのため、会場が盛り上がってました。そんな良い感じの雰囲気のまま「Required Plugins」の説明は残り3分のところで終わりました。最後に感謝の言葉を言うのは30秒もあればできるので、強引に続けてもよかったのですが、練習不足であるのが明らかで、せっかく盛り上がったのに、話を延長して、残念な終わり方は嫌だなー。終わりよければ全て良しだよなーって逃げの気持ちが先行してしまい、そこで「ありがとうございました」と締めてしまいました。

が、やはりあの出来る人たちには見逃してもらえない感じでした。そこで、.ideaの設定共有の話をしたのですが、仕組み自体はただのファイルをgitで管理しているという簡単なものなので、1分もかからずみんな納得してくれて「あーこんな簡単ならやれば良かった・・・完全にチキンだったー」と自己嫌悪でした。

オフィスアワー

登壇後の質問で囲まれた時に運営の方に「やっぱりオフィスアワーやりますか?」と言われました。これは自分の聞き間違えだったかもしれないです。 そこで自分は(あ、自分はオフィスアワーなしだったんだ。)と勘違いしてしまい、質問対応後、そのまま控え室に戻りました。

そしたら、どなたかが、オフィスアワーで待ってくれてた様で、それを知った時には次のセッションが始まっていました。

そこで運営の方が色々動き回ってくれて、こんなツイートをしてくれました。

諸々対応して頂き、ありがとうございました!今後もいつでも回答しますし、DMも空いてますので、何か質問あれば今からでもしてください。

まとめ

とにかく楽しかったです。

自分は年2回くらいしかこういう大きなイベントには参加しないので、運営の人や他の参加者の方達よりゆるいスケジュールで当日過ごしました。 しかし、二日後のいまだに体が本調子に戻らなくて、ちょっとまずいなーって感じです。もうちょっと外に行こうか・・・?

Android開発者ではないので、次回のDroidKaigiでCfS突破できるようなネタが探せるのか?が課題ですが、来年も登壇出来たらなーって考えています。おもしろ登壇枠があればきっと大丈夫だと思うのですが・・・

運営の方たちの細かな気配りがいっぱいありました。色々対応して頂き、ありがとうございました。

そして、最後に、自分の登壇を聴いて下さった方たち、当日「おー!」と盛り上がってくれて本当に本当に本当に話しやすかったです。すっごく気持ち良かったし、楽しかったです。ありがとうございました!!!

Android Studio設定見直してみませんか? -詳細-

このブログはDroidKaigi 2019Android Studio設定見直してみませんか? の詳細です。 せっかく聴いてくれる方がメモを取ってて話を聴き逃してもらいたくないためのエントリーです。

登壇中何らかの問題が発生した時の対策でもあります。

前提

  • 設定の遷移の区分けはJetBrainsの公式と同じで「 | 」です。「Preferences | Keymap」という記述の場合、Preferencesの中にあるKeymapというメニューを表しています。
  • Macを使っている前提で話が書いてあります。
  • Android Studio 3.1から3.3.1での動作確認はしています。

Quick Lists

リファクタ、Surrend With、右クリックなどをすると出てくるポップアップがあると思います。

f:id:shiraji:20190202145813p:plain:w300 f:id:shiraji:20190202145726p:plain:w300
いろんなポップアップがあります

これ、実は自分専用のポップアップを作ることができます。

Preferences | Appearance & Behavior | Quick Lists

と遷移するとQuick Listsを作成する画面が出てきます。

f:id:shiraji:20190202150153p:plain
Quick Listsの設定画面

ここの「+」をクリックし、「Display name」にはわかりやすいものを設定し、ポップアップに表示したいアクションを追加します。

f:id:shiraji:20190202150414p:plain
shiraji quick listsというQuick Listsを作ってみました

「Find Actions」で「Display name」に入力した値を選択すると、自分でカスタマイズしたポップアップが表示されるようになります。

f:id:shiraji:20190202150617p:plain
Find Actionsに表示される

f:id:shiraji:20190202214450p:plain
自分専用のポップアップが!

このQuick ListsはKeymapを設定することも出来て、便利です。

f:id:shiraji:20190202150740p:plain
keymapも設定できる

Font ligatures

!=, ->, ==ってITエンジニアなら読むことは出来ると思うのですが、!=は≠と表示される方がカッコイイです!(主観です)Android Studioではこの表示をサポートしています。

Preferences | Editor | Font

Enable font ligaturesにチェックを入れ、Font ligaturesに対応しているフォントに変えます。

f:id:shiraji:20190202151148p:plain
Fontはデフォルトで入っていてFont ligaturesに対応しているFira Codeを選択

そうすると、コードがこんな感じに表示されるようになります。

f:id:shiraji:20190202151032p:plain:w300 f:id:shiraji:20190202151234p:plain:w300
左が変更前、右が変更後

Notification

右下や右上に出てくるポップアップです。

f:id:shiraji:20190202151703p:plain
Power Save ModeをONにすると出てくるポップアップ

このポップアップですが、すぐ消えちゃったり、何度も出てきてイライラさせたりしてくれます。 全てのポップアップにはIDが振られており、Notificationの設定で表示方法を変えることができます。これは3rdパーティのプラグインも含まれます。

f:id:shiraji:20190202151917p:plain
Gradle Syncが終わったらポップアップを表示させるようにしてみる

今回紹介したいのはこの設定ではなく、どのNotificationでも使われていない、「Read aloud」という設定です。

f:id:shiraji:20190202152300p:plain
どの設定もOFFになっている

Gradle Syncの設定の「Read aloud」を選択して、Gradle Syncをしたらどうなるでしょう? Notificationの内容をAndroid Studioが大きな声で何秒かかったのかを伝えてくれます!(この渾身のネタが文字でしか伝えられない悲しさ・・・)

ちなみに当日は、「おおおお!」とAndroid Studioさんに言ってもらうためのプラグインを使い、褒めてもらいました。

github.com

File Color

File Colorはデフォルトで利用されているので、結構みんな知らないうちに使っている機能だと思います。Project Viewにあるテストコードの背景が黄緑になっています。これがFile Colorです。

f:id:shiraji:20190202184757p:plain
背景が黄緑色になっている

f:id:shiraji:20190202184859p:plain
タブも色が変わる

File Colorは便利な利用方法があります。

Preferences | Appearance & Behavior | File Colors

f:id:shiraji:20190202210717p:plain

上の方のWindowにある、プラスボタンをクリックします。

「Scope」を「Production」として、「Color」を「Blue」としてみます。そうすると、「Run」ボタンを押して、アプリを起動する時に利用されるソースコードが青くハイライトされるようになります。

f:id:shiraji:20190202210853p:plain
青くハイライトされる

Build Variantを変えても即反映されます。

f:id:shiraji:20190202211137p:plain
Build VariantをpremiumReleaseにしたら、debugのソースのハイライトが消え、premiumのソースがハイライトされた

コードフォーマット

コードフォーマットにはいろんな方法が提供されています。

昔よく話に上がっていたのは、reformat code/organize importsなどを保存時に実行するマクロを組むとか、Eclipseのデフォルト機能から作られたであろう、Save Actions - Plugins | JetBrainsというプラグインを導入する、Commitダイアログにあるreformat code/organize importsなどにチェックして、Commitする。

f:id:shiraji:20190202212158p:plain
Commitダイアログのコードフォーマットの設定

ここで紹介するのは、コードを書いているときに、コードフォーマット漏れしているかを確認する方法です。

Preferences | Editor | Inspections | Kotlin | Style Issues

KotlinのInspectionの中に「File is not formatted according to project」という設定があります。これを有効にして、「Severity」を「Error」とします。

f:id:shiraji:20190202212545p:plain

これでプロジェクトのコードフォーマット設定に違反したコードを書くと文法エラーのような表示なります。

f:id:shiraji:20190202212658p:plain
コードフォーマットされていないとエラー表示になる

この赤線のところで、「Option(Alt) + Enter」をすると、「Reformat File」という選択肢が出るようになります。

f:id:shiraji:20190202212737p:plain
Reformat Fileという選択肢が出る

そこで「Reformat File」を選択すると、フォーマットされるようになります。

f:id:shiraji:20190202213134g:plain
簡単にコードフォーマットできる

これを利用すれば、コーディング中にフォーマットされているかどうかの確認が可能です。Android Studio上でエラー表示になっているだけで、ビルドは問題なく出来ます。

余談ですが、特定の箇所をCode Formatしたくない場合もあると思います。そう言う場合は

Preferences | Editor | Code Style

「Enable formatter markers in comments」を有効にし、「@formatter:off」と「@formatter:on」で括れば、フォーマットエラー表記もされないようになりますし、「Reformat File」しても無視されます。

f:id:shiraji:20190202214019p:plain
コードフォーマット対象にはならない

Breakpointsの削除

Breakpointsはデバッグ時に必須なものです。Breakpointsを特定の条件下のみ発動することも可能です。Breakpointを右クリックし、「Condition」を入力すればその「Condition」がtrueの時のみBreakpointで止まります。

f:id:shiraji:20190203013509p:plain
Breakpointに条件を追加する

で、このBreakpoint、作るときも削除するときも簡単で、クリックしたら出来ちゃいます。

f:id:shiraji:20190203013747g:plain
ワンクリックで簡単すぎる削除・・・

結構複雑な条件を設定したにも関わらず、誤ってワンクリックで消してしまい、またその条件を入力しなくてはならなくなった経験ありませんか?筆者は首がもげるくらいあります。

この問題への対処方法があります。

Preferences | Build, Execution, Deployment | Debugger

「Remove breakpoint」のところにある、「Confirm removal of conditional or logging breakpoints」を有効にしてみてください。

そうすると、条件付きのBreakpointをクリックすると、削除するか確認ダイアログが出現するようになります。

f:id:shiraji:20190203014225p:plain
削除するか確認ダイアログ

Inject Languages

Inject Languageと言う機能は生のStringに対して、JSONYAMLなどの言語に対するサポートができるようになる機能です。

対象のStringにカーソルを合わせ、「Option (Alt) + Enter」を押し、「Inject Language or reference」を選択します。その後、そのStringの言語を指定したら、その言語のサポートを受けられるようになります。

f:id:shiraji:20190203015402p:plain
同じ文字列なのに、コードハイライトが有効になっている

また、ここではJSONを利用しているため、「Edit JSON Fragment」と言う機能も利用でき、それを利用すると、別WindowでJSONを入力したら、エスケープなどを良しなにやってくれるようになります。

f:id:shiraji:20190203015606p:plain
下のWindowで編集したら上の文字列に反映される

この機能は非常に便利なのですが、チームで共有するためには、@language("JSON")//language=jsonなどを記述しなくてはなりません。この記述は「Inject Language or reference」を選択したタイミングですぐに再度「Option (Alt) + Enter」を押せば補完してもらえるのですが、忘れがちです。

f:id:shiraji:20190203020224p:plain
アノテーションをつけるかを聞かれる。別のアクションをしたら消えてしまう!

この問題を解消する機能があります。

Preferences | Editor | Language Injections | Advanced

この設定画面の一番下にある「Add @Launguage annotation or comment if needed」を有効にします。その後、もう一度「Inject Language or reference」を選択すると、@language("JSON")//language=jsonを最初から補完してくれるようになります。

Layout Editor

Android開発者なら誰もがお世話になるだろうLayout Editorの設定の紹介です。

f:id:shiraji:20190203135101p:plain

このLayout Editorは設定がいっぱいあって、なかなか面白い機能ではあるのですが、今回紹介するのはこの画面の設定ではなく、Preferecesの方の設定を変えてみます。

Preferences | Editor | Layout Editor

f:id:shiraji:20190203135321p:plain

この三つの設定のうち、一番上にある、「Prefer XML editor」という設定。有効にしてみて、もう一度Layout Editorを開いてみます。

f:id:shiraji:20190203135434p:plain
Prefer XML editorを有効にして、開き直しても特に見た目の違いが見えない。。。

よーく見てみます。

f:id:shiraji:20190203135607p:plain
本当に違いがあります

Textタブの位置が変わっています。

f:id:shiraji:20190203135655p:plain
Textタブの位置が左に!!!

デフォルトでは、Designが左で、Textが右。

f:id:shiraji:20190203135757p:plain
デフォルトはこれ

細部までこだわり抜いて作られている感じがします。

Preferenceのパスのコピー方法

これは設定というより機能のお話です。

登壇中もこのブログでも特定の設定画面への遷移を「Preferences | Keymap」のように記述していました。たぶんここを読んでいる方も社内や自分のドキュメントで設定への遷移を書いたことある人いるのではないでしょうか?

これをタイピングするのは、なかなか厳しいです。そこでこの機能を使うと便利です。

f:id:shiraji:20190203165414p:plain
Preferences | Build, Execution, Deployment | Gradle をタイピングするのは大変

左側にあるTree的なメニューにポインターを合わせ、右クリックしてみてください。「Copy Preferences Path」と出てきます。これをクリックすれば、そこまでのパスをコピーすることが出来ます。

f:id:shiraji:20190203165546p:plain
Copyメニューが出てくる

Pluginのインストールを強制する

特定の機能を使っている場合、チームで必須で使うプラグイン揃えたい時があると思います。例えばDatabindingを使っているプロジェクトでDatabinding Support - Plugins | JetBrainsを入れるとか。

登壇で使ったプロジェクトでは、自分がどんなタイピングをしたのか、どんなActionを実行したのかをあとでみやすくなるように、Presentation Assistant - Plugins | JetBrainsを強制していました。

Preferences | Build, Execution, Deployment | Required Plugins

プラグインの強制方法はこの設定画面で、現在使っているプラグインの中から強制するプラグインを選択します。

f:id:shiraji:20190203173216p:plain

これらのプラグインをインストールせずにプロジェクトを開くと、右下のところにエラーが表示されます。

f:id:shiraji:20190203173110p:plain
プラグインがインストールされていない場合、エラーが出る。

このエラーポップアップの「Install required plugin」というリンクをクリックすると、インストール予定のプラグインの詳細が表示されます。OKボタンを押すと、全てのプラグインをインストールしてくれます。

f:id:shiraji:20190203180205p:plain


当日の発表は多分ここまでです。これ以降は時間の都合上、発表することが出来なかったお話です。


設定の共有

ここまで色々設定変更を見てきましたが、これらの設定はチーム内で共有することが可能です。多くの設定はプロジェクトの.idea内に含まれています。

f:id:shiraji:20190203181739p:plain
.idea内に設定ファイルが格納されている

externalDependencies.xmlは必要なプラグインの設定、vcs.xmlはバージョンコントロールの設定だったりします。

ただし、例えば、workspace.xmlのようなその個人の設定ファイルも含まれてしまっていますので、必要に応じて、.gitignoreなどでコミットしないように注意が必要です。

github.com

GitHubのgitignoreにJetBrainsのものが公開されていますので、それを参考にすると良いと思います。

icon.png/icon_dark.pngというファイルがあると思います。これはそのプロジェクトiconとして認識されます。

f:id:shiraji:20190203182650p:plain
プロジェクトのアイコンが表示される

ちなみに、最近Android Studioの対応がされた、Toolboxでもアイコンが表示されます。

f:id:shiraji:20190203182808p:plain
Toolbox便利なのでぜひ使うといいと思います

Android StudioをNotepadにしてみよう!

最後に(最初から?)ちょっとAndroid Studioで遊んでみます。

Android Studioにはいろんなボタンや空白などがあります。これを全て消すとどうなるか!?を試してみます。

f:id:shiraji:20190203183042p:plain
初期表示

「Hide All Windows

f:id:shiraji:20190203183255p:plain
Tool Windowを隠す

「Tabs Placement」を「None」に

f:id:shiraji:20190203183407p:plain
タブが無くなった

「Show line numbers」を「OFF」に

f:id:shiraji:20190203183558p:plain
行番号が消えた

「Status bar」を「OFF」に

f:id:shiraji:20190203183647p:plain
最下部のStatus Barが非表示に

「Navigation Bar」を「OFF」に

f:id:shiraji:20190203183748p:plain
上部のNavigation Barを消した

「Show Gutter icons」を「OFF」に

f:id:shiraji:20190203183900p:plain
行番号の横にあったスペースがなくなった

「Tool Buttons」を「OFF」に

f:id:shiraji:20190203184030p:plain
外枠のボタンが全部なくなった

「Breadcrumbs」を「Don't Show」に

f:id:shiraji:20190203184125p:plain
下部のスペースがなくなった

ここまで来るともうNotepadとほぼ見分けが付きません!画面が有効活用出来そうです!

ちなみに、ここまでやってしまって、最初に戻す方法は用意されていません。Macの場合、~/Library/Preferences/AndroidStudio3.3/optionsフォルダを消せば元に戻せます。実行は自己責任でお願いします!

まとめ

以上、DroidKaigi2019の Android Studio設定見直してみませんか? の詳細でした。

これを聴いてくれた、または読んでくれた方が1人でも設定変えてみたり、他にも面白い設定/機能ないかなー?ってAndroid Studioの探訪をしてくれると嬉しいなーって思います!

宣伝

さて、Ubieでは、こんな感じで、便利なものを積極的に採用して開発を進めています。もし、Ubieに興味出てきたなーって方はぜひ、@shiraj_iにDM下さい!

サーバサイドエンジニア以外にもいろんな職種募集していますので、こちらもぜひ確認してみてください。

speakerdeck.com

GraphQL(Kotlin)とStackdriver Traceの美しさに惚れました。

GraphQL(Kotlin)とStackdriver Traceがすごくいい感じだったから見て欲しい。

実装

ここで公開したアプリに修正を加えてみました。

shiraji.hatenablog.com

github.com

ライブラリの追加

spring-cloud-gcp-starter-traceを使い、Stackdriver Trace*1利用するため、gradleに変更を加えます。

repositories {
    mavenCentral()
    jcenter()
+    maven(url = "http://repo.spring.io/libs-milestone")
}

dependencies {

+    val springCloudGcpVersion = "1.1.0.RC2"
+    compile("org.springframework.cloud:spring-cloud-gcp-starter-logging:$springCloudGcpVersion")
+    compile("org.springframework.cloud:spring-cloud-gcp-starter-trace:$springCloudGcpVersion") {
+        // remove this after 1.1.0.RELEASE
+        exclude(group = "io.grpc")
+    }
+    compile("app.ubie:brave-kt:1.0.0")

https://github.com/ubie-inc/kotlin-graphql-sample/commit/b0aee867adf13e3e2ef41e8c3e8a5979619995f3

exclude(group = "io.grpc")しているのは、1.0.0.RC1よりバージョンが上のspring-cloud-gcp-starter-traceを使うと、io.grpcが複数のバージョンに依存してしまう問題があるためです。以下で問題提起しています。1.1.0.RELEASEで修正が完了する模様です。

github.com

環境変数などを変更

次に、Stackdriver Traceを利用できるように環境変数などを変更しています。 GraphQLのクエリをログ出力するために、graphql.GraphQLのログレベルをDEBUGに変えています。

  cloud:
    gcp:
      trace:
-        enabled: false
+        enabled: true
      logging:
-        enabled: false
+        enabled: true
  sleuth:
    sampler:
      probability: 1.0
@@ -24,3 +24,4 @@ logging:
  level:
    root: INFO
    org.springframework.jdbc.core.JdbcTemplate: DEBUG
+   graphql.GraphQL: DEBUG

https://github.com/ubie-inc/kotlin-graphql-sample/commit/beb23dc3b858c1cd8cbead49d2f7c1a0abd59b21

Scope Spanを使い、さらに見やすく

最後に、brave-ktを利用して、各クエリがどれくらい時間がかかっているのかを確認するTraceを入れます。

-        if (icd.isBlank()) return emptyList()
-        return jdbcTemplate.query(
+        return Tracing.currentTracer().scopedSpan("findKinkiDrugsByIcd") {
+            if (icd.isBlank()) return emptyList()
+            jdbcTemplate.query(
                 //language=SQL
                 """
                 SELECT
                   yj_code,
                   icd
                 FROM
                   disease_kinki_drug
                 WHERE
                   icd = :icd
                 """.trimIndent(), mapOf("icd" to icd), rowMapper
-        )
+            )
+        }

https://github.com/ubie-inc/kotlin-graphql-sample/commit/25e8e477b365f037daa4948dc94b24ff5789709a

brave-ktに関しては以下の記事に書いてあります。

shiraji.hatenablog.com

結果

ライブラリ追加して、ちょこっと見やすい工夫を入れるだけなのですが、以下のような結果が表示されるようになります。

f:id:shiraji:20190116030939p:plain
Scope Spanを使い、各DBアクセスの時間を見えるように

f:id:shiraji:20190116031047p:plain
1クエリ内で発行されたログも表示できる

f:id:shiraji:20190116031125p:plain
リクエストクエリなども見える

特定のクエリに対して、どのSQLがどのタイミングで発行され、どれくらいの時間がかかっているのか?などが一目でわかるようになりました。

感想

めっちゃ便利。この結果が美しくて惚れました 😍

宣伝

さて、Ubieでは、こんな感じで、便利なものを積極的に採用して開発を進めています。もし、Ubieに興味出てきたなーって方はぜひ、@shiraj_iにDM下さい!

サーバサイドエンジニア以外にもいろんな職種募集していますので、こちらもぜひ確認してみてください。

speakerdeck.com

*1:Stackdriver Traceを利用するには https://cloud.google.com/trace/docs/quickstart?hl=ja を参照

Twitterエゴサーチで見る2018年まとめ

今年本当に自分のエンジニア生活が一変した年だったので、書き留めておく。(2年連続同じ文言)

shiraji.hatenablog.com

技術的な話は皆無です。ツイートと共に自分のための振り返りです。ので、自分のことを知りたい人以外が読んでもらっても多分「あ、そう。」という感想だけしか得られないはずので、戻るボタンクリックお願いします。

1月

2018年はこんなところからスタート

実はですが、初詣に行って、嫁ちゃんに今年で転職しそうだね。しっかりお祈りしときな。と言われて、(ははーん!この人何も俺のことわかってないね!結婚して何年経ったんだよ?)と思ったけど、今日の時点では(何で自分より自分のことを知ってる人がこの世に存在するんだ・・・?)と言う畏怖の念を抱いております。

2月

DroidKaigiがありました。How to Kontribute v4をやりました。このネタは結構な回数こなしてたんですが、あんまりうまくやれずに悔しい思いをしたのを覚えています。

きっと心の底から喜んでるでしょうね!

3月

r.kt #3でライブコントリビュートしました。ライブでコーディングしたの初めてだったので、かなり練習したのを覚えてます。

recruit-lifestyle.connpass.com

ライブストリーミングでshibuya.apkにも参加しました。子供がいるのでこう言うのがどんどん流行ってほしい!と思ってます。準備が大変ですけど・・・。

4月

4月になったので、キャリアについて真剣に考え始めたタイミングでした。早めのジョイン狙いだよなーってなってる時です。

年収ツイートするといいねいっぱい貰えると学んだツイート

フラグが立った日

そして、その日のうちに、スタートアップの早めのジョインなんて今の自分じゃ無理だと判断したツイート。

やっぱり4月は転職周りのツイート多いな。。。

5月

Google IOに行かせてもらいました。初めての参加でした。

Codelabで問題一切やらずに、ChromeBookの検証してた。

これ忘れられなくて、どうしてもやりたくて、現職でやらせてもらいました。もうすぐ詳細を弊社の誰かが書くはず!

6月

サーバサイドKotlinやりたくて仕方なくなってる頃です。

なるほど

GitHub Satellite Tokyoに参加して、色々話聞きました。で、この機能を知らなかったことに正直衝撃を受けてて、毎日GitHub触ってないことに対して危機感を覚えました。このままこのキャリアでもいいかな?と考えてもいたのですが、この危機感は今でも鮮明に覚えていて、この日を境にキャリアを変えると決断しました。で、6月終わりには現職に転職を決めました。

7月

コネヒトさんのイベントに参加して、Kotlin Festのネタ集めを始めました。本当にこのイベントのおかげで色々助かったので、コネヒトさんには感謝しかない!

にも関わらず恩を仇で返す

当然ごめん。

8月

そして最終出社日

最後の最後まで、店舗の方に顔だして仕事してたりしてました。自分がこの会社で長く働けなかったことは本当に悔しいし、またどこかの大企業に再挑戦できる機会がどこかであればいいなと思ってます。

そして、テンションおかしくなって、なぜかその日のうちにコミケに初参加を決めました。

参加者がみんな熱いな!ってちょっと感動してました。

Kotlin Festのスケジュールが公開されて、ふてくされました。

入社日前日に現職のBBQイベントがあったので、家族同伴で参加しました。

入社して一番やりたかったことを2日目にしてやらせてもらって、本当に嬉しかった。

その一週間後のKotlin Festで登壇。自分と同じ時間のLTの人たちがみんな時間通り進めたおかげで、最後の辺り全員が自分の登壇を観ると言う美味しい状況でした。

あと、ぼっち飯回避でTwitterで募集したら始めてお会いする人たちとご飯いけました。本当に楽しかった。

shiraji.hatenablog.com

この8月は今年の中で一番濃かったなー。

9月

現役引退予定でしたが、いまだにバリバリコーディングしてます。35歳定年なんてのはないですね。

10月

Pixelを合法的に日本で触れるなんて思ってもいなかったですね。これが4月までに発生してたら転職とかなかったかも?なので、何が起こるかわかりませんね。

GraphQL始めました。この辺りからツイートがGraphQL一色になってる。かなりお気に入りになった模様。

これ公開したら良くね?って気づいてすぐにOSSとしてコーディングスタイル公開しました。なかなか良い反応もらえて嬉しかった。

その勢いのままbrave-ktも公開しました。

shiraji.hatenablog.com

github.com

11月

2年連続でDroidKaigi登壇が決まりました。今回は日本語でやります。ライブコーディングの予定です。スライドあるとしても自己紹介だけになるので聴きに来てね!

キャリア変えたことを報告しました。Android開発者に罵られるかも?とビクビクしてました。でも当然そんなこと無く、本当に暖かい良い開発者コミュニティだなーと思います。DroidKaigiで少しでも恩を返せたらと!

shiraji.hatenablog.com

12月

今年はアドベントカレンダーに参加しない方針だったので、こっちの参加表明。

でもKotlin枠が空いてて、書くのを抑えられなかった人です。これ結構プロダクションに乗っかってるコードに近いので、興味ある人はぜひ触ってみてください!10月から月1ペースでOSS公開してます。そんな頻度とかは特に意識はしてないけど、出せるものは出して、サーバサイドKotlinやる人増えてくれたら嬉しいなー。

shiraji.hatenablog.com

github.com

2018年の目標達成度

2018年の目標

一回登壇を経験したので、流れも掴めたし、登壇の方の負荷も減ると思うので、コードのアウトプットと両立させたい。

負荷減ってない気が・・・。OSSのコードアウトプット量は前半かなり減っていたので、焦りが出た。それを機に転職して、2018年後半結構アウトプット出来たと思う。 ただ、まだまだやれると思うので、来年はもっと増やしていきたい。

2019年の目標

OSSもそうだけど、仕事でのアウトプットも増やしていきたい。まだまだ手探り感がある。 プライベートはようやく来年から落ち着きそうなので、家族みんな元気に過ごす!が目標。

最後に

8月に転職してまだ4ヶ月しか経ってないのかーと驚きです。今年は仕事もプライベートも色々あって、ドタバタだった感があります。

今年も初めましてな方といっぱい会うことが出来ました。来年もきっと楽しいことが起こるだろうなとワクワクしています。

今年一年、ありがとうございました。来年もよろしくお願いいたします。

Kotlin大好きな人向けなCollectionのstdlibメソッドを掘り出してみた

これはQiita Kotlin Advent Calendar 10日目の記事です。

qiita.com

これマニアックなんじゃね?Kotlin大好きな人向けなんじゃね?ってstdlibにあるIterable/Collection/List/Set/Mapのメソッドを独断と偏見で挙げてみようと思います!

Collection - Kotlin Programming Language

想定読者

  • KotlinのCollectionのstdlibメソッドもっと知りたい人
  • 一旦はさすがです!って褒めてくれる人

環境

Kotlin 1.3.11で使えるメソッドにしています。全メソッドPlaygroundで動作確認済みです。

distinct

説明: 重複削除したListを作る

distinct - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/HJnYskugV

fun main() {
    val list = listOf(1,1,1,3,5)
    println("List: $list") // List: [1, 1, 1, 3, 5]
    println("Result: ${list.distinct()}") // Result: [1, 3, 5]
}

感想: かー毎回Setに詰め込んでたね。それでListが欲しい場合は、toListしてたね。さらに順番が必要なら色々頑張ってたね。便利😊

intersect

説明: 両方のCollectionに入っている要素をSetにして返す

intersect - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/SkQkak_eE

fun main() {
    val list1 = listOf(1,1,1,3,5)
    val list2 = listOf(3,4,1)
    println(list1.intersect(list2)) // [1, 3]
}

感想: 知らなかったら、filterとかcontainsメソッドなどで泣きながら書いてたと思う。

union

説明: Collectionをがっちゃんこする。戻り値はSet

union - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/rykBje_lV

fun main() {
    val list1 = listOf(1,1,1,3,5)
    val list2 = listOf(3,4,1)
    println(list1.union(list2)) // [1, 3, 5, 4]
}

感想: intersectと同じ感想

onEach

説明: 渡した引数のactionを全ての要素に実行し、レシーバーを返す

onEach - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/HyrGyxugE

fun main() {
    val list = listOf(1,1,1,3,5)
    list.onEach {
        println("Log: $it")
    }.filter {
        it > 3
    }.forEach {
        println("Result: $it")
    }
}

結果

Log: 1
Log: 1
Log: 1
Log: 3
Log: 5
Result: 5

感想: forEachして、そのまま何かしたい!って時にまたレシーバーを書いてたけど、これ使えば全部繋げられるじゃん。便利じゃん。onEachWithIndexとか欲しくなりそう。

partition

説明: Collectionの要素が引数の条件にマッチした要素をPairのfirstのListに。マッチしない要素をsecondのListに分割する

partition - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/HJgvexugN

fun main() {
    val list = listOf(1,1,1,3,5)
    println(list.partition { it >= 3 }) // ([3, 5], [1, 1, 1])
}

感想: 分割が必要な時、頑張らなくてもいいね!

requireNoNulls

説明: 要素にnullがないことを担保する。もし、nullがあればIllegalArgumentException

requireNoNulls - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/SJ3VMlul4

fun main() {
    val list: List<Int?> = listOf(1,2,4)
    val listNoNulls: List<Int> = list.requireNoNulls()
}

感想: requireNotNullのCollection版って感じ。nullがないことが前提条件のメソッドとかで利用できそう。(特に気にもせずに無心でfilterNotNullするかもだが。。。)

unzip

説明: PairのArrayに対し、firstの値だけのListとsecondの値だけのListをPairとして返す。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/unzip.html

サンプルコード:

https://pl.kotl.in/ryYFNedx4

fun main() {
    val array = arrayOf(1 to "foo", 2 to "bar", 3 to 5)
    println(array.unzip()) ([1, 2, 3], [foo, bar, 5])
}

感想: ちょっと限定的すぎる?🤔いや、こういうのいいですよねきっと!

windowed

説明: Collectionをsizeの要素数のListを作る。次のListはstep分ずれたものからスタートする。

ごめんなさい。どう英訳すれば一番わかりやすいのかすらわからない。以下が原文。

Returns a list of snapshots of the window of the given size sliding along this collection with the given step, where each snapshot is a list.

windowed - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/r13a_gdxN

fun main() {
    val list = listOf(0,1,2,3,4,5,6,7,8,9)
    println(list.windowed(size = 5, step = 3)) // [[0, 1, 2, 3, 4], [3, 4, 5, 6, 7]]
    println(list.windowed(size = 5, step = 3, partialWindows = true)) // [[0, 1, 2, 3, 4], [3, 4, 5, 6, 7], [6, 7, 8, 9], [9]]
}

partialWindowsがtrueだった場合、sizeに足りてないものも含む。

感想: ちょっと置いていかれたメソッド。これが便利なんだ!というくらいKotlinを使いこなしたい・・・

zipWithNext

説明: Listの隣り合った要素をListのPairとして返す

zipWithNext - Kotlin Programming Language

サンプルコード:

https://pl.kotl.in/r1cjdxOlE

fun main() {
    val list = listOf(0,1,2,3,4,5,6,7,8,9)
    println(list.zipWithNext()) // [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]
    println(list.zipWithNext { a, b -> a + b }) // [1, 3, 5, 7, 9, 11, 13, 15, 17]
}

感想: transformを渡せば、数列とかで便利かも?あとは次の値を見て何かするような処理とかでもいいかも。

サーバサイドKotlin+GraphQLのアプリケーションをOSS化しました

これはQiita Kotlin Advent Calendar 2018 1日目の記事です。

qiita.com

ツイートしたら良い反応もらえたので、サーバサイドKotlinのアプリを以下で公開する事に決めました。

github.com

cloneして、docker-compose upしたら、GraphiQLが http://localhost:8090/graphiql 立ち上がって、サーバの動作確認が出来る。簡単!!!

f:id:shiraji:20181214165629p:plain
GraphiQL画面

Ubie内で絶賛開発中のシステムに少し手を加えていますが、基本的に実際に開発している環境と同じになっています。

公開目的

公開に至った理由はいくつかあります。

サーバサイドKotlinやりたいって人のハードルを下げたかった

やりたい!という声はいろんなところで聞くけど、「環境ないし・・・。」「経験無いし・・・。」という方も多いと思ってます。実際Ubie入社前の自分がそうでした。

このプロジェクトは、clone後すぐにローカルで動かす事が可能です。

そのため、このお手軽さを見てもらい、もっと多くの方にサーバサイドKotlinやってもらいたいなーと思いました。

Kotlin+SpringBoot+GraphQLの開発者にコードレビューしてもらいたかった。または仲良くなりたかった

今回、色々な事情があり、KotlinでGraphQLの採用をしています。自分にKotlin+GraphQLの実績がないため、コードを公開することにより、いろんな人に見てもらい、より良いものになったら良いなと思いました。さらに同じような環境の方ともっと仲良くなりたいです!

特に後述しますが、多対多のGraphQLResolverの処理が本当にこんな感じのコードで良いのかが不明です。Spring+GraphQLの情報が少なすぎる。。。もっと効率良く出来そうなんですが・・・

同じ構成のものをOSS化することにより、Ubieの入社即パフォーマンス発揮!をしてもらいたかった

今のところ、Ubieのサーバサイドに関わる人には入社前に1日インターンをしてもらい、チームに溶け込めるか?を見てもらう時間を取っています。しかし、時間が1日しかなく、環境構築に時間を取られてしまうのはもったいないです。そのため、同じ環境をOSS化することにより、先に環境構築出来る状況にしたいと考えました。

さらに将来的には1日インターン宗教上無理!って方にこのOSSプロダクト開発に携わってもらい、雰囲気をそこで味わってもらうのもいいかなと考えています。

技術スタック

このプロジェクトでは以下の技術スタックを利用しています。

今後テスト書くので、以下が追加予定

  • JUnit5
  • Mockk
  • WebTestClient

パッケージ構成

app.ubie.kotlingraphqlsample
├── domain
├── infrastructure
│   └── jdbc
├── presentation
│   ├── queryresolver
│   └── resolver
└── service

(Query)Resolver → Service → JDBCという呼び出し階層になってます。

DB

f:id:shiraji:20181214205606p:plain
E-R図

薬と傷病の関係性のサンプルテーブルになっています。医療業界で利用されているデータに合わせ、IDがなかったり、外部キーがUniqueじゃなかったり、全て多対多の仕様になっています。

DBアクセスはspringがデフォルトで提供しているJDBCを使い、SQLをコードに書いてDBアクセスしています。これは賛否両論あると思いますが、以下の理由から採用しています。

  • SQLのチューニングがしやすい
  • ラーニングコストが低い
  • 一目でどこでどのSQLを発行しているのかがわかる

Flywayを利用して自動マイグレーションが走る状態にしてあります。

GraphQL

GraphQLのスキーマ定義ファイルには薬情報と病気情報が定義されています。

type Query {
    # 薬を取得します
    drugs(yjCode: String!) : [Drug!]
    # 病気を取得します
    diseases(icd: String!) : [Disease!]
}

# 薬情報
type Drug {
    # 薬品名
    name: String!
    # YJ Code。だいたい薬を表すために使われるCode。一意ではないので注意
    yjCode: String!
    # 併用禁忌薬
    kinkiDrugs: [Drug!]
    # 処方してはいけない特定の病気
    kinkiDiseases: [Disease!]
} 

# 病気
type Disease {
    # 傷病に対してつくコード。一意ではないので注意
    icd: String!
    # 病名
    name: String!
    # 処方されてはいけない薬
    kinkiDrugs: [Drug!]
}

Queryブロックには公開APIが定義されています。graphql-javaではこの定義をGraphQLQueryResolverを実装したクラスで記述する必要があります。このプロジェクトではqueryresolverパッケージ内で定義されています。

@Component
class DiseaseQueryResolver(private val service: DiseaseService) : GraphQLQueryResolver {
    fun diseases(icd: String): List<Disease> = service.getDiseases(icd)
}
@Component
class DrugQueryResolver(val drugService: DrugService) : GraphQLQueryResolver {
    fun drugs(yjCode: String): List<Drug> = drugService.getDrugs(yjCode)
}

Drug/Diseaseブロック内にあるkinkiDrugsなどの外部キーを使った結合はgraphql-javaではGraphQLResolver<T>を実装する必要があります。resolverパッケージ内で定義されています。typeがDrugkinkiDrugsの取得時にはfun getKinkiDrugs(drug: Drug): List<Drug>が呼び出される。

@Component
class DiseaseResolver(private val service: DiseaseKinkiDrugService, private val drugService: DrugService) : GraphQLResolver<Disease> {

    fun getKinkiDrugs(disease: Disease): List<Drug> {
        val kinkiDrugs = service.findKinkiDrugsByIcd(disease.icd)
        return drugService.getDrugs(kinkiDrugs.map { it.yjCode })
    }
}
@Component
class DrugResolver(
    private val kinkiDrugService: KinkiDrugService,
    private val diseseKinkiDrugService: DiseaseKinkiDrugService,
    private val drugService: DrugService,
    private val diseaseService: DiseaseService
) : GraphQLResolver<Drug> {

    fun getKinkiDrugs(drug: Drug): List<Drug> {
        val kinkiDrugs = kinkiDrugService.findKinkiDrugsByYjCode(drug.yjCode)
        return drugService.getDrugs(kinkiDrugs.map { it.kinkiYjCode })
    }

    fun getKinkiDiseases(drug: Drug): List<Disease> {
        val kinkiDrugs = diseseKinkiDrugService.findKinkiDrugsByYjCode(drug.yjCode)
        return diseaseService.getDiseases(kinkiDrugs.map { it.icd })
    }
}

多対多な関係が多く、SQLの発行回数が若干多いなーという印象があります。この辺りどうしたらいいのか誰かと語りたい!!!

終わりに

このコード読んで、UbieでサーバサイドKotlinやってみたいと思った方は @shiraj_i に直接DMか以下のWantedlyさんのサイトから話を聞きにきて下さい!

www.wantedly.com

もっと気軽にUbieに遊びに来たい!という方は以下のBosyuさんからメッセージを送って下さい!

bosyu.me