「コーディングを支える技術」技術書筋トレ₍₍(ง˘ω˘)ว⁾⁾:1本目

どうも、キッチンです。

さて自分は2021年の春からWeb系の企業に就職が決まったのですが、働き始めると通信やアーキテクチャなどの基礎知識をつけようとしてもなかなか時間が取れなくなるでしょう。

そこで自由に学ぶ時間が取れる大学生のうちに体系立った基礎的な知識を学ぼうということで一ヶ月ごとに1冊の技術書を読む「技術書筋トレ₍₍(ง˘ω˘)ว⁾⁾」を始めることにしました。

 

ところでこの顔文字って筋トレしてる感あっていいですよね₍₍(ง˘ω˘)ว⁾⁾

 

この記事は技術書ノックの1本目になります。

 

今月の技術書

f:id:kitchen_py:20200203144923p:plain

今月のイッポン

 

この本を選んだ理由

1本目ということで、「プログラミング言語ってなに?」というところから学びに行きます。

そこで前に読んで分かりやすかった「Webを支える技術」のシリーズからちょうど良さそうな本が出ていたので選んでみました。

 

この本の対象読者

一つの言語を習得していて自らなんらかのアウトプットを出したことがあるレベルの人を対象にしています。

 

本を読んで得られたこと

  • プログラミングに関する要素技術についての歴史的な変遷
  • 要素技術に対する言語ごとの考え方の違い
  • 文字集合Unicode)、符号化器(ASCII, UTF-8)の話
要素技術に対する言語ごとの考え方の違い

例えば『ファイルを開いた後に閉じる』といったような、対になる処理を正確に実行するための取り組みは結構おもしろかったです。

 

Finnaly

この問題に対しての取り組みは複数あって、この中の一つとしてMicrosoftがとった取り組みがFinallyでした。Finallyは例えばPythonでは以下のように書くことができ、これによって例えばFinallyで囲われた部分にファイルを閉じる処理を書けば途中でエラーが出てもファイルは無事閉じられることになります。

  

じゃあFinallyが無い言語ではどうしているのか?

C++にはFinallyがありません。

C++ではFinallyの代わりにコンストラクタ/デストラクタが使われています。対象を扱うためのクラスを用意し、スコープの寿命を利用することで必ずデストラクタを呼び出して対の処理を呼び出すようになっています。 

 

次に読む本

次はソフトウェアのアーキテクチャについて学びたいです。


春休みごろにどうせまたWebサービスでも作りたくなるだろうと思うので、その時には「今回のサービスで使うのに良さそうなアーキテクチャはAとBがあってそれぞれにはこういった長所があるけれど、今回のアプリは今後の拡張性を考えてBでいこう」みたいなアーキテクチャの評価と選定のプロセスを踏めるようにしておきたいんですよね。

これによって実装中に迷った時に同じアーキテクチャの実装例ではその問題にどう対処したかなどを参考にすることができるようになることを期待しています。

CyberAgentのアドテクインターンに行ってきた話をするよ

ぱじめまして。

先日、CyberAgentが主催するアドテクインターンに行って参りました。

学ぶことが本当に多いインターンで、自分の考えをまとめてそれに対して他の人からのフィードバックを貰いたいという思いが積もったために一筆したためました。
書き終えてみれば文字数も1万字を超えており、そこでふと振り返ってみる自分の頭に浮かび上がる1つのワードがありました。

今日はこれを是非みなさんに伝えたいと思います。

それでは聞いてください。


一万字越えててマジ万字

f:id:kitchen_py:20191013124301j:plain

アドテクインターンis何

アドテクっていうのは広告に関するテクノロジーのことです。

 広告分野は結構カオスなんですが、その仕組みの一つにメーカーさんとかの「広告出したい側」とブログ主なんかの「広告枠を持っている側(メディア側)」が、それぞれお互いの利益を最大化しようとする代理人をたてて広告枠をオークションする(RTB)というものがあります。

 今回のインターンではオークショニアの役割を果たすサーバが広告枠情報を送信し、それぞれの学生チームがその広告枠にいくらまで出すかを決めるサーバを実装します。

  • 期間
    3日
    開発は最終日のお昼までで、その後はシステムの運用フェーズ

  • チーム開発or個人開発
    チーム開発
    1チームはサーバサイド2〜3人+機械学習(以下ML)2人で構成される

  • 参加人数
    30-35人ぐらいだった気がする

  • 待遇・報酬
    遠方からの参加の場合東京までの交通費支給
    報酬は無いです

