見出し画像

多くのエンジニアに「Adacotechに入社したい」と思ってもらうために開発組織が取り組んだ事

こんにちは。私は現在自社開発を行いながら、株式会社アダコテックの新規クラウドサービス事業開発のPM兼開発者として参画させていただいています。

私がAdacotechから依頼を受けた当時、Adacotechはフロントエンドのエンジニアをリードできる人が不足しており、開発を牽引してくれるエンジニアを求めていました。

課題が明確で、自分の得意とするフロントエンドの開発を整えるというミッションに関してはすぐに役に立てそうだった事と、大学時代に機械学習を少し齧っていたので事業内容に興味を持てたこともあり、あまり迷わずお手伝いさせていただくことにしました。

今回はAdacotechの開発組織で働き始めてちょうど一年が過ぎたので、みなさんにAdacotechという組織を知ってもらうため、開発時のエピソードを交えつつAdacotechは開発組織を強くするためにどのような取り組みをしてきたか、また、どのような文化で開発を行なっているのかについてご紹介します。


ZenHubの導入

当初PM的な立場の人がおらず、締め切りまでにどれくらいのタスクが存在し、具体的な要件定義から実装設計を行い方針を立てる人がおらず、工数見積もりやタスクの可視化ができていなかったため、ZenHubを導入し、大枠のロードマップとタスクの見える化、工数見積もり、および実装の方針立てを行い、タスクがメンバーにちゃんと分散する仕組みを作りました。

最初は、フロントエンド、バックエンド、その他のサービスを分けて管理した結果、タスクが見辛くなったり、エピックの粒度が不規則であったり、仕様が不明瞭なままイシューが切られたり、テストの時のクローズルールが不明瞭だったりと、色々運用上に問題があったのですが、今ではプロジェクト上のEpicの立て方をルール化して運用してフィットしており、スプリントのサイクルに対して上手く適応できるようになりました。

画像2

現在のフローでは仕様書で仕様を定義=>エピック上で実装方針を指示する=>エピックに紐づくイシューを立てる=>イシューをPRに紐づけて実装が終わったらクローズ=>エピックをレビューパイプラインに移動させる=>動作検証環境で動作確認を行ったらエピックを閉じるというようなフローになり、今では効率的に実装からQAのサイクルを回せるようになりました。

画像3

Nuxt.jsからNext.jsへ移行・フルリプレース

Adacotechの開発に加わった当時のAdacotechのクラウドサービスのフロントエンドはVue.jsのNuxt.jsを使用して作っていました。この時、アプリケーションには以下のような問題点がありました。

・コンポーネントが適切に分割されておらず、ほぼ一つのページに全ての機能が入っていた
・Open APIを利用しているもののクライアントのgeneratorを利用していなかったためフロントエンドが送っているリクエストと要求されているリクエストのスキーマが異なるものがあり、開発者が何度も似たようなバグにハマってしまって生産性が低くなっていた
・度重なる仕様変更で利用がされていないエンドポイントが残ったままになっていた
・vuexのStateに対してコンポーネントからのサイドエフェクトや、computedによる双方向バインディングを許容するコードがありバグの温床になっていた
・vuexのStateとActionの対応関係が適切に分割されておらす、巨大なStateを引き摺り回し、多くのコンポーネントで不要なパラメータがpropsに渡され依存関係が把握しづらくなっていた。
・DBで本来統一的に扱える構造のデータのテーブルが用途の数だけ分かれており複数のAPIを分割して実行する仕組みになっていた
・当初のスケジュールに間に合わせるためにUXを考慮せずに作られたレイアウトがそのまま残ってしまっていた

そこで、一旦以下のリファクタリングを行いました。

・vuexをmoduleモードにして関連のあるstateとaction毎にstateを分割した
・typescriptを導入した
・storybookを導入してコンポーネントを分解した上でそれぞれカタログとして参照できるようにした
・vueのテストライブラリを導入した
・汎用的なコンポーネントをUIライブラリを作り別のリポジトリから切り出してNPM化する

