ブログ

ソフトウェアエンジニアインターンのhiroです。
…といっても、正直フライウィールのソフトウェアエンジニア インターンは一体何をやっているのかよく分からない、という方も少なくないと思います。実際、私もフライウィールに応募した時は、スタートアップのインターンはどういう事をやるのかなかなかイメージが沸きませんでした。そこで今回は、自分がインターンとしてどういった課題に取り組んだのかご紹介したいと思います。

概要

今回のインターンで私はインターネット広告配信システム、具体的にはDSP(Demand-Side Platform)と呼ばれている部分の開発を任されているチームに配属されました。DSPとは、広告主がインターネット広告を出稿する為に利用されるプラットフォームのことです。フライウィールはデータの力を利用することで、広告の配信を効率化し、より良いDSPの開発を試みています。
私は長期インターンとしてチームの一員となって実際の業務をアサインされる形式で取り組みました。ただ仕様通りにコードを書くだけではなく、タスクの選定→デザイン→実装→単体テスト→コードレビュー→マージと、限りなく実務に近い流れでエンジニアリングを経験することが出来ました。DSPの開発で主に使われている言語はJavaで、他にもDependency Injectionの為にSpring Boot、単体テスト用にJUnit、インターフェイスの定義にProtocol Buffer等と、どれも慣れない技術ばかりでした。ですが、メンターを含むチーム全員が私に親切に教えて頂けたのですぐに使えるようになりました。「チーム全員でサポートしますので、誰に聞いても大丈夫です」という言葉がとても印象的でした。
ここからは、実際に私が携わったタスクをいくつかご紹介したいと思います。

クライアントとサーバーのスキーマバージョンのチェック

DSPのクライアントとサーバーはgRPCというプロトコルで、protocol bufferで定義されているスキーマを用いて通信を行っています。これが成り立つ前提として、クライアントとサーバーが参照しているAPIに互換性がなければいけません。例えば、クライアントが知らない新しいフィールドがサーバー側に定義されている場合、更新時に新しいフィールドの値が消えてしまう恐れがあります。こういう意図しない挙動を防ぐ為に、クライアントとサーバーの間にスキーマの互換性が存在することを確認する必要があります。
これにはいくつかやり方がありますが、今回はprotocol buffer自体にバージョン番号を埋め込んで実装することにしました。

enum SchemaVersion {
  allow_alias = true;
  CLIENT_VERSION_UNSPECIFIED = 0;
  V_1_3 = 5;
  // Alias.
  CURRENT = 5;
  reserved 1 to 4; // old versions.
}

これで、サーバーはクライアントから送られたリクエストのメタデータからバージョン番号を取得して確認することで、互換性を保証することができました。また、万が一バージョン番号を変更せずに既存のprotocol bufferを変更したものがプッシュされた場合も、dangerJSを使ってGitHub上で警告を出すこともできました。

DSPの機能追加

配信量調整に関する機能の追加もアサインされました。特定の条件を満たした上で良しなに配信量を調整するロジックを実装しました。元々、配信量を調整する機能自体は過去に簡易的な実装が存在していたので、これを単純に適切な部分に移行すれば良いだけのはずでした。しかし、エッジケースの存在から元のコードより分岐処理が増えてしまいました。このままでは技術的な負債になってしまう為、1からデザインを考え直すことになりました。
そこで、デザインドックの出番です。
今回のような複雑な設計を実装する前に議論する場として、デザインドックは非常に効果的です。ドラフトを書き、フィードバックを貰い、軌道を修正するという過程を何度も繰り返すことによって、実装のイメージが明確になりました。特に、エッジケースの洗い出しや全体的なロジックの流れの整理にとても役に立ちました。また、プロダクトマネージャーや広告運用チームと本当に求められている機能は何なのかを議論し、様々な観点からインプットを取り入れることができました。

予測モデルを用いた入札価格最適化実験

DSPでは、リアルタイムのオークションで広告枠を落札して初めて広告を配信することが出来ます。ここで、広告枠の効果を機械学習で予測して、結果から入札価格を計算することで、費用対効果を改善できるかを検証する実験を行いました。機械学習モデルはデータサイエンティストの手によって作られ、私はそのモデルをDSPに導入する部分を担当しました。また、モデルの配信やA/Bテスト用の環境も十分にそろっていなかった為、実験を行うにあたって必要な環境を整えました。このように、今回の実験において私に与えられる裁量は大きく、タスクの切り分け等自分で考える部分が大きかったです。具体的には、実装にあたって以下のことに取り組みました。

  • 入札戦略のスキーマをprotocol bufferで定義
  • 実験用に入札リクエストのトラフィックの振り分け
  • 予測モデルをJSONファイルから読み込みDIコンテナにBeanとして登録
  • 入札戦略と予測モデルから適切な入札価格を決定

やることはたくさんありましたが、全体的なデザインや実装法はメンターからアドバイスを貰うことが出来たので、比較的スムーズに実装することができました。

その他

紹介したものの他にも、広告運用者をサポートする機能の実装にも取り組みました。また、コードベースに慣れると、たまたま見つけたバグを修正したり、モジュールの分離性を高める為にリファクタリングを行ったり、自らチケットを切って取り組む内容の方向性をある程度自由に決められるようになりました。同じ時期にフライウィールでインターンしていたエンジニアは私以外にも数名いて、レコメンドに使われる機械学習モデルのパフォーマンスの改善や、実際の広告運用を手助けする補助ツールの開発等に注力していました。

最後に

私がインターンとして貴重な経験ができた背景には、開発に集中できる素晴らしい環境がスタートアップで既に整っていることがとても大きいと思います。具体的には以下のような点が挙げられます。

  • 優秀なエンジニア達からノウハウを直接学ぶことが出来る
  • コミュニケーションが活発で、情報を共有したり質問を聞くことに対して積極的になれる
  • 新しい知見や技術を取り入れることに対して躊躇が無い
  • 与えられる裁量が大きく、自由に課題に取り組める

フライウィールでインターンとして働くイメージが少しでも沸いたんじゃないんでしょうか。新しい課題にガッツリ取り組むことに興味がある方は、是非応募してみてください!
池田 宏陸