adtech.cyberagent.io

要件

 メンター側が運用しているメディアサイドのサーバ(Sell-Side-Platform)に対して、オークションを行う広告サイドのサーバ(Demand-Side-Platform)を実装&運営する。

  • 運営サーバからメディアの広告枠情報が各チームに毎秒2000リクエスト投げられる
  • 運営サーバから送られてくる広告枠情報を分析して、その枠にいくらまで出せるかを推定したレスポンスを返す
  • レスポンスは100[ms]以内 
  • レスポンスを受け取った運営サーバは、一番高く買ってくれるチームに対して落札完了の通知を行う
  • 各チームは予算を持っており、数時間にわたる運用フェーズ終了時には可能な限り使いきっている必要がある
  • 予算が尽きてオークションに参加しない時は204を返す等の細かいルール

 最終日はそれぞれのチームが作ったサーバの運用を行います。

インターン開催前夜

 渋谷駅に付いてるなんかすごく高いビルの高層階で顔合わせ会がありました。 ハッカソンタイプのインターンでは他のチームの人と関わる機会ってあんまりないと思うんですが、このインターンではチーム外の学生とも交流ができるようになってていました。ありがたい。

 チームメイトともこのタイミングで顔合わせできるようになっていて、お互いになにができる人だとかザックリどんな方針で推定しようかとかのお話ができました。インターン中だと時間制限があってゆっくり話せないし嬉しみがある。 あと、インターン前日の宿も手配してくれていて、これがなかったら近辺のカプセルホテルに泊まるとかになってたと思うので学生的には結構嬉しい要素でした。

f:id:kitchen_py:20190927211044j:plain
インターン前々日に泊まっていたネット繋がらなさそうなドミトリー(CAとは特に関係ない)

1日目

 午前中はアドテクの説明だけで終わりました。

 お昼ご飯を食べながら1時間ぐらいチームビルディングをして、午後から作業開始です。

チームビルディング

 チームビルディングではレクリエーション形式で自分が大事にしていることとか、逆に優先してないこととかをレクリエーションを通して共有しました。  この時点で積極的にリーダーシップを取ってまとめるタイプの人がいないことが分かったので、自分は普段人をまとめるタイプじゃないですが誰かがやらないとチームが回らなそうな予感がしたためにこのインターンではファシリテーターもどきの役割をすることにしました。あとこの時になんとなくMLとサーバサイドの間に立つコミュニケーションが必要なポジションは自分がやると良さそうかなーってざっくり考え始めてました。

言語選定

 まず、MLについてはデータ分析のためのライブラリが充実していることと習熟度からPythonを使うことは決定しました。これはそこまで議論は無かったと思います。

 次にサーバサイドメンバーが実装する部分についてですが、これについては結構迷いました。2つの選択肢が考えられていて、1つは毎秒2000リクエストをより確実に捌くためにGoかScalaを使う選択肢で、もうひとつがMLとの接続部分の実装を簡易にするためにPythonで実装する選択肢。

 GoかScalaを選ぶ場合はサーバの中で2つの言語の通信を行う必要があり工数が増えるというデメリットがある一方で、サーバサイドとMLでプログラムが完全に分かれるために責任範囲が明確になり、またコンフリクトしにくいというメリットがあります。

 Pythonを選ぶ場合はサーバサイドとMLサイドのプログラムを結合する部分が楽であるというメリットがありますが、実装が完了していざテストしてみると言語の速度の問題でリクエストを捌ききれなかった場合に絶望的な出戻りがあるというリスクがあります。

 結局、もしPythonを選んで言語の速度の問題でリクエストを捌ききれなかった時のリスクを回避するために比較的処理が早いGoを選ぶことにしました。

システムの設計

f:id:kitchen_py:20190916220431j:plain
実装したGoサーバとPythonサーバを通した処理の流れ
 フレームワークについてですが、Goは標準ライブラリが充実しているためにフレームワークを使わずに実装することにしました。 pythonサーバは確かflask使ってた気がします。正直あんまり覚えてないです。 2000QPSで送られてくるデータに対して高速に返答する必要があるため、DBにはKey-Valueでデータを取ってこれるRedisを採用しました。

 次にデプロイですが、タスク的にGCPでも足りましたがインフラをやってくれる人が新しいことに挑戦してみたいということでKubernetesを使うことにしました。

 全体的な処理の流れとしては、GoサーバはDBを参照して得たデータとリクエストごとの広告枠データをJSON形式のHTTPリクエストを使ってPythonサーバにPOSTします。そしてPythonサーバは前処理・推論の後にその広告枠の予測CTRを返します。次にGoサーバは得られたCTRに加えて、対象の広告主の予算をオーバーしていないか、制限時間が近いのに予算が余りすぎていないかなどから得られる係数を考慮して最終的な広告枠に出す価格をメディア側のサーバ(SSP)に返します。 最も高い価格を出していた場合は落札の通知がメディア側サーバから送られ、Goサーバは広告主の予算を更新します。