この時、現状のアプリケーションはVuexをかなり複雑に実装してしまっていたことから、それを紐解きながら再実装をするコストとTypescriptとReactを用いてReduxに移行するコストがほぼ同じ程度であるという結論に至ったため、Adacotechのプロダクトの複雑性を考慮してTypescriptと親和性の高いReactへの移行を提案をしました。

一度機能をある程度作り切っているアプリケーションに対して本来、このような提案はチームとしてはかなり大変な意思決定だと思うのですが、Adacotechのチームは私の提案するリファクタリング後のメリットを理解して、尊重してくれた上で迅速に協力してくれました。

この時、それなりの規模の機能が出来上がっていた当初の思惑通りには行かず、難航した部分もありました。

特にスケジュールを優先するためDBの変更とフロントエンドの開発を非同期で行い、旧バージョンと、新バージョンの差分を作りながらリニューアルを行なっていた事で、結合時に壊れてしまったエンドポイントを修復するコストが高くついてしまいました。

また、当時、機械学習のジョブサービスおよび認証サーバのコンテナ化が進んでいなかったため、クラウド上のインスタンスに接続して開発していたため、ローカルでの動作確認が困難な状況でした。

当初はフロントエンド中心のリファクタリングの予定だったのですが、結果として、インフラやバックエンドの構成にも多く手を入れることになりました。

多くの困難があったのですがそれにチームとして立ち向かった結果、以下のように多くのノウハウや成果を得る事ができました。

・全てのフロントエンドのコードがTypescriptで書かれるようになった
・Dockerでクラウドのインフラを模倣し、ローカル環境で動作検証環境を作れるようにした
・StorybookによってComponentの作成タスクとページ作成タスクを切り離せるようにした
・Cypressの導入によってE2Eテストでコア機能のデグレがないか確認できるようになった
・AWSのシミュレータや自社サービスのコンテナ化を行うことでローカル環境で開発ができるようになった
・Databaseの負債が解消されSeedを作成したことによって、動作確認がスムーズになった
・Lint・Prettier設定を見直し、push前にコードフォーマットのチェックが入るようになった
・Swagger CLIとOpenAPI GeneratorによってOAS仕様管理yamlを分割可能にし、クライアントコードを自動生成する仕組みを作ることによって、フロントエンド側のリクエスト、レスポンス、urlの設定負担を減らした
・Atomic DesignやReduxによるコード規約を策定し、チーム間でコードの品質に差が出づらいような仕組みが出来た

これらを達成したことによりリプレース前の無秩序な状態から脱却し、現在では開発効率が大きく向上し、少数のチームメンバーでも高い生産性を維持できるようになりました。

生産性を高める取り組み

terrafromによるAWSリソースの管理

Adacotech
ではサービスに必要なインフラをterraformで管理しています。

./modules
├── alb
├── auth0
├── cloudfront
├── cloudwatch_alarm
├── cron-lambda
├── ecs-cluster
├── ecs-ec2-instance
├── ecs-guardian
├── ecs-service
├── ecs-service-ec2
├── ecs-service-simple
├── ecs-task
├── ecs-task-role
├── firehose
├── flowlog
├── front_and_domain
├── gw-ec2
├── redis-cluster
├── userdata-bucket
├── vpc
└── vpc-foreign

以上は、Adacotechで管理しているAWS等のインフラリソースを管理しているterraformのモジュールの一覧です。Adacotechではかなり多くの部分のインフラを1から再現できるように設計しており、手動によるAWSの操作をほとんど無くす事で運用のコストを大きく下げる事に成功しました。これによってチーム全体で多くの時間をコード開発の時間に費やす事ができています。

Storybook + Typedocでカタログとドキュメントを導入

Storybookを導入し、コンポーネントを管理するようにしました。また、これをS3にデプロイし、社内IPからエンジニア以外の方以外も閲覧できる仕組みを作っています。

