Retty新卒エンジニアの入社半年間の振り返り〜Part.2〜

こんにちは、激辛な食べ物が大好きな2018年新卒エンジニアの諏訪です!Rettyではサーバーサイド兼フロントエンドエンジニアをしています。インターンを含めるとほぼ2年間Rettyにいますが、入社半年の節目として振り返ります!

入社前

大学に通いつつ独学でプログラミングを初め、自作PCでサーバーを作るなどプログラミングからネットワークやインフラ周りまで幅広く勉強していました。ずっと独学で勉強していたので自分の技術力に不安を感じ、Web系のインターンに7社参加し、実際の現場でプロダクトに触らせてもらうことで、実装からリリースまでのフローやプランナーとのコミュニケーションなどを学びました。 Rettyには大学3年の頃から1年半ほどインターンに参加し、インフラからフロントまでフルスタックに働くことができそうだと思いRettyにJoinしました。

f:id:rettydev:20181115173323j:plain △大学3年の頃から1年半ほどインターンに参加(2017年11月撮影、左が諏訪、右は先輩エンジニアの竹野)

なぜフロントもサーバーサイドもやっているのか

RettyにJoinするまではフロントはほとんど触ったことはありませんでした。サーバーサイドを極めていくには、フロントからどういうリクエストが来てどれだけのトラフィックが必要なのか、どういうネットワーク構成でどの部分でデータがキャッシュされているのかなど、知らないといけないことはたくさんあります。最初から一つの分野に絞ってしまうと視野が狭くなってしまうので、新卒の段階ではまずフルスタックに働けるようになろうと思いました。最初はフロントからやりたいなと考えていたタイミングで、ちょうどフロントの案件が発生したこともあり、フロントエンドの世界へと足を踏み入れました。

最初はVue.jsやVuexの概念を理解するのに苦労しましたが、先輩にペアプロペアプログラミング)やコードレビューをしていただき、実務で触れるレベルまでスキルを磨くことができました。

今ではフロントの開発が楽しくなってしまい、7 : 3ぐらいの比率でフロントメインで業務に携わっています(笑)

関わったプロジェクト

入社後は主に以下の二つのチームを兼務しています。

WEBチーム