f:id:kitchen_py:20190927211049p:plain
オートスケーリングのイメージ

タスク割り振り

 さて、システムの設計は終わりました。次はタスクの割り振りです。

 サーバサイドですが、まずGCPのデプロイ経験があるサーバ担当の1人がインフラ担当、別のサーバ担当2人がGo言語が初めての人とGo言語慣れてる人のタッグでGoサーバを担当することになりました。 デプロイ経験がある人がいてくれるのはありがたい。

 MLは普通に二人でMLやるわけですが、2人とも共同で機械学習を行うのは初めてだったので、2人でやるいい感じの開発方法をいくつか考えてみたりしました。このフェーズが一番楽しかったかもしれない。

  • 弱肉強食作戦
     一番愚直な作戦で、それぞれに作った予測器を比較していい方を使おうというもの。

  • アンサンブル作戦
     2人が別々のCTR予測器を作ってアンサンブル学習する作戦です。  弱肉強食作戦と比較して一方のコードが全て消えるとかいう悲しいことは無いですが、 せっかく実効速度が早いモデルを作ってももうひとつのモデルがボトルネックになりそう。

  • 特長エンジニアリング+予測器作戦
     1人が効果的な特徴量を作り、もう一人が予測器の方に注力するという作戦。  個人芸のコラボレーションによって性能を上げる感じがとってもエモい。  予測器を作るだけだとその担当は余力が残りそうなので、追加でオンライン学習とか重みのオンラインストレージ保存とかやってもいいかもしれません。  個人的に推しな作戦です。

 まあそれはとりあえず前処理終わった時点で決めればいいかということで判断を保留して、最低限MLの間で何をどこに実装する必要があるのかを共有するためにペアプロ形式でファイル構成とかをやりました。

 やるべきことは決まった、さあ後はゴリゴリ実装するだけ。 だけどまぁデータの前処理せな話が始まらんよなぁということで、前処理担当とPythonサーバのモック担当に分かれて作業することにしました。 この時点で相方があんまり話すタイプでは無かったので、Goサーバ側と頻繁に打ち合わせをす必要があるPythonサーバのモック担当を自分がやって、相方にデータの前処理をお願いしました。 うん、バランス良さそうに見える。いい感じですね(フラグ)。


当時のぼくの心境「よしよし、いい感じに決まってきてる。gitあんまり使ったことない(?)人がいたり口数少ない人もいるけどみんなやること分かってるしなんとかなるやろ。」

いざ開発

 Goサーバ側はGoに慣れている人が速攻でモックを作り上げてくれました。すごい。

 ML担当である自分の相方はデータの前処理が結構長引いていて自分がPythonサーバのモックを作った後にしばらく空き時間ができたので、Makefile書いたりデプロイのために使うライブラリのバージョンをリストアップしたり、MLなのに負荷テスト用のサーバをGoで書いたりと独立したタスクを刈り取ってました。  サーバと自分のタスクは順調に進んでいたんですが、デプロイとデータの前処理については手間取っているようでした。デプロイはその人にとって挑戦的なことをしているから時間かかるのは仕方ないけど、もっと人に聞きながら進めてもよかったねという反省を得て明日からはメンターさんに細かく聞きながら作業を進めるという方針になりました。  チームで決めていた一日目の目標は最小構成で統合して動作テストをすることでしたが、 結局ローカル環境でGoサーバとPythonサーバを導通させてテストすることも最小構成のデプロイもできてはいませんでした。


ぼくの心境「まぁちょっと進捗ヤバイけど、みんな今日の夜に作業してくれるみたいだしなんとかなるやろ」

f:id:kitchen_py:20190927211047j:plain
一日ごとにやったKPT

2日目前半

〜 午前の作業が終わり、2日目のお昼 〜
ML : 「データ前処理、、、終わってません」
デプロイ : 「最小構成のデプロイ、、、できてません」
f:id:kitchen_py:20190927200014p:plainf:id:kitchen_py:20190927200014p:plainf:id:kitchen_py:20190927200014p:plain