スクリーンショット 2021-05-12 9.09.54

これによって、プロダクト開発からUI開発を切り離すことができたため、デザインタスクが終わったものから随時、開発に着手することができるようになり、開発効率が上がりました。

Open APIからクライアントを自動生成する

Adacotechが作っているAPIはOpen APIを元に作成しています。BackendではFlask上にAPIが実装されているかconnexionで検証しています。

画像7

また、Swaggerでドキュメントが確認できたり

画像8

Open API Generatorでクライアントの自動生成をしています。これによって、APIのリクエストやレスポンスの型を定義しなくても使えるようになり、コードの保守性が上がりました。

リリースサイクルを規則的にする

Adacotechではアジャイル開発を採用し2週間単位でのスプリント開発を採用しています。デプロイをステージングとプロダクションを1週間単位で交互に行っており、リリースサイクルをなるべく規則的に行うように努めています

スクリーンショット 2021-05-12 11.08.10

また、以下の図のように、リリース時に決まったフォーマットの情報でデプロイ時の手順を書き残し、デプロイ時に担当する人がメモを見ながら作業できるようにしてあります。

画像5

また、不具合などを記録し、重要なものはポストモーテムとしてNotion上に蓄積されるようにしています。

UXを高める取り組み

静的サイト + BFF構成

クライアントサイドでフロントエンドのCloudFrontを用いた静的サイト配信+BFF構成を採用しており、サーバダウンによるフロントエンドの配信不能リスクやFirst Contentful Paintまでのレイテンシを極力少なくしています。

マイクロサービス + マルチプロセスワーカーによる負荷分散

ECSタスクを用いたContainer Orchestration型のWebサービスを構築しているので、サービス負荷に対するスケーリングが可能な状態になっています。またCelery、Cloud SQS、ElastiCacheによって負荷分散を行なっており、ユーザーが大量にデータをアップロードしたり、機械学習の重い処理をワーカーに移譲することによって、ユーザーが操作を待つことなく操作を継続することができます。

ログ解析基盤による障害ログの早期発見・アプリケーションのPit fall検知

Fluent bitからkinesisログストリームにログ配信を行うことによってAthenaやRed Shiftでのログ解析を可能にしています。これによって障害発生から、原因特定まで迅速に行えるようになりました。

属人化させないための取り組み

デプロイの持ち回り制

デプロイを持ち回り制にしました。GitHub Flowに従い、branchからタグを切るとSTGのデプロイが行われ、masterにマージするとデプロイが走るという構成を整えています。

画像4

また、開発環境や本番環境にアクセスするBatsionをチームメンバーにアクセスできるようにしており、メンテナンスモードで本番環境の接続をメンテナンスページに変更し、メンテナンスが終わった後に元に戻す仕組みを数回コマンドを実行するだけで実現しています。

これによって、新しく入ってきたメンバーであってもインストラクションに従えば簡単にデプロイができるようになりました。

実際にジョインして1ヶ月経たないメンバーにデプロイを行っていただいた際もミスなくデプロイが行えました。

これによりデプロイに対する心理的負担が減り、メンバーが障害時に落ち着いて対処できるようにしています。

任せる文化

Adacotechは手を挙げた人に任せる文化があります。私の得意な領域は主にフロントエンドの実装になるのですが、インフラの構成を理解するためにterraformのリポジトリを見ながら触らせてもらっていいか尋ねた所インフラも一部作業をさせていただけることになり、現在も多くの事を学ばせていただいています。

これが可能だったのはAdacotechのAWSアカウントはスイッチロールを前提としたOUをきちんと構成しているので、安全に権限を開発メンバーに渡せるようにしてあった事も一つの理由です。

また、フロントエンドエンジニアの方にもバックエンドのタスクをお願いしたり、その逆も行いながらチーム全員が横断的にプロジェクトで使用している技術に関する知識を得てもらいながら個人の出来る領域を広げていってもらっています。

