雀巽の日記帳

雀巽が綴る日常の記録

ロンドンのスタートアップに転職して1年が経った~この1年でやったこと~

年内最終出勤が終わり、クリスマス・年末年始休暇に突入しました 🎉

今年の年始に加入したため、これでほぼ丸1年が経過したことになります。

necojackarc.hatenablog.com

そんな昔のことに感じないんですが、自分のブログを読み返してみると随分と昔のことのようにも感じます。

読み返してみると、そう言えばそもそもロンドンに来れない可能性も無くはなかったんだよな、と思い出しました。 無事に VISA のスポンサーになってもらい、ロンドンに移住したというだけでも、凄い1年だったなと感じます。

1年間の振り返りは毎年年始にしているので、今回はロンドンのスタートアップで何をしたのか、ちょっと振り返っておこうかなと思います。

テックスタック

時系列で振り返る前に、簡単にウチのテックスタックについてせっかくなので紹介したいと思います。

基本構成は SPA + RESTful API です。

スタック *1 フレームワーク インフラ
SPA Ember.js S3 + CloudFront
API Serverless with Node.js + Python API Gateway + Lambda

注目すべき点はインフラかなと思います。

S3 + Lambda が基盤となっているので、デプロイでコケない限りは稼働率が実質 S3 と Lambda の稼働率そのままです。

サービス 稼働率
S3 99.999999999%
Lambda 99.95%

実際、今年のウチのサービス稼働率は100%でした。すごーい!

APIPython が出てきてますが、Python機械学習部分でのみ使っています。 基本はすべて JavaScript (Node.js) で書いており、Lambda 内から別の function を呼び出す機能を使って、 一部機能で JS から Python のモデルを呼ぶ、ということをしています。

Ember は常に2位グループでそこそこの人気を維持し続けている息の長い JS フレームワークです。 現状の1位グループは React、Vue、Angular だと思いますが、そのちょっと下あたりの人気度です。 Ember と同世代のフレームワークがほぼ死滅していることを考えると、その息の長さがわかると思います。

Rails をベースにしているので、Rails の知識があると始めやすいです。 そしてもちろん、Rails のようにとっても Opinionated な感じです。そこが最大の利点にもなります。

あと他には、Airflow をデータ処理に利用しています。 Python はそっちでも使っています。

この辺に関しては、2人目のデータエンジニアが来年2月に加入予定なので、 俺が Python でデータ処理をゴリゴリ書くことはもうなさそう……!

ざっくりこんな感じです。それでは、ざっくり四半期ごとに振り返ってみます。

1Q

CTO 兼 VPoE である上司を除くと、エンジニアは私ただ一人という状態でのスタート! サービスリリースすらしておらず(一応ペライチのウェブサイトはあった)ザ・スタートアップという状態。

ソフトウェアエンジニアとして加入しましたが、もちろん2人チームなのでいわゆるフルスタックエンジニア。 HTML/CSS は得意ではないので、なんやかんや苦労しましたが、サービスリリースに必要な作業は全部やっていました。

とにかく色々頑張ってた時期なので、特に書くことがない……!

サービスリリースできたよ良かった!以上!

2Q

試用期間も終わり、採用活動にも参加するようになりました。

面接を受ける立場での英語も大変でしたが、面接をする立場での面接はもっと大変! 面接毎に上司に面接での評価(強み・弱み・まとめ etc.)を伝える必要があったのですが、英語力は高い方ではないので大変でした。

ちなみに、今でも面接は大変です。というか、英語力が社内でワーストなので、1年経った今でも毎日大変です。

採用活動については、ウチはなかなか面白いフローを利用しています。

  1. 候補者に API の URL を送る
  2. URL を GET すると API チャレンジ(簡単なクイズと答えの POST 先の URL)が表示される
  3. URL にプロフィールとクイズを POST する
  4. 1次面接
  5. コーディングチャレンジ(期限は1週間程度、主に再帰と並列プログラミングへの理解度チェック、もちろん設計力、実装力、可読性なども見る)
  6. 2次面接
  7. 最終面接

と言った感じです。候補者に URL に GET/POST させるところが面白いかなと思います。

このあたりのことが出来ないレベルだと、そもそも1次面接にたどり着くことすらないので、 この時点でそこそこ人数が絞られて効率が良いです。

コーディングチャレンジは習得が難しいとされる再帰と並列への理解度チェックを実務に即した内容で出しています。 ゴリゴリのアルゴリズム試験は特に必須技能じゃないのでしていません。というか、されてたら俺、落ちてたと思います。

このコーディングチャレンジでのコードの綺麗さ、入社後に上がってくるコードを見ると、当然ですが思いっきり相関があります。

どんなコードを書く人か予め知れるので、かなり良いと感じています。 まぁ、問題を作るのが難しいという問題はありますが、ウチのは今の所うまくいってるかなと思います。

そして無事3人を採用!ソフトウェアエンジニア(フルスタック)2人、フロントエンドエンジニア1人です。

念願のフロントエンドエンジニアが加入したので、そのフロントエンドエンジニアを筆頭にフロントエンドのモジュール化をこの時期は主に頑張っていました。

正確にはドイツ語版をドイツ向けにカスタムしてリリースするというプロジェクトが進行中だったので、 イギリス版と共通で使えるモジュールたコンポーネントを作成・切り出ししつつ、ドイツ版を作成する、という感じでした。

なので、事業としてのメインはドイツ版リリースです。

私が主に関わっていたのは、この「共通コンポーネント作成」の基盤づくりでした。 もう少し詳しく言うと、Ember addon の作成をしていました。変な落とし穴にそこそこハマりましたが楽しかったです。