ぼくの心境「あかん、なんともならんかもしれん」

 結局データの前処理は大体2時間程度でおわるという共通認識でしたが2日目のお昼まで長引いてしまったため、この時点で自分の「 特長エンジニアリング+予測器作戦」とか「アンサンブル作戦」だとかモデルの妥当性を検証するだとかの計画は瓦解しました。

 これによって俺達コミュニケーション取れてなかっんじゃねって認識が受け入れてもらえて、その問題を仕組みで解決するべくメンターさんからのアドバイスでMLの間で「30分ごとの進捗報告」を取り入れてみることにしました。これは実際かなり上手く機能していて、これをきっかけにMLはチームとして機能し始めました。

2日目後半

 前処理が終わってからの自分はロジスティクス回帰の学習部分を書いていたんですが、何故か予測値はテストデータに対して0しか吐き出さないという状況に悩まされてました。
データの不均衡性が怪しかったのでclass_weightを考慮したりダウンサンプリングを使ったり、それでも良くならなくて教師データを見直したりで午後はこの問題に対応していました。

 データの不均衡周りを解決した辺りで施設が閉まる時間になり、MLは場所をスタバに移して深夜作業のための打ち合わせしたりしてました。直接会えない時間帯のコンフリクトや大きな出戻りが怖かったので。この時やったこととしては、共通して使う部分のコードの読み合わせと誰がどのファイルに何を実装するのかという確認です。そして深夜にやることとしては自分がストリームデータを受けて推定値を返すという最低限のPythonサーバの実装を担当して、相方がAUCなりの評価指標を使って推定器の評価をしてから寝ようねっていうことで解散しました。

f:id:kitchen_py:20190927211035j:plain
おしゃんな開発

2日目深夜

 2時ぐらいに寝る予定でしたが、途中から気分がノッてきて朝まで実装してました。

f:id:kitchen_py:20190927211056j:plain

 後はパラメータ調整するぐらいで、もうデプロイ班に引き渡してもいいぐらいまでには進捗が進みました。というか、空が徐々に明るくなってきているぐらいでちゃんと起きれる自信が無くなっていて、後は自分がいなくてもMLは大丈夫って言えるぐらいまで進ませなければならない必要性がでてきたのでやりましたって感じです。 やったことは以下です。

  • ストリームデータから推論する実装
  • ロジスティクス回帰の重みを外部保存、デプロイ時はロードのみを行う実装
  • 統合して動作確認
  • 負荷テスト

 CAに来る前の別のインターンではタスクに優先順位をつけて作業することができていないという反省があったので、ここではタスクに優先順位をつけて上から順に消化していくことに気をつけました。 評価がおざなりではありますが、MLサーバがやっておくべき最低限の機能と動作検証は大体出来たので個人的には満足な一夜でした。

3日目後半

 午前までは開発期間で、12時で一旦完全にコード編集を閉め切りになります。 午後はシステムの運営をしながら成果発表のためのパワポを作って発表します。

 サーバが謎の現象で落ちているチームもあったしローカルで動いていてもデプロイした後に上手く動かなくなったチームもあったりしてました。 自分たちのチームも例にもれず、デプロイしてみると処理速度が遅くてタイムアウトしていたりといったいうエラーに悩まされました。 Pythonサーバは高負荷時でも5[ms]程度だったので、おそらくGoサーバかどこかで動作が遅くなっていたということらしいです。

 この時自分は静かに発表用パワポを作っていることしかできず歯痒い思いをしてました。ちゃんとデプロイまわりも通して全体が分かるようになりたい...

f:id:kitchen_py:20190930205904j:plain
プレゼント待ってます



振り返りパート

 ここまでがアドテクコンペのインターンの流れを追った実体験という話で、ここから先は振り返りとか懺悔とかやります。

1日目: チームビルディング・コミュニケーションの振り返り

 チームメイト同士で何がどの程度できるかの技術レベルを把握しきれてなかったのはミスでした。
割り振っていたタスクがなかなか終わらず、丸一日自分の作業が滞る事態が発生していました。

 自分が知らない分野の技術レベルを測るのってやっぱ難しいです。でも例えばデプロイをやったことがないがデプロイをやりたといった場合、その人が出す目安の「〇時間かかる」の信用度はその人がソフトウェア全般に対してどの程度の経験があるかで大まかに推測できたと思います。

 問題を回避するためのよりいい方法としては、今までに作った作品の見せ合いをするとかが考えられると思います。