WEBチームではRettyの検索ページ( ex. https://retty.me/area/PRE13/ )や、店舗情報詳細ページで施策や機能追加の業務を行なっています。

配属直後はフロント初心者だったため、施策や小さめの機能追加の実装をしていましたが、5月頭ぐらいには店舗情報詳細ページに予約カレンダー機能を追加するといった大きめの実装を任せてもらいました。10月には、お店検索需要が高まる忘年会シーズンに向けた施策の実装も行いました。VueでA/Bテスト基盤を作るなど技術的にも色々できた半年でした。

PCに実装した予約カレンダーは、日付選択時にアニメーションを与えることで、切り替わっていることに気づいてもらえる仕組みを入れました。また、カレンダーを導入するにあたり、これまではDBにデータを取得しに行くことでカレンダーを生成していたのですが、負荷の問題からDBを直接見にいくことはせず、間にElasticsearchを挟むなど様々な工夫をしています。

スマホカレンダースマホカレンダー
WEB版Rettyの予約カレンダー

javascriptCSSをプロダクトレベルでほとんど触ったことがない状態からスタートしましたが、配属直後から実務を任せてもらえたことで、webpack等のビルド環境やVue.js等のフレームワークを実務レベルで使い、他エンジニアのコードレビューができる状態まで短期間で成長することができました。 また、プランナーとのコミュニケーションや他チームとの連携、仕様をもらってからの工数見積もり等、個人でプログラミングをしている時にはあまり身につかないスキルや経験を学ぶことができました。

編集チーム

編集チームでは主にRettyグルメニュース( https://retty.news/ )の入稿画面の改修や開発生産性向上の業務に携わっています。入稿画面にSEO向けの機能の追加やtextlintを利用した記事の自動校正システムの導入をしました。

開発の生産性を向上させるものとして、これまで手動で行っていたDBマイグレーションの自動化やステージング用のDBの自動更新、デプロイ自動化など、オペレーション・ミスが発生しそうな部分の自動化を行いました。 この辺りではRDSやCircleCI、Elastic Beanstalkの経験を積むことができました。

これからについて

個人での開発はたくさんしてきましたが、チームで開発をするのは初めてだったので自分のスキルの足りなさを感じる一方、いろいろな方にサポートいただいたおかげで、メンターからは「セマンティックなHTMLからBEMとscss、モダンjsの書き方、Vue.jsにおけるコンポーネント設計、バンドラー環境開発など、フロントエンドの最初のハードルである膨大な量の技術をあっという間にものにしていく姿には1年目とは思えない安定感があった。」との評価をいただくほど、成長を実感できた半年でした。

現在はフロントメインで働いていますが、大規模なトラフィックに耐えられるサーバーサイドの設計実装やパフォーマンスのチューニングをするのが好きなので、いずれはサーバーサイドをメインにしたいと思っています。ですが、フロントのスキルもまだまだなので、当面はフロントメインで去年の自分の10倍は成長する気持ちで頑張りたいと思います!

Retty新卒エンジニアの入社半年間の振り返り〜Part.1〜

はじめまして。2018年度の新卒でエンジニアとして入社しました山田です。 4月の入社から半年という節目を迎えるに当たり、これまでRettyでチャレンジしてきたことについてまとめていきたいと思います。

自己紹介

高専出身です。 在学中は電子制御工学科に属しており、ロボットを作るための様々な技術(機械工学、プログラミング、電気工学etc…)を包括的に学んでいました。 ロボコンに出場して、地区大会で優勝したこともありました!

その傍ら、プログラミングを通した物作りにハマり、個人でAndroidアプリを作って販売してみたり、ベンチャー企業ウェブアプリケーション開発に参加したりとソフトウェア開発に携わってきました。

そのような経験を積む中で、自分が興味関心を持っていること(プログラミング以外に食べることも好きです!)を仕事にしたいと考え、卒業後、Rettyへジョインしました。

主な業務について

4月下旬からアプリチームに参加し、APIサーバー開発からiOS/Androidアプリ開発までを手がけています。 Rettyのアプリチームでは、フロントエンドであるiOS/Androidアプリの開発は勿論、それらがバックエンドで使用しているAPIサーバーの開発も担っています。

スクラム開発を導入しており、今までチームでの開発経験に乏しい僕にとっては、とても良い刺激になりました! 特に、タスクにポイントをつけておくことで、チームとしてどのくらいのタスクをこなすことができるのか数値化し、今後の改善に活かしていくやり方はとても合理的だなと感じました。 参加してすぐの時は見積もりの勘所がわからず、大変だったな〜という思い出があります。
広範な技術を扱うチームなので、とてもたくさんのことにチャレンジしています!

f:id:rettydev:20181025111648p:plain
Rettyアプリチームのメンバー(手前右が山田)

APIサーバー開発

アプリチームにジョインして最初に担当したタスクがAPIの機能追加でした。 Rettyで使用しているAPIサーバーはKotlinで開発されています。
Kotlinは個人的なAndroidアプリ開発では触っていたのですが、Android以外でKotlinを使用することがなかったため、とても新鮮でした!
また、今までSQLにそこまで多く触れたことが無く、SQLを活用してDBからデータを取得してくるということに対してとても不便そうなイメージを持っていました。しかし、そういった部分にも挑戦することができ、例えばViewのような、自らの知らなかったより便利な機能を知ることができ、そんなイメージを払拭することができたなど、多くの学びを得ることができました。

iOSアプリ開発

次にiOSアプリの開発にも参加しました。 Rettyに入社するまでiOSアプリ開発の経験は一切なく、Objective-Cは勿論Swiftも、iOS固有の知識も何も知らない状態だったので、思い通りにUIを作ることがなかなかできず、最初はとても苦労しました。
しかし、アプリチームの先輩エンジニアから手取り足取り教えていただき、参加してから一ヶ月が経過した時にはきちんと開発に参加できるようになりました。 実際に、開発に関わったものとしては、非ログイン機能や新しい投稿画面の実装、各種不具合修正などを行いました。

Androidアプリ開発

7月ごろからAndroidアプリのリニューアルに向けた開発も行なっており、現在はこの業務がメインです。

僕が開発に参加するまでのAndroidアプリは、Activity内にUI周りの処理やUIと関係ないデータの処理などが入り混じっている、いわゆる「FatActivity」な設計となっていました。これによってコードの見通しがとても悪く、リファクタリングも簡単に行えないような状態でした。
これをなんとかしたいと思い、リニューアルをするという良いタイミングだったので、「今後のためにもMVPアーキテクチャを適用し、テストの導入を進めていきたい」とチームに提案したところ、快く受け入れてもらえ、設計の改善も自ら主導することになりました。

最近では、投稿ユーザーさんのプロフィール詳細画面のリニューアルを行いました。以前よりもサクサク動くようになり、メンバーからも「使いやすくなった」というフィードバックをもらえました!

f:id:rettydev:20181015142121p:plain
Android版Rettyアプリのユーザー詳細画面

おわりに

Rettyにジョインしてからおよそ半年、サーバーサイドからAndroid/iOSアプリのフロントエンドまで、知っていたことも全く知らなかったことも、区別なく様々なことに挑戦してきました。これにより、領域を気にせず、知らないことにも臆さず、やりたいと思ったことにどんどん突っ込んでいける力が身についたと感じます。

今後も、この自由に挑戦できる環境を活かして、ゆくゆくはプロダクト開発を担えるフルスタックエンジニアになることを目指して、技術の区別なくどんどん知識を吸収し経験を積んでいきたいと思います!

新卒メンバー全員でシャッフルランチをつくり、PDCAサイクルを回してみました(後編)

2018年4月に入社した新卒エンジニアの堤です。前回に引き続き、入社後に新卒メンバー全員で初めて企画・開発した「シャッフルランチ」の取り組みについてご紹介します。

f:id:rettydev:20180925185708j:plain ▲2018年の新卒入社は総合職3名、エンジニア4名の計7名。職種を問わず新卒メンバー全員が参加する研修が2週間ほど行われました

1. シャッフルランチトライアル後のシステム改善

まずは、トライアルでのシャッフルランチ導入後の改善について。

主に、

  • 構成の刷新
  • シャッフルロジックの改良

についてお話します。

(1) 構成の刷新

前半でもお話しましたが、シャッフルランチの実施初期はGASを利用していました。ただ、運用していく上で大きく2点課題がみつかり、構成を刷新することになりました。 具体的には下記の2点です。

  1. GASがチーム開発に向かない
  2. Slackボタンが使えない

1について、GASが標準ではバージョン管理に対応していません。基本的にはWeb上のIDEからGASのソースコードを直接編集する形になります。この場合、

  • 複数人で開発するときに編集箇所が競合し、編集が適用されないなどの面倒が生じる可能性がある
  • バージョン管理がされないので、以前の状態に戻すことが難しい

という状況になります。 トライアル開発時は完全に分担しており、開発量も多くなかったので問題になりませんでしたが、運用にあたって加えたい機能が次々と出てきたため、このまま開発を続けることが難しくなりました。 ちなみに、GASとローカルを同期する機能は以下にまとめられているので、個人開発であればバージョン管理の問題は解決されそうです。

https://techblog.recruitjobs.net/development/maneged_google-apps-script_by_github

2つ目の課題は、Slackボタンが使えない点でした。 背景として、アンケートや出欠確認でSlackのボタンを使いたいよね、という話が上がっていました。ただ、Slackのボタンには3秒以内にレスポンスを返さないとTimeoutする仕様があり、GASだと3回に1回程度はTimeoutしてしまいました。 これに関してはGASを使っている以上はどうしようもないので、トライアル時にはボタンの利用を諦めました。 その他にも、GASのJavaScriptが古い(ECMA Script 5)だったり、動作時間に制限(1度に6分まで)があるなど、今後の運用を考えると移行したほうが良さそうだという話になりました。

以上の理由から、最初のトライアルを終えて2度目のトライアルまでに、主に新卒エンジニアの神(こう)と諏訪が以下の状態にお引越ししてくれました。

  • バックエンド
    • Botkit (Node.js)
  • 開発環境
    • GitLab CI
    • Rancher

BotkitはNode.jsによるbot作成フレームワークの一つで、Slack以外にも様々なChatBotを作成することができます(https://botkit.ai/)。 また、GitLabを立て、CIツールとしてGitLab CIを用いることで、Docker Image作成の自動化を図っています。GitLab CIについてはこちら(https://qiita.com/bremen/items/f47f383b9931a840a25c) に詳しく書かれています。 さらに、Rancherを利用することで、GitLab CIによって作成されたDocker ImageのデプロイをGUIから簡単に行えるようにしています(https://www.slideshare.net/recruitcojp/rancherrancher)。 これによって、

  • チーム開発のスピード向上
  • (レスポンス速度改善により)Slackのボタンが利用可能に
  • botフレームワークの利用により、bot機能の開発が楽に

が実現されました。

(2) シャッフルロジックの改良

トライアルを実施してみると、「よく話す人と同じグループになったためシャッフル感がない」「同じ部署の人と一緒になった」などという意見が散見されました。 今までは完全にランダムシャッフルを行ってグループを作っていましたが、「似ている社員が違うグループになるようにシャッフルしたほうがいいのではないか?」という話が上がりました。 そこで、社員の下記の属性を利用し、似た社員が同じグループになりにくいようなシャッフルを行うこととしました。

  • 社員属性
    • チーム
    • 職種
    • 性別
    • 勤続年数

要件はこちらです。

  1. 属性の似た社員が同じグループになりにくい
  2. メンバーは毎回異なるようにしたい

「属性の似た社員が同じグループになりにくい」ということで、確率を利用したロジックを用いることにします。今回は「焼きなまし法(Simulated Annealing)」1という方法を用いることにしました。 焼きなまし法組み合わせ最適化問題に対するアルゴリズムの一種で、巡回セールスマン問題(TSP)などを解決するときに利用されます。 今回は

  • 条件
    • 同一グループに属する社員同士の類似度をコストとする
  • 制約
    • 全体のコストを低下

と設定し、ロジックを作成しました。 ロジックの大まかな流れがこちらです。

  • 全体のコストが小さくなるように、以下のようにSwapをR(=2000)回程度繰り返す
    1. 別々のグループからランダムに2人選ぶ
    2. 2人を入れ替えたときのコスト変化を計算する
    3. コスト減少ならSwap、そうでなくても確率PでSwap

焼きなまし法では、こちらの「確率P」が徐々に下がっていくことで、最初はコストが増加するSwapも許容しつつ、だんだんコストが減少するSwapのみ許容に変化していき、最適な解に近づけていきます。 今回は「メンバーは毎回異なるようにしたい」という要件があったため、確率Pの値は割と高い値を保ったままにしています。そうでないと最適解に近い値を求めてしまい、毎回メンバーが固定されてしまうからです。 今回はこちらのロジックを採用することにより、属性の似た社員が同じグループに固まることを防ぎつつ、メンバーが毎回異なるようなシャッフルを実現できました。

補足
今回のコストは以下のように設定しています。
グループgのコストは以下のように定義する
- groupCost(g) := (baseCost(g) / groupSize(g) ** 2) ** 2
ただし、
- baseCost(g) := グループgに属するメンバー同士の類似度合計
- メンバー(a, b)の類似度 := sameJob(a, b) + sameTeam(a, b) * 2 + sameSex(a, b) + distHist(a, b)
- sameXXX(a, b) := XXXが同じなら1、そうでないなら0
- distHist(a, b) := 勤続年数が近いほど大きくなる値
このとき、全体のコストは各グループコストの合計である。

その他、出欠の自動化であったり、取得に時間のかかるSpreadSheetのCache作成など、課題が上がるごとに機能を追加していきました。 現在もシャッフルランチの運用をより良く、より楽にするために改善を重ねています。

2. 本格運用を開始

2018年4月に新卒でRettyに入社し、Webプランナーを担当している山田陸です。

新卒メンバーみんなで試行錯誤を重ね、トライアル期間に見つけた課題も解消し、7月より全社でシャッフルランチの本格運用を開始しました。 新たな課題が出る一方で、社内ではポジティブな変化もありました。

(1) 課題:参加率の低下

トライアル期間中は、出席者に直接声をかけることも行なっていたため多くの社員が参加してくれましたが、自動化するために出席確認をbotで送る仕組みに変えたところ、大幅に参加率が低下してしまいました。

原因は、シャッフルランチの目的やメリットが社内に浸透しきれていないことや、既に予定が入っていて参加できない人を含めて選定している点などが考えられます。 完全自動化からは少し離れてしまいますが、社内でのアナウンスなど、シャッフルランチが定着するための取り組みも行なっていこうと考えています。

(2) ポジティブな変化:社員同士の声のかけ合いやすさ向上

一度ランチをしたことで、その後も社内で声をかけやすくなったという声がありました。ランチを通じて、仕事だけでなくお互いのプライベートなども知れば、互いの距離はグッと縮まります。シャッフルランチをきっかけに、仕事でのコミュニケーションにもつながることを垣間見ることができたことは、非常に嬉しいです。

3. 今後のシャッフルランチについて

Rettyはこれからも事業の拡大に伴い、社員の数も増えていくことが予想されます。社員同士の交流は、会社全体が「チームRetty」として成果を生み出していく上で欠かせません。 社員同士の交流を活性化するためにも、シャッフルランチの改良を重ね、参加率を向上させていきたいと思います。

私たち新卒メンバーが企画した「シャッフルランチ」によって社内のコミュニケーションが活性化され、サービスやビジネスの成長に貢献できたら嬉しいです。

新卒メンバー全員でシャッフルランチをつくり、PDCAサイクルを回してみました(前編)

こんにちは、2018年4月に新卒でRettyに入社し、現在はプロダクト部門でWebプランナーを担当している山田陸です。

2018年の新卒入社は、総合職が私を含めて盛山、武藤、私の3名、エンジニア職が神、諏訪、堤、山田、の4名、計7名います。今回は、新卒で入社した私たちが入社後に初めて企画・開発した「シャッフルランチ」について、メンバーを代表して私とエンジニアの堤からご紹介します。

f:id:rettydev:20180925184148j:plain ▲入社式の記念撮影(2018年4月、メッセージフラッグを囲む7名が新卒メンバー)

1.なぜシャッフルランチなのか?

(1) 研修中に得た気づき

今年の新卒入社研修は、職種を問わず新卒メンバー全員が参加する研修が2週間ほど行われました。同期間、私たちは毎日、話してみたい先輩社員に声をかけ、ランチに出かけていました。

それぞれのチームの仕事内容や雰囲気などについて、ざっくばらんに話を聞くことがランチの主な目的でしたが、先輩たちからは「以前よりも社員同士の交流が減っている気がする」といった声がありました。

社員数は100名を超え、部署の数も増え、顔を合わせる機会の少ないメンバーが増えていると感じていたようです。

成長と共に組織が拡大するベンチャー企業ではよくある話だと思い、当初はこの課題に対して私たち自身が何かするという発想はありませんでした。しかし、研修では「チームで動いてこそ、大きな成果を生み出すことができる」という話を繰り返し聞き、Rettyではいかにチームワークを重視しているかについて知ったことで、改めてこの課題に向き合うことを考えました。

(2) 課題解決方法の検討とシャッフルランチの決定

  入社して1週間が経過した4/9(月)の研修後に新卒メンバー全員で集まり、他社の事例なども参考にアイデアを出し合いました。そうして検討が始まったのが、他社でも導入事例が増えている「シャッフルランチ」です。グルメサービスを運営するRettyでは、「User Happy」なサービスを提供するために、まずは社員自身が「食」を楽しむことを大切にしています。部門や職種の垣根を超えた交流を活性化する方法としても、「食」に関わることの方が、Rettyらしいと思いました。また、「シャッフルランチ」であれば、2週間の研修期間の中でも企画・開発し、研修後もPDCAサイクルを回すことができそうだと判断しました。

早速、研修期間のランチで感じた課題や、それを解消したい旨を研修責任者に伝え、新卒メンバーのプロジェクトとして取り組むことが決定し、4/13(金)には全社員が集まる総会でも発表しました。

開発に向けて、まずはトライアルとしての運用フローを検討しました。私たちが考えたフローは、下記です。

  • 社内のコミュニケーションツールSlackに、シャッフルしたメンバーのチャンネルを自動で作成
  • 新卒メンバーが音頭を取りながらお店選び、予約などを実施
  • シャッフルメンバーでランチ
  • ランチ後にメンバーにアンケートを実施

まずは上記のフローでトライアルを実施し、シャッフルランチが上手くいきそうかどうかを検証することにしました。

2.シャッフルランチシステムの開発

新卒エンジニアの堤です。

ここからは、神、諏訪、山田、堤の4名による新卒エンジニアチームで行った、シャッフルランチ導入までの取り組みを紹介します。

(1) 技術選定と役割分担

シャッフルランチを新卒プロジェクトとして決めたのが4/9(月)ですが、それを社内で発表しデモを動かすのを4/13(金)の総会の日に設定しました。 そのため作業期間は4日、しかも日中は研修のため、空き時間を使っての短い時間で作り上げる必要がありました。 そこで新卒エンジニア4人で相談し、サービスの仕様や構成、役割分担を決定し、各自進めていきました。

  • 仕様
    • 社員のランチ出欠をSpreadSheet上に保存しておく
    • 決まった日時に、ランチ参加社員をシャッフルしてグループを複数作成
    • Slackにてグループチャットを作成し、ランチを促す
    • Googleカレンダーにランチの予定を登録
  • 構成
  • 役割分担
    • DB連携機能
    • 環境構築・スケジューリング
    • Slack連携機能・Googleカレンダー連携機能
    • ランダムシャッフル

全社発表の日までにデモを実行できるまで作成し、5月の半ばに最初のバージョンを完成させてトライしました。

(2) 実際の動作

実際に作動させた場合、Slack上でグループを作成した後、このようにメッセージを投げてシャッフルランチを促します。 f:id:rettydev:20180925103139p:plain

(3) 構成について

今回は機能がシンプルなため、GAS + SpreadSheet(DB) + Slack(UI) とすることで、サーバを用意せず準備・運用の手間を省く構成としました。 GASとは、

Google Apps Script は、Googleが提供するサーバーサイド・スクリプト環境です1

GASの詳細は省きますが、簡単なWebアプリケーションや定期実行スクリプトJavaScriptで作成し、動作させることができます。 また、GASを利用するときにデータベースが必要な場合は、SpreadSheetが一緒に用いられます。GASからのアクセスが簡単で、かつSQLの知識がなくともデータベースを編集できるという利点があります。今回参加者リストを管理したのですが、新卒総合職もリストを編集・閲覧する必要があり、この利点が活きました。 また、UIとしてSlackを利用しています。理由として、

  • 社内で日常的にコミュニケーションツールとして利用されている
  • APIが充実している

ことが挙げられます。 Slack連携やこれら全体の連結は、新卒エンジニアの諏訪が行ってくれました。

(4) SpreadSheet連携

GASでSpreadSheetを利用するに当たって、表を配列として扱う必要があります。2 読み込み・書き込み時に配列への操作が必要となるため、例えば次のようなSheetがあった場合に、

id team user
0 営業 Shogo
1 App Yutaka
2 検索 Shiho
3 経理 Taro

3行目のuser列の値を取り出す操作は以下のようになります。

// シートを取得
var sheet = SpreadsheetApp.getActive().getSheetByName('sheet1');
// 3行目
var rowIndex = 3;
var colStartIndex = 2;
var rowNum = 1;
var colNum = 1;
var data1 = sheet.getRange(rowIndex, colStartIndex, rowNum, colNum).getValues();
// または
var sheetData = sheet.getValues();
var data2 = sheetData[rowIndex][colStartIndex];

ただ、これだと1行目のタイトル行の扱いが面倒だったり、数値での列指定のため列の追加に弱かったりします。そこで、新卒エンジニアの山田が以下のライブラリを作ってくれました。

https://5hyn3.github.io/posts/use-spreadsheets-from-gas-without-thinking-about-difficulties/

詳細はリンク先で書かれていますが、SpreadSheetの各行をオブジェクトとして扱えるようにし、上記の問題点を解決してくれました。また、updateやsave等のメソッド作成により、DBを扱うようにSpreadSheetを扱えるようになりました。

(5) サービスの運用と課題

最初のトライアル実施までに、念入りに新卒メンバーでテストしていたこともあり、無事社員をシャッフルしてランチに行くことができました。 ただ、いくつか足りないこと、やりたいことが数回のトライアル実施を通じて挙がってきました。次回の記事では、挙がった課題とその解決策についてお話します。

PyCon ThailandでGeoDjangoについて話してきました

こんにちは、Retty Global Team サーバーサイドエンジニアの omega (@equal_001) です。

PyCon Thailand参加に参加し、GeoDjangoについて話してきました。

PyCon Thailand

th.pycon.org

6/16, 6/17の二日間で開催されました。 今回が第一回目の開催で、参加者は200人程だったそうです。

現地の学生さんやTHAI PROGRAMMER というタイのプログラマコミュニティの方々も参加されていました。

話した内容

CFP: Powerful geographic web framework GeoDjango

docs.google.com

GeoDjangoというDjango地理空間情報を扱うための公式モジュールについて話しました。 Retty Global でもレストランの位置情報を扱う際に使用しています。

今回はBeginner向けの発表にしたのであまり深い話はしませんでしたが、当日の参加者でGeoDjangoを知る人が少なかったので発表後に良いフィードバックをいくつかいただけました。

感想

タイでもブロックチェーン, 機械学習系の発表が多めでした。 タイのプログラマ事情は日本にいるとなかなか耳にしないのですが、自国向けサービスがたくさんあり近年はスタートアップも増えてきているとのことです。

来年も開催するかもしれないとのことだったので、次回はDjangoを使った開発の知見などを発表したいと思います。

一緒にRetty 海外向けサービスの開発をしたい人を募集しています!

Retty Global Teamでは海外向けサービスの開発に興味のあるエンジニアを募集しています!

iOSエンジニア(Swift) | Retty株式会社

iOSDCでiOSアプリのリニューアルについて話をしてきました

RettyでiOSをメインに開発とかマネジメントをしているkosakoです。 先日iOSDC 短期間でやり遂げるための、 大規模リニューアルの進め方 というタイトルで話をしてきましたので、レポートとかネットでの反応に応えてみます。

f:id:rettydev:20170926145915j:plain

提出したCfPとスライド

Rettyでは2年半ぶりに大規模なリニューアルを行っています。 まだリリースはされていませんが、言語をObjective-cからswift4.0へ移行したり、アーキテクチャの刷新も短期間で行おうとしています。 やり遂げるためにどんなことをやっているのか、リニューアルなど大きな開発で起きる仕様の変更による手戻りの発生への対応、全員の共通認識をどうやって合わせてチームビルディングを行っていくかなどをお話します。

ネットの反応

概ね好評だったようでよかったです。 サグラダファミリアと一日8時間コードがかけると思っているは結構うけたようでよかったです。

Design Docや自前のHIGなどへの取り組みも興味を持っていただけたようです。

テストについて

  • QAさんによるテストやテスト仕様書の話をしなかったので、自動テストだけでいくと思われてたかもしれません
  • 仕様書とテスト仕様書はちゃんと作って、継続的な運用にしていく予定です

感想

会場がすごく広くて、自分が発表したA会場は500人ぐらいはいるかなり大きな会場でした。 4会場あって、様々な発表があり視点が広がって非常に楽しい時間でした。 リニューアル関係の話も結構あって、いろんな会社がいろんな取り組みをしているのが興味深かったです。

来年はリニューアルしたアプリでの具体的な成果を発表できたらと思っています。

最後に。今年はストラップスポンサーとしても参加していました。 今年のオープニングは三石 琴乃さんによる某アニメ風になっております。弊社も読み上げられていますので見てみてください。

カラムナフォーマットのきほん 〜データウェアハウスを支える技術〜

こんにちは、Retty.Inc ソフトウェアエンジニア兼データサイエンティストのchie(@chie8842)です。 好きなたべものは焼肉とみかんです。

現在Rettyでは、次世代分析基盤を構築しています。Rettyでは、サービス拡大に伴いログの急増や分析需要の拡大が見込まれるため、高いスループットとコストパフォーマンスを両立する、スケールするアーキテクチャ設計が求められています。

今回は、こうしたスケールするアーキテクチャ設計の実現のために理解しておくべきDWHのコア技術の一つである、カラムナフォーマットに焦点を当てて紹介します。

はじめに - カラムナフォーマットとは

カラムナフォーマットとは、データベースの分析用途に利用されるファイルフォーマットの種類の一つです。大量のデータを扱う際に効率的に圧縮してストレージコストを下げたり、計算時に必要なデータだけを取り出して計算コストを小さくできる設計がされています。
本稿では、分析基盤で利用されるファイルフォーマットの概要を紹介し、 そのあとに、カラムナフォーマットにおける符号化方式、データモデル、ファイルフォーマットについて説明しようと思います。

分析基盤で利用されるフォーマット

最近は分析基盤用途として、Hive、Presto、Sparkといった並列分散処理プロダクトやそれらのマネージドシステムであるAmazonのEMRやAthena、GCPのDataProc、そしてフルマネージドなBigQueryやRedShiftが利用されるようになりました。

これらのプロダクトで取り扱えるフォーマットは、大きく以下3つに分けることができます。

  • テキストフォーマット(例:CSVJSON
  • 行指向フォーマット(例:AVRO)
  • 列指向(カラムナ)フォーマット(例:Parquet、ORC)1

CSVJSONといったテキストフォーマットは、人間からの可視性が高い、アプリケーション連携がやりやすいというメリットがあります。しかしながら、データベース用途のフォーマットとしては、人間からの可視性よりも、保存時の圧縮効率や機械による処理のしやすさを追求する必要があります。データベース用途に向いているフォーマットの種類としては、行指向フォーマットと列指向フォーマットがあります。
行指向フォーマットと列指向フォーマットの違いは、データの格納方式です。
行指向フォーマットは、行方向に連続してデータを格納するため、一つの行をまとめて操作することの多いOLTP処理に向いています。従来のデータベースはもともとこの行指向フォーマットが利用されてきました。
ストレージ技術などの発展により、DWH用途での利用を行うようになって、注目されるようになったのが列指向フォーマットです。列指向フォーマットは、列方向に連続してデータを格納する方式で、列単位でデータを取り出す分析用途に向いています。

主要なOSSのカラムナフォーマットのライブラリとしては、ParquetとORCがあります。
ParquetはTwitter社とCloudera社が、2010年のGoogleの論文Dremel: Interactive Analysis of Web-Scale Datasets(以下Dremel Paper)におけるデータレイアウトに関する内容をOSS実装したもので、ORCはもとはApache Hiveのためのフォーマットとして実装されたという背景の違いがあります。

カラムナフォーマットにおける符号化方式の基礎

カラムナフォーマットでは、データ型やカーディナリティ等の特性に応じて、様々な符号化方式から決定木等によって各列に最適なエンコード方式を選択します。これらの符号化技術自体は、行指向フォーマットでも利用されるものですが、カラムナフォーマットでは、型が同じデータが並んだり、規則的にインクリメントするデータが並ぶなど、符号化によるデータ圧縮が効きやすいというメリットがあります。

ここで符号化方式の一部を紹介します。

Null Suppression

これは、nullの多い列の圧縮に大きく寄与する技術です。nullの値を埋め込む代わりに、どこにいくつnullが存在するかの情報を保持することで、データサイズを小さくします。

Dictionary Encoding

以下の図のように、辞書情報を作成して、その辞書情報を利用して符号化する方式です。
データのカーディナリティの低いString形式のデータに有効ですが、データのカーディナリティが高くなると、辞書情報が肥大化して圧縮率は低くなります。 スクリーンショット 2017-06-05 2.25.22.png

Run-Length Encoding(RLE)

RLEは、繰り返しが続くデータに対して、下図のように繰り返し項目をまとめて保存する方法です。
繰り返しの長さが長くなるほど、圧縮率が高くなる特徴があります。
スクリーンショット 2017-06-05 2.24.41.png

Delta Encoding

Delta EncodingはTimestamp型などのインクリメンタルなデータで効果的なエンコード方式です。
Delta Encodingでは、まず最初に参照値を決め、それ以外の値をブロックに分けます。
それぞれのデータにおいて、一つ左隣の値との差分をとります。
この値の最も小さい値を使って標準化し、最後にビット数に直します。
図の例だと、最初の112bitから40bitと、3分の1程度に圧縮されていますが、データ量が多くなるほど圧縮率が高くなります。^2 スクリーンショット 2017-06-05 2.28.10.png

Bit-Vector Encoding

Bit-Vector Encodingは、Boolean型などの限られた値をとるデータに用いるエンコード方式です。
ある値と合致するかどうかを1と0で表したものを保持します。データのカーディナリティが著しく低い場合に有効です。
スクリーンショット 2017-06-05 2.34.59.png

Dremelのデータモデル

次に、BigQueryやParquetで実装されている、Dremelのデータモデルについて紹介します。
カラムナフォーマットについて書かれた論文に、GoogleのDremel Paperがあります。BigQueryはこのDremelの外部公開版であり、また、Parquetもこの論文をOSS実装したものです。
Dremelの新規性として、ネストされたデータに対応できる柔軟なデータモデルが挙げられます。下図(Dremel PaperのFigure1を引用)の左のように、record orientedな方式では、ネストされた型や特性の異なるデータが、並ぶ形となり、上記で述べたエンコードの効果を受けにくく、またネストされた一部のフィールドを利用する際にも、不必要なフィールドも含めてデコードする必要があります。対して右のcolumn orientedな方式では、同じフィールドのデータをまとめて保存でき、ネストされたデータの一部を利用する際には、木構造をたどることで必要なフィールドのみを抽出することができます。

スクリーンショット 2017-06-05 2.49.04.png

しかし、1つの行に何回同じフィールドが出現するかわからないようなrepetableなデータを扱う場合、そのデータ構造を欠落させることなく小さいオーバヘッドで木構造のデータを保持するための工夫が必要となります。
Dremelでは、下図(Dremel PaperのFigure2,3を引用)のように、反復レベル(Figure3の表におけるr列)と定義レベル(Figure3におけるd列)をもつことで、データ構造を復元できるようにしています。
スクリーンショット 2017-06-05 2.49.18.png 反復レベルと定義レベルの説明は以下のとおりです。

  • 反復レベル
    • あるレコードにおいてそのフィールドが初めて出現する場合は0とする
    • 2つ目以降については、親フィールド配下での反復回数を表す
  • 定義レベル
    • 一意でないフィールドの階層を表す

BigQueryでは、repetableなデータで構成されるデータを対象とした分析を行う場合などにこのデータモデルによるクエリ速度向上が見込まれます。

ただし、私個人の意見としては、Parquetの場合はクエリエンジン側がこのようなデータモデルに対応したものである必要があることもあり、現状でこのデータモデルの恩恵が生かされている例は少ないのではないかと考えています。

ファイルフォーマット

ParquetやORCでは、分散処理を行うことを前提として、Encoding/Compressionの単位、IOの単位、MapReduceの単位で処理しやすいようにデータが分割配置の工夫がされています。
以下の図はParquetのファイルフォーマットの説明図です。
スクリーンショット 2017-06-05 2.51.28.png File/Row Group/Column/Pageといった単位でデータを分割配置されていることがわかります。
また、上記の分割単位ごとに、ヘッダ/フッタにメタ情報を持っています。メタ情報の内容としては、

  • レコード数
  • データの最大値/最小値
  • メモリに展開した際のサイズ

などがあげられます。
メタデータを利用することで、データを読み込む際に、必要のないデータを読み飛ばすことができます。たとえば、

SELECT tbl1.colA, tbl2.colB FROM tbl1 JOIN tbl2 ON tbl1.colA == tbl2.colA;

といったクエリの場合、最終的に必要となるのは、tbl1のcolA、tbl2のcolAとcolBだけとなります。ParquetやORCを利用すると、ファイルスキャンの段階で、これらの必要なデータのみを抽出することが可能になります。
ただし、メタデータによる最適化が利用されるかどうかはクエリエンジンのオプティマイザによって作られる実行プランに依存します。

分析基盤におけるフォーマットの選定について

ここまでカラムナフォーマットのアーキテクチャと分析基盤における有効性についてざっくり説明しました。
上述したとおり、カラムナフォーマットにはクエリパフォーマンスをあげるための仕掛けが施されています。ただし、フォーマットはあくまで最適化しやすいデータ形式であって、それらを活かし切るかどうかは実際に処理を行うクエリエンジン側に依存します。
データの特性や利用するプロダクト、実行するクエリパターンによって、フォーマットを適切に使い分けることができるとよいと考えます。

まとめ

以上、目新しい技術というわけではないですが、分析基盤の縁の下の力持ち的なカラムナフォーマットの技術について、淡々と述べてみました。

尚、本稿の内容については、5/18のBIGDATA-JAWSにて、「カラムナフォーマットのきほん」というタイトルで発表をさせていただきました。

speakerdeck.com

Rettyでは、DWH技術を学びたい技術者を募集しています。
www.wantedly.com よろしくお願いいたします!

参考資料


  1. BigQueryとRedShiftも内部的にカラムナフォーマットが用いられている。