コンポーネントを切り出すタイミングで、フロントエンドのテストはかなり充実させることができたのも良かったです。

3Q

イギリスの終了ビザをゲットしてロンドンにとうちゃーく!いやほーい!

フロントエンドのコンポーネント化も終わりキレイになったので、やっとこさ得意領域であるサーバーサイド業がメインに……と、思いきや、データ関連の作業が突如大量に必要になり、しばらく Python でゴリゴリデータ処理していました。

この頃は「データエンジニアはよ!データエンジニア早くきてくれー!」とボヤいたりしてました。 ボヤいてたら2人ほど採用が決まりました。やったね。

が、もちろんサーバーサイド作業、正確には API 周りの作業もゴリゴリしてました。

一番達成感があるのが、APIアーキテクチャをゴロッと一新したことです。 ここでのアーキテクチャは、Clean Architecture とかで指される範囲のアーキテクチャです。

サーバーサイドのコードですが、コアとなる部分は私の加入前に書かれており、

  1. Lambda のイベントハンドラとなるメイン関数(Lambda 特有の処理、エンドポイント固有の処理、ドメインロジック)
  2. 外部 API アクセスレイヤー
  3. データアクセスレイヤー

という構造になっていました。

1の責務がエライことになっており、Lambda とエンドポイントとドメインロジックが一塊となっていたので、 「このドメインロジック他でも使いたいんだよな~」となった際に、 「Lambda の呼び出しを擬似的に再現」するか「コピペ」するかという、なかなかロックな状態になっていました。

もちろん、ドメインロジックが切り出されてないので、テストもきっつい! HTTP リクエストを作りエンドポイントを直接呼び出すテストしかなかったです。

そこで、各メイン関数の標準化を行い、Lambda 特有の処理はデコレータで付与できるようにし、以下の構造に作り直しました。

  1. アプリケーションレイヤー(エンドポイント固有の処理、Lambda 特有の処理はデコレータで export 時に付与)
  2. ドメインレイヤー(ドメインロジックの集合体)
  3. 外部 API アクセスレイヤー(外部サービスへの処理をラップし、ドメインレイヤーが扱いやすいインターフェースを提供)
  4. データアクセスレイヤー(その名の通り、データベースのアクセスを担当)

この過程で、URL の標準化、各メイン関数の標準化など、色々同時に勧め、かなり全体を整えました。

これのおかげで各レイヤーごとのテストが書けるようになったので、ドメインロジックのテストが充実し始めています。

Q4

API の大規模リファクタリングが一段落したあと、史上最大(と言っても、ウチの会社出来て1年ちょっとだけどな!ワハハ!)の設計変更 + 機能追加と戦ってました。 早速の大型案件で、API 大規模リファクタリングの効果が早速発揮されることとなりました。

サービスリリース時は「どんなデータを入れるのかわからんので、とりあえず JSON 型のカラムいっぱい作っとく」というこれまたロックな思想で DB 設計されていたのですが、この設計変更 + 機能追加で、リレーショナルデータベースとしてより健全な形で設計し直されました。

この DB の変更でメインサービスの大体のものが壊れたので、ひたすら設計修正しながら動くようにしてました。 feature branch と master branch の差分、今確認したら +25,624 −19,403 でした。すげえな。

ちなみに、このとんでもなく巨大な feature branch ですが、今日の今日まで作業していて、年内最終出勤日に無事ちょうど終わりました。

年明けのリリースわくわくすっぞ。

アーキテクチャになってから最初の大規模機能改修 + 機能追加だったのですが、 今回追加された部分についてはドメイン層、データアクセス層、そしてエンドポイント単位の E2E テストをしっかり同時に追加でき、 この点でも新アーキテクチャの効果がしっかりと発揮されました。

また、API 大規模リファクタリング時には手を出せなかった細かい部分の標準化も同時にかなり勧めることができたので、この1年でかなりコードベースがキレイになりました。

「テストがないが最重要機能、かつ旧データ構造に依存」という爆弾みたいな部分にはまだ手を出せてないのですが、 コードをを変更せずゴッソリとモジュールとして切り出し、使いやすいインターフェースで包みアダプターを追加しておきました。

アダプターを追加したことで、爆弾に触れることなく新機能から使えるようにでき、かつ今後の爆弾処理では、

  1. 追加した新インターフェースに対するテストを書く
  2. 内部の関数を切り崩し、適切な単位でテストを書く
  3. 最後にアダプターを取り除き旧データ構造と完全におさらばする

というステップで、外側に一切爆風を出すことなく処理することができそうです。 2, 3 はパッと覗いた感じ大変そうだったので、早く1だけでも空きを見て済ませておきたいかなと思います。

そしてクリスマス・年末年始休暇へ突入!16連休やっほーい!

まとめ

上司が私を初期メンバーとして採用した理由の一つに「コードがキレイ。設計力に期待ができる。サービス立ち上げ経験もあり、今後の成長に向けたコードベースの土台作りに貢献できる。また、知識の幅が広く初期メンバーとして最適」というのが確かあったのですが、その期待に答えれた1年だったんじゃないかなと思います。

まだまだ課題は大量にありますが、サービスを成長させつつコードベースも成長させることに邁進していこうと思います!

英語力については、圧倒的に足りて無くて死にそうですが、死なないように頑張ります……リスニングと語彙、リスニングと語彙、リスニングと語彙……。

来年も楽しみながら頑張ろー!

ばいちっ。

*1:このスタックの使い方ってあってるのかな……?