副産的に「方向性は自分とは違うけど、君結構おもろいことやっとるやんけ!」ってな具合に互いを認め合う機会にもなったんじゃないでしょうか。

1日目: ミーティングの振り返り

ぼく 「あの~、チーム内でタスクの重さとかの共通認識持ってたいんだけど、いい?」
みんな「(カタカタ...)」

ぼく

f:id:kitchen_py:20190916194416p:plain
からすさん絵

当時の自分としては「ミーティング中は話を聞くのが普通では?」って考えでしたが、時間をおいて考えてみると自分の話し方にもいくつか改善できる点が見つかりました。

  • ミーティングの必要性が説明されていない
  • その話にどれぐらいの時間がかかるのかが明確ではない

なので二日目からは「認識の違いから来る出戻りを少なくしたいから、これについて目安5分で話そう」っみたいに時間と必要性を明確にするようにしました。 そこに気をつけるようにしてからはみんな話を聞いてくれるようになったのでいい改善だったんじゃないかと思います。

1日目: 弱みをさらけ出せてなかった

やっぱり初手で弱みをさらけ出すのは超重要だと思います。再確認しました。 例えば「集中力切れると不機嫌になる」とか「コミュニケーションが苦手」とか言いにくいことは初手で消化しときましょ。これ大事。

1日目: 言語選定の振り返り

 結果的にではありますが、言語選定でPythonとGoを分けたのはかなりいい選択だったと思っています。というのは、与えられたタスクにおいてはモックを一度作ればサーバサイドとMLサイドが歩調を合わせて実装するべきところが少なく、それぞれのプログラムが完全に分離されていることによってMLだけでテストしたりするのが非常に楽だったためです。ROSがなぜあの形になっているのかがよく分かる体験でした。

 あと、後から分かったことなんですがチームメンバでgitに慣れていない人が多かったためにプログラムのロールバックが起こったりしていたらしいんですよね。これがもし全てPythonでやっていたのなら必然的に複数人が同じファイルを触るケースは多くなるわけで、きっとコンフリクトは勃発するわロールバック祭りだわで大変なことになってたと思います。

f:id:kitchen_py:20190930205801j:plain
唐突に現れる渋谷周辺のラーメン春日亭、これがまたおいしい

2日目:データの前処理の長引き

これは非常に考えさせられるテーマでした。

ハッカソン中にこの問題を振り返った時の思考プロセスはこんな感じでした。

  1. データの前処理は必須のタスクで絶対にやらなくてはいけない
  2. もし自分が前処理をしていたら早く終わっていただろう
  3. でもその場合は相方はサーバ経験とGoの経験を持っていないために数時間手が空いてしまっただろう。それに、Goサーバでも遅れがあったから自分が手伝いに行く必要性もあった。 ↓
  4. もしハッカソン開始時点で前処理をやってもらうと時間がかかることが分かっていたとしても今の状況を選んでいたんじゃないか。

これに対する懇親会やカンファレンスなどでいただいた意見を列挙しておきます。

  • アジャイル的な考えでいくならば、タスクを可能な限り細分化する * 一般的には有効な方法だと思います。 ただ、今回はタスクは要素を分解して二人で並列してやっていくことはかなり非効率的なものだったために分けることはできなかったと思っています。

  • 進捗が「少し不安かな?」って思ったタイミングでペアプロに切り替える
    これは目からウロコでした。 タイミングによっては言い出しづらいことですが、当時の自分はムードメーカーとしての立ち回りをしていた(つもりな)のでペアプロする?みたいにフラットにフォローしに行けたはず。

f:id:kitchen_py:20190930210332j:plain
堅い話をしてしまったので場を和ませに来てくれた渋谷のラーメン風ジャンクフード、これがまたおいしい

まずは最低限の実装をしよう

相手が求めている最低限の実装を先にCommitする習慣を付ける必要性を感じました。 自分はこだわるところにはとことんこだわるタチなので、先にセーフティネットを用意してからこだわるようにしていきたいと思います。

分からないことを分からないって言うこと、無知をさらけ出すこと

ハッカソンはいろんな分野の人が集まるので必然的に自分の知らない技術とかライブラリも出てくるわけで、 そこでプライドを捨てれなくて「あ〜それね、知っているが??」みたいになるとせっかくの知るチャンスを失うことになるので勿体無いです。

その点で言うと自分は馬鹿みたいに「Redisってなに?Kubernetesってなに?」って聞きまくることができていて、無知をさらけ出すことについてはガチプロだったと思います