このようにAdacotechは挑戦したい人には専門領域ではなくても仕事を任せる文化とそれを実現できる環境があります。

これは人によっては大変だと思う方もいるかもしれませんが、エンジニアとしてキャリアを築いていくための大きな武器になるはずです。私自身も「Adacotechで1年以上働いたエンジニアはどこの会社へ行っても通用する」と思っていますし、入社された方にも外部の会社の方から見てもそう思ってもらえる環境を作っていくことを目指しています。

エンジニア組織強化のための取り組み

定例会

週に1回ずつSprintの計画MTGと進捗確認MTGを行なっています。計画MTGでは、スプリントの開始時にスプリントで目指す目標の確認と、進捗確認MTGでは現在までの進捗を確認してステージングまたはプロダクションにデプロイする成果物を確認するMTGになります。また進捗確認MTGでは月1で次の項のレトロスペクティブを行なっています。レトロスペクティブで上がった課題は進捗MTGで確認しています。

レトロスペクティブ

レトロスペクティブではスプリント中にあった出来事についてよかった事、問題だった事を共有し合います。その後、チームとして継続していきたい事や、取り組むべき課題を設定し、チームの問題の早期発見や解消のサイクルを早めるために役立てています。

画像10

振り返りの時間に各々のTry進捗状況の確認を行うためのボードがあったり、problemやkeepのリストが一覧できる仕組みを整えているので、新しく入った方にも今までの出来事やどのような知見が溜まってきたかを一覧できるようにしてあります。

スクリーンショット 2021-05-15 16.25.00

以下の図のように用途に応じてカードを用途に応じてフィルタリングしたビューを作成しています。

勉強会

Adacotechでは月1、2回程度の自由参加の勉強会を開いています。
領域を横断して知見を共有することで自分たちの事業で用いている技術やツールに対する理解を深めています。

オンライン上でZoom配信をして録画してあるので、参加していなかった方も後で見返す事ができるようにしてあります。

過去のトピックについては

・Adacotechが扱っているHLAC特徴量による画像異常検出の手法について
・ゼロ知識からReactを始めるための開発までのステップについて
・AWSのパラメータ最適化のための機械学習サーバの動かし方
・Blenderを用いた物体の異常検知シミュレーション

などを取り上げました。

開発メンバーの外部の勉強会やイベントへの積極的な参加

Adacotechは外部のイベントへの参加を積極的に行なっています。

表彰実績など

Adacotechは外部の表彰実績があります。2020年度のCTO of the year候補にノミネートされたり、AWS様のブログに採用事例を取り上げていただきました。

エンジニア採用の取り組み

Adacotechでは1 day internという形で実際にAdacotechの開発者と課題をペアプログラミングしながら解いていただくという形のコーディング試験を設けることがあります。

Adacotechに対して開発のカルチャーや要求されるスキルのレベルを感じてもらい入社前と入社後のギャップを埋める事が一番の目的なので、応募者の方にはなるべく普段の開発に近い形で取り組んでもらえるようにしています。

参加された方からは、自分の知らないツールやアーキテクチャに関して教えていただいて勉強になった、チームでどのように開発を行なっているのかイメージがついてよかったなどの意見をいただいています。

こうした取り組みで入社前にAdacotechで組織をよく知ってもらい、組織として一緒に働いていただける方にはAdacotechで働く事に懸念やミスマッチがない事を納得していただいた上で入社していただけるように注力しています。

We are hiring!

ここまでAdacotechの組織の取り組みをご覧いただいてありがとうございます。ご覧いただいた通りAdacotechは数多くの組織改革に取り組み、挑戦を積極的に行なっており、会社として組織を作っていく面白いフェーズです。

現在Adacotechでは組織として成長していくために、一緒に組織を動かしながら、働いてくれるメンバーを募集しています。もし、興味があればHPのリクルートページの職種別応募フォームよりご応募していただければと思います!

この記事でAdacotechという組織に興味を持っていただけたら幸いです。

この記事が気に入ったらサポートをしてみませんか?