f:id:kitchen_py:20190930210622j:plain
もはや渋谷にすら関係がない。次郎系ラーメン店の総本山

時間の見積もりの甘さ

「その作業どれぐらいで終わる?」って聞かれた時、自分はこの時間までに終わりたいっていう目標の時間を伝えていました。 それで目標の時間はあくまでも目標なので大体オーバーするんですよね。 1時間で終わるって言ってたものが3時間とかかかってたら当然相手は不安になるわけで、これは良くない癖だと認識できたので改善策を立てていきたいと思います。

改善策

  • バッファをとった時間を伝える
    目標の時間を持つこと自体は悪くないと思うので、「目標としては1時間で終わらせたいけど、2時間ぐらいは見ておいてほしい」っていうふうに正直に伝えようと思います。
  • 遅れそうになった時に伝えること
    遅れることには理由があるはずで、その理由とあとどれぐらいかかりそうかを伝えられればチームメイトも安心。

運用フェーズに入ってからの問題発生はどうやったら避けれたか

私達のチームでは、運用フェーズに入ってからローカル上では見えなかった問題が発生していました。 これの根本的な原因としては自分を含むML班やGoサーバ班がGKEによるデプロイのタスクの重さを見誤り大きく遅れてしまったためにGoサーバが細かくデプロイして検証していくことができず、結果として運用でエラーがでたと解釈できます。 もし自分達がGKEがリスキーだと認識していたならば、まずはGCEでデプロイできるようにセーフティネットを張って、その後に挑戦的なことをやろうと提案できていたんじゃないでしょうか。

これを経験して流石にデプロイを知らなさすぎるということで、具体的な改善方法としてDocker本を買ったのでこれを読んだうえで自作サービスをデプロイすることで理解を深めていこうと思います。 f:id:kitchen_py:20190927211041j:plain

ペアプロの際にvimで感動を与えることができた

うろ覚えですが「vimって使い手によってここまで変わるのか...」って言葉を引き出せました。 自分の力はエディタ界隈においてまだ小学生レベルですが、それでも誰かに認められるのって嬉しいですね。

まとめ

 手が空いた時は片っ端から浮いてるタスクを刈り取っていけたり、ML担当になのにGo書いてたり、一夜でロジスティクス回帰の学習部分実装と外部への重み保存とストリームデータから推論する実装と統合テストと負荷テストを終わらせたり、個人としてはこれ以上無いほどにベストを尽くしました。 他にもサーバ間の通信部分などコミュニケーションが必要となる部分を率先して担当し、密に確認をとりながら進めることで大きな出戻りも無く終われたことは目立たないながらもファインプレーだったと思います。

 ただ個人としてベストを尽くした一方でチームがよりうまく回るためになにかできたことがあったんじゃないかという思いもあり、実際にやってるときはベストのように思っていても時間をおいてみるとよりベターな方法があったんじゃないかと考えさせられることが多いインターンでした。

 今までは自分は一人のエンジニアとしてチームの足りてない部分を埋める役割かゴリゴリコードを書く役割が多かったのですが、今後はエンジニアという枠にとらわれずに必要があればファシリテーターのような役割を補う選択肢も考えていこうと思います。

最後に

 一緒に実装したチームのみんな、メンターの方々、エモいが口癖になってたメンターの方々、そしてCAを紹介していただいたyodaさん、本当にありがとうございました!

あと最後に1つ、これから誰かと一緒にコードを書くみんなに伝えたい。
人に渡すコードには分かりやすい変数名を使ってくれよな! f:id:kitchen_py:20190927211045j:plain

TreasureっていうWeb系インターンに行ってきた話

TL;DR

  • Web系インターンのTreasure2019に参加してきました
  • Treasureはイイぞ
  • 強い人が多い環境も最高ダゾ
  • ロボット開発とWeb開発は開発方法に根本的な違いがあるという気付き

f:id:kitchen_py:20190901222907j:plain

まずここで衝撃

 

どんなこと書いてるのか

他の人がインターンで何をやったかというところにフォーカスしていたので、自分は学生活動とチームのWeb開発の違いというところにフォーカスして書いていきました。

denden-seven.hatenablog.com

shinya-ml.hatenablog.com

Treasureってなんぞや

TreasureはVoyageGroupさんのWeb系インターンの名称です。

 

学生の参加人数は30人ほどで、みんなそれぞれに実務経験者だったりNIPSに論文出してたり、それぞれの必殺技みたいな強みがあって結構おもしろかったです。

f:id:kitchen_py:20190901223040j:plain

え、なにこれ

f:id:kitchen_py:20190901223130j:plain

おしゃん

f:id:kitchen_py:20190901223125j:plain

おしゃしゃん



期間としては3週間あって、その中で前半は講義形式でインプットを行って後半に学んだことを使ってプロダクトをチームで開発するという形式でした。

この前半の講義ではフロントからバックエンドとデータベースを扱っていて、1つのプロダクトを作るために必要な知識を限りのある時間に詰め込みましたっていう感じ。

この講師陣がまた物凄くて、みんなのGoで有名なすずけんさんを始めとした技術的にめちゃくちゃ強い方々が毎日交代でそれぞれの担当分野を教えてくれるんですが、 これまた講義の内容が濃すぎて毎日シェアハウスのメンバーと日が変わるまで復習したりしてました。

f:id:kitchen_py:20190901223510j:plain

LTの様子

あと、vimmerを増やしたりしました。

f:id:kitchen_py:20190901223544j:plain

f:id:kitchen_py:20190901223543p:plain

チーム開発の話

後半のチーム開発では5人ほどのチームを組んで約1週間の間にプロダクトを考えてデプロイするところまでやるというものでした。

問題を解決するためにプロダクトを作るのでハードウェアを絡ませても面白かったと思うのですが、このインターンではたぶんウェブサービスを作ることを想定してそうだったりしたで、流石に自重しました。

 

チーム開発する上でなにかと判断を迫られることが多そうだったので、とりあえず個人的な優先度決め。

  1. 自分にとって新しいことができるようになる。
  2. チームへの貢献

ただ、優先度1の技術獲得については別にフロントやってもサーバやっても新しいことを学ぶことになるので、フロントとかサーバとか考えずにチームが上手く回るように足りない部分を補うような動きをすることにしました。(チームはサーバサイドをやりたそうな人が多かったので、結果的にフロントをやることになりました。)

 

具体的に自分がやったこととしては、Preact使ったフロント開発、Makefileのバグとりとか、自分が見つけた不具合をDBレベルでバリデーションかけたりといったことでした。

f:id:kitchen_py:20190901224348p:plain

最高にかっちょいいトップ画面。 かっちょよくない???

8,9割はフロント触っていたのでMaterialDesignのドキュメントを読みながらえっちらおっちら任意の実装を行うっていうことができるようになった(と思う)のですが、今振り返ってみるともう少しサーバ・DB周りを触る選択肢もあったと思います。

もちろん当初の自分のスキルセットと開発期間ということや、フロントも余裕があるわけではなかったという結構大変な状況でしたし、難しい選択であったと言えるでしょう。

でもそもそもTreasureにはWebに挑戦するために来たわけですし、メンターの方には相当な負担をかけることになりますが「技術獲得のためにOJT形式でサーバに1つAPIを生やしたいです!!!終電までお付き合いお願いします!!!!」とか言ってみるぐらいの挑戦はあってよかったと思います。(←ここ反省ポイント)

f:id:kitchen_py:20190901223257j:plain

お世話になったメンターさんと進捗の権化タワー

ロボットコンペティションとWeb開発の違い

実は、このチーム開発が始まるまでは「ロボット開発はチームで結構やってきたし、まあなんとかなるやろ。 一応世界5位やし。(謎イキリ)」程度に考えてました。

ただこれが全く違うものだったんですよね。

先に言っておくと、以下のことが違う点でした。

  • 最適化するべきこと
  • コードレビューの文化
  • ソフトウェアをメンテナンスする文化
1. 最適化するべきことの違い

ロボットコンペティションの場合は技術獲得や政治を考えなければ、最適化するべきは大会の点数っていうことが明確になってるんですね。

ソフトウェアはハードウェアと違って人件費以外ほぼかからないし、ロボカップやワールドロボットサミットのような知能ロボットの分野ではニューラルネットワークの実行時間が長いことが知られているから実行時間については数十秒程度でもいいよとか、Webと比べるとかなり緩く設定されてることがほとんどです。

 

それに対して、Web開発はUX向上やサービスのコンセプトなど最適化するべき項目が多いように見えました。


2. レビュー文化とコードをメンテナンスする文化の違い

ロボットコンペティションだと基本的にそれぞれの担当箇所のソースコードを書いてもレビューは無いし、書いたコードは1つの大会で使ったらもうそれ以降使われないことも多いんですよね。

 

これらの理由としては、ROSの存在が大きいと思います(個人的な意見です)。

Web業界の方に向けてROSについて少し話しておきましょう。

ROSというのはロボット開発のためのミドルウェアのことです。

簡単に言えば、ソフトウェアをレゴブロックのようにソフトウェア同士の通信の部分を規格化することができます(だいぶ噛み砕いてるけどマサカリ飛ばさないでね)。

例えばROSに対応した画像認識のプログラムがあったとして、そのプログラムを全く読んでいない人でも、レゴブロックをつなぎ合わせるように自分のプログラムを繋げることができるようになります。

Foo!!ROS最高!!

こういったROSの特性から、一度書かれたコードは使おうと思えばブラックボックスとして利用可能になります。

もちろん使うソフトウェアの理論は調べて使いますが、知能ロボットコンペティションにおいては例えば人間の認識、物体の三次元位置推定、音声認識自然言語処理、自己位置推定、さらにはハードウェア制御などなどと最低限実装するべきことが山ほどありますしこれを片手で数えられる程度の人数で2,3ヶ月で実装するとかはまあよくあります。

既存の動くことが確認されているソフトウェアをソースコードのレベルで理解しようとする人は非常に少ないと思います。

f:id:kitchen_py:20190901224024j:plain

文脈を無視した寿司

VoyageGroupの感想

  • 技術的なネタが通じるのが嬉しい
    ドアをノックして「GET /open」とか言ったら「200 OK」とか返してくれそうな会社で、技術的に熱い話ができる人が多いような印象でした。 これを自分の研究室でやったなら、たぶんタイムアウトするでしょう。
  • 技術的に強い人が多い
    N数が10ぐらいの自分の観測によると強い人が多かったです。
  • 燻製やってる人が多い
    この情報いるか??
  • 自作キーボード勢多い
    この情報いるか???

    f:id:kitchen_py:20190901224224j:plain

    そして文脈を無視して現れる寿司


強くあるための環境についての話

インターンではWebが初めてだったということもあって技術的なインプットをたくさんもらいました。

ただ、それよりもこのインターンではエンジニアとして強くなるために必要なことを教えてもらった気がします。

 

 

先輩エンジニアの方のライブインタビューで、こんな解答がありました。

(脳内再現)

質問者の方「仕事をするチームの大きさは?」

先輩エンジニア「2人ぐらい、わざとチョイ足りないぐらいにしてる

 

これには衝撃を受けました。

実は自分、前年度は10ヶ月の間に3つのロボットコンペと共同研究と卒業研究を行うという謎の多忙具合だったんですよね。

新しいことに挑戦したい気持ちで手を上げ続けていたらどんどんタスクが増えていって、特に機械学習分野の基礎的な理解を十分に固めることができなくなっていたわけです。

 

それを受けて、今年はじっくり機械学習の基礎であったり修論サーベイを着実にやっていこうと思ってロボットコンペティションとかやってなかったんですよね。

基礎から学び直すことは自分にとって必要なことだったし後悔はしていません。

 

ただ、成長度合いとしてはやはり去年のほうが劇的でした。

かなり厳しい道になると思いますが、この秋はコンフォートゾーンの外側にいくために研究と並行して大会にもチャレンジしていきたいと思います。

どんどん成長できる環境に自分を追い込んでいきましょう。

 

最後に

Web系が初めてということもあって、本当に怒涛の日々でした。

VG社での濃密な講義が終わってシェアハウスに戻っても、常に開発したり技術のことを話したり燻製したりと本当に技術漬けの3週間だったと思います。

 

ふとインターンが終わった今の自分を見てみると普通に人の形を保ってるし、もっと頑張れたんじゃないかとも考えられるんですが、毎日普通に2時ぐらいまで開発とか自習とかやってたし、それに加えてなんか風邪ひいていたりしたしで、「あれ?なんか結構自分、頑張れてたんちゃう?」って思う自分もいて、なんかもう分からんくなってきました。

ただ少し真面目なことを喋っておくと、メタ的な視点で常に自分がやっている作業がどんな位置づけで優先度はどの程度なのかということを考え続ける必要性を感じたりと、今後の課題が多く見えてきたので今後はそれをクリアしていきたいと思います。

 

最後に、Voyageで丁寧に教えてくれた講師やメンターの方々、充電器忘れたアホな自分をフォローしてくれた人事の方々、チームのみんな、一緒に3週間過ごしてくれたTreasureのみんな、燻製をうまいといってくれた方々、燻製鍋を保管してくれたAUさん、本当にありがとうございました!!!

f:id:kitchen_py:20190901223933j:plain

我がメガネサワーズ