新卒エンジニアが配属後3ヶ月間で学んだ事 ~ 開発・ユーザ・ビジネス の理解 ~

新卒エンジニアが配属後3ヶ月間で学んだ事 ~ 開発・ユーザ・ビジネス の理解 ~

このエントリは全9回を予定する18卒新人ブログリレーの第5回です。

はじめまして。リクルートテクノロジーズ新卒1年目の西野拓馬です!

入社後の研修を経て、7月からリクルートテクノロジーズのプロダクト開発のチームに配属されました。

今回は、新卒エンジニアとしてプロダクト開発現場に配属され約3ヶ月の間何に取り組み、そこから何を学んだかについて紹介したいと思います。

  • リクルートテクノロジーズの新卒エンジニアは何を経験し、何を学ぶのか?
  • 新人はチームにジョインした時にどういうことを感じ、何に苦戦するのか?

こういった問いを持つ読者に、少しでも参考になれば幸いです。

以下が本記事の構成になります。

はじめに

私がプロダクト開発者として参考にしているものの1つに「プロダクトマネジメントトライアングル」と呼ばれるグラフィックモデルがあります。

出典:https://productlogic.org/2014/06/22/the-product-management-triangle/

この「プロダクトマネジメントトライアングル」は、プロダクトをマネジメントしグロースさせるには、開発・ユーザ・ビジネスの三つの要素の理解とマネジメントが重要であり、それをモデルとして表したものになります。詳しくはこちらの翻訳記事をご覧ください。

この3ヶ月間、エンジニアとしての「開発」だけでなく、「ユーザ」や「ビジネス」の理解まで染み出し取り組んだ結果、

プロダクトをグロースさせるためにはどうすれば良いか?

という問いに、より俯瞰的な視点で考えられるようになったと感じています。

そこで今回、この3ヶ月の取り組みを、開発・ユーザ・ビジネスの3つの観点にわけて紹介していきたいと思います。

配属チーム

私の配属されたチームの開発するプロダクトは市場とともに急成長しており、web・ネイティブアプリ(iOS/Android)ともに日々高速な改善が求められています。モバイル開発がしたい!という私の希望から、まずはAndroidアプリの開発の担当をすることとなりました。

また、開発チームでは、アジャイルソフトウェア開発手法の1つである「スクラム」で開発を行なっており、エンジニア、デザイナー、QAエンジニア、スクラムマスター、開発リーダー、PO(プロダクトオーナー)、PM(プロダクトマネージャ)でチーム構成されており、2週間のタイムボックスでスプリントを回しています。

開発

ここでは開発者として取り組んだことと、そこからの学びを紹介します。

参考:入社までの開発経験

学生時代は京都のスタートアップにて少人数チームでwebアプリケーション(React/Redux, Ruby on Rails)開発をしていました。

Android未経験からの技術のキャッチアップ

まずはAndroidエンジニアとしてスタートすることとなりましたが、Android開発が未経験だった私は、Androidエンジニアとしてまずは自走できるレベルまで立ち上がる必要がありました。

ここでは、約1ヶ月間でのキャッチアップ〜開発チームに入るまでのプロセスを紹介します。

1. Android立ち上げメソッド(1週間程)

まずは、社内で代々受け継がれているAndroidの技術について網羅的にまとまった教科書のようなものがあるのですが、それを一周ざっくりと読み、その後理解度チェックシート(これも社内で受け継がれているもの)で確認をします。これを1週間ほどで終わらせ、Androidに関する基礎的な知識をインプット&脳内indexを作りました。

2. 課題アプリケーションの作成(1週間程)

Androidの基礎的インプットを終えたあとは、実際に課題アプリ(簡単なフォームと画面遷移を要件としたアプリ)を実装します。実装したアプリに対し現場のメンバーからレビューをもらい、実際にマージできる品質になるまで修正を繰り返していきました。

3. 過去行った案件の開発(2週間程)

課題アプリ実装を終えた後は、実際のプロダクトのソースコードに対して開発を行います。といっても、実際の開発チームに入って開発するのではなく、過去に実装された(既にマージ済み)案件を開発していきます。案件実装前のブランチを切り、実際の開発フローで開発を行い、レビュー&修正を繰り返します。この時、なるべくプロダクト構造全体を把握できるよう、なるべく影響範囲が広く実装難易度の高い案件を選択しました。

4. 実際の開発チームに入る

約1ヶ月間の立ち上げ期間の中で、Androidエンジニアとして最低限の基礎知識を身につけ、実際の開発チームに入りました。

web開発経験しかない自分にとってAndroidを学ぶ上で戸惑ったポイントがいくつかありました。例えば以下のような点です。

・List表示の手順の多さ

List形式で表示するための手順の多さに驚きました。Adapterなど1度読んで理解した気にはなれど、いざ実装するとなると思うように手が動かず最初は苦戦しました。

・アプリケーションの状態の管理

画面の回転時やバックグラウンド時など、web開発よりもアプリケーションの状態や状態の変化への対応など、考えることが多く複雑に感じました。逆にそれらの状態に沿った挙動を実装するのが楽しいとも言えます。

・APKファイルの容量

容量の大きいアプリは、アンインストールの対象となる可能性が高くなる、またそもそもダウンロードしてもらえない可能性があるので、画像やライブラリの追加時にはどれくらい容量に影響するかも考慮しなくてはなりません。

これら以外にも戸惑ったポイントは多々ありましたが、とにかく実際に手を動かして、実装していく中で理解していきました。また、既存のAndroidプロダクトのソースコードを読む時はActivityやFragmentの継承ツリーを実際に紙に書いていき、それぞれの階層でどのような処理をしているのかをまとめて理解を深めていきました。

開発に入ってわかった技術的負債

そして、実際のスプリントで開発を進めていく中で、Androidプロダクトが複数の技術的負債を抱えていることがわかりました。

Androidプロダクトはもともと外部委託により開発されていたものを数年前に引き継ぎ、自社で差分開発を行なってきました。そのため、もともと引き継ぎ時から負債を抱えていたことに加え、設計・実装した開発者とコミュニケーションを取ることができないため設計意図や実装理由などがわからない箇所が複数あり、技術的負債を抱えやすい状態でした。

絡み合う依存関係

Androidプロダクトでは、複雑な依存関係により、ある変更に対して思わぬ影響が出てしまったり、軽微に見える改修が大規模な改修となってしまったりすることがありました。

そこで、どれくらい依存関係が複雑になっているのかをこちらの可視化ツール(https://github.com/alexzaitsev/apk-dependency-graph)を用いて可視化してみることにしました。以下の図が実際の依存関係を可視化したグラフになります。

左のグラフが当時のAndroidプロダクトの依存関係を可視化したもので、右のグラフが綺麗なアーキテクチャで実装されたソースコードを可視化した時のグラフです。

左のグラフではクラス同士が密に結合しあって関心が分離できておらず、非常に管理の難しい状態であると言えます。

多重継承問題

また、複数の箇所で深い継承関係を持つクラスが見られました。以下の図は実際のソースコードにある継承ツリーで、7段にもわたって継承されているフラグメントも存在していました。

「この時はこのFragmentを継承する」といったルールを元に実装されてはいるものの、ビジネス要件によってそのルールはすぐに破綻してしまいます。そういった時に無理にメソッドをオーバーライドして対処したり、親から新たな継承を作ったりすることでさらに複雑化していきます。そして大元のFragmentは影響範囲が大きすぎて誰も手をつけられなくなっていました。

FatなActivity

そして、巨大すぎるActivity問題です。

Activity内で様々な処理(通信処理のハンドリングやviewの状態管理など)を行ってしまうことによって、巨大で複雑なActivityとなってしまっていました。巨大なソースコードは可読性を低下させ、様々な処理が1つのActivity内で行われておりデータや処理の流れが全く読めない状態でした。

開発速度の低下

これらの負債により、可読性・拡張性は著しく低下していました。

可読性・拡張性の低下は、軽微な改修に見える案件にも見積もり以上の時間がかかってしまったり、私含め新しくチームにジョインしたメンバーがソースコードを理解するまでに多くの時間を必要としたりするなど、複数の問題を引き起こしていました。

技術的負債とは?

そもそも負債とは何なのか?

フィリップ・クルーシュテンは「技術的負債」についての議論の中で、「見える・見えない」「プラスの価値・マイナスの価値」の2つの軸によるマトリックスを定義し、「マイナスの価値」×「見えない」領域を「技術的負債」と捉えました。

出典:https://resources.sei.cmu.edu/asset_files/WhitePaper/2012_019_001_58818.pdf

この「見える・見えない」とは、経営者(プロダクトオーナーやビジネス組織)の視点から表面的な機能を見たときに発見できるか・できないか、という意味です。

「バグ」はマイナスの価値ではあるが経営者が「見える」ため、それについてどう扱うか大きな問題にはなりません。つまり、経営者側から見えて管理できる状態であればあとは開発者と工数を見積もり、優先順位をつけるなどの対処(開発者と経営者とのコミュニケーション)ができるようになるのです。

一方で、「技術的負債」は経営者からは見ることができません。つまり管理もできなければ、開発者と同じレベルでコミュニケーションを取ることもできないのです。そのため、開発者としては処理したい「技術的負債の解消」というタスクに対して、経営者はそのメリットや効果がわからないために、議論が発散してしまうなどの問題が起こります。

技術的負債の解消に向けて

では、技術的負債を解消していくにはどうするべきか?

それは「見えない」を「見える」に変えることが重要になります。つまり技術的負債を何らかの方法で可視化・定量化し経営者と開発者がコミュニケーションできる状態にすることです。

そして技術的負債の可視化については「エンジニアリング組織論への招待」のp.265で次のようにまとめられています。

この図では、技術的負債を可視化するには「エンジニアは知っていて経営者は知らないこと」、「経営者は知っていてエンジニアは知らないこと」を解消していくこととが重要で、それぞれの方法の具体例を示しています。

私たちのAndroidプロダクトにおいても、課題を可視化・定量化し、開発工数を鑑みて優先度の高い順に負債の解消・改善を進めております。

まず課題の可視化においては、開発速度を落としている複雑な箇所を洗い出し、負債によってどれくらいの余分な開発工数がかかっているかを推定しPOやPMとも共有します。次に、負債の種類を普段の機能開発の中で段階的に改修していけるものと「負債解消」という特別なタスクとして用意するレベルのものを分けます。あとは、開発工数や事業フェーズ、人的リソースなどを鑑みPO・PMと相談しながら、それらの負債を解消していきました。

以下が実際に行った負債解消の取り組みです。

・MVVMアーキテクチャへの移行

現在、もともと開発者独自のアーキテクチャだったものを、段階的にMVVMアーキテクチャへ移行しています。MVVMアーキテクチャでは、通信と画面状態の管理はViewModel内で行い、Activityは画面描画と画面遷移に徹すればよいので、Activityもすっきりと書け、データの流れもわかりやすくなりました。これにより、FatなActivityも少しずつ減らすことができ、複雑性の低下、バグの減少につながりました。

・Kotlin化

以前は全てjavaで書かれていましたが、新規実装時にはKotlinで書くように、また既存コードをKotlinに変更していきました。その結果、Javaと比べてコード量は減るため可読性が向上しました。また、KotlinのNull安全な言語仕様によりNullPointerExceptionが発生する可能性をコンパイル段階で排除できるため、クラッシュ率の削減にも繋がりました。

・独自カスタムライブラリの排除

例えば、画像の通信周りの処理では、開発者が独自にライブラリをカスタムしたものが使われていました。これにより、新しくジョインしたメンバーなどが、内部でどんな処理が行われているのか理解するのに余計に時間を要してしまっていたこと、また、パフォーマンスの低さや扱いづらさなど、多くの問題がありました。そこで、独自でカスタムされたライブラリをなるべく排除していきました。

これらの取り組みにより、ソースコードの複雑性が低下し開発速度が向上しただけでなく、アプリクラッシュ率が負債解消に取り組む以前は約5%あったものを約2.5%にまで削減することができました。深い継承関係を持つような手のつけにくい部分など、まだまだ着手できていないところは多く残っていますが、今後も課題を可視化・定量化しながらプロダクト改善&負債解消を続けて行く予定です。

学び

そして、負債と向き合う中で、今となっては複雑なシステムではあるが、当時の要件やAndoroidを取り巻く環境を想像しながら読み解いていくと、ある意味ではよく共通化・設計されているなあとも感じる部分も多々ありました。つまり当時のビジネス要件やAndroidをとりまく技術を考えるとベストを尽くしていた痕跡がありました。

ユーザのニーズに高速に対応して行く中でかつての設計が崩れていく様を想像しながら、

  • 当時の状況で自分ならどう実装できたか?自分も同じように実装したのではないか?
  • プロダクトの改善・運用をして行く中で今後どう負債を解消していけるか?
  • 今ベストなアーキテクチャと思っていてもどういう状況から負債になりうるか?

など、多くのことを考えさせられました。

そこから、現在の実装では以下の点に特に注意して実装しています。

・シンプルに作ること

  • YAGNI原則KISSの法則に従い、今必要な機能をシンプルに作ること。なるべく複雑性を排除し、誰が読んでもすぐに理解できるシンプルなコードを書くよう心がけること。

・どういう要因によって負債となりうるか

  • 完璧な設計はなくどんなコードもいつか負債となりうることを前提として、どういう要因によって負債が生まれうるかを考えておく。チーム人員の変更または増減、開発体制の変更、予想外の機能追加など、あらかじめ注意しておくべきポイントを押さえ、その時々には注意して実装をする。

技術的負債と向き合う中で、負債の捉え方、対処方法、また負債を生まないために気をつけることなど多くの学びがあったと実感しています。

Androidの負債解消やアーキテクチャ設計に関しては「Android アプリ設計パターン入門」という本が大変参考になりましたので、ぜひ参考にしてみてください。

ユーザ

ここではユーザ理解について取り組んだことを2つ紹介したいと思います。

カスタマーサポート対応から得た学び

まず、カスタマーサポート(以下CS)対応についての紹介です。

私たちのサービスではCS対応チームと開発チームが連携し、複雑な問い合わせや技術的な調査が必要な場合は開発チームが対応しています。

私もいくつかの技術調査の必要なCS対応をさせていただきました。対応のフローは主に以下のようなプロセスで進んで行き、各プロセスにて気づきや学びがあったので紹介します。

1. ログ・DB調査

ここでは、ユーザからの問い合わせに対して、実際にユーザがとった行動を確認するためにログやDBの調査を行います。ログやDBの調査を通して、システムの詳細(課金周り、テーブル設計、ログ収集周りなど)を把握することができました。

2. ユーザ行動の推定

ログやDB情報と問い合わせ内容からユーザの行動を想像・推定する必要があります。また、なぜユーザはここがわからなかったのか、または誤解をしてしまったのかを考え、想定通りの行動に促せなかった理由を探り、UI/UX改善の提案に至る場合もありました。

3. 説明・返答

実際に開発側で原因や解決策が判明した時には、それらをカスタマーに伝える際にわかりやすく伝える必要があります。普段、エンジニア同士でのコミュニケーションでは当たり前に用いている用語なども、噛み砕き説明する必要があるので、人にわかりやすく伝える力が向上したと思います。

また、ユーザの不満や不明点がCS対応チームに集まることを実感し、プロダクト改善の仕組みを考える上でCS対応チームとの連携がいかに重要であるかを実感できました。新卒エンジニアがCS対応に取り組むメリットは、ZOZO Technologiesさんの「新卒エンジニアがカスタマーサポートを一度は経験しておくべき6つの理由」というブログ記事によくまとまっていますので参考にしてみてください。

ユーザビリティテストをするメリット

次にユーザビリティテストについての紹介です。私たちのサービス開発チームではユーザビリティテストを実施しています。

ユーザビリティテストとは、実際に私たちのアプリを使ったことがないユーザに体験していただき、現状のプロダクトに関する率直な意見をもらったり、検討段階の機能を使っていただき反応をテストしたりするものです。

  • 実際にスマホをどのように持って、どのような操作で触っているか。
  • 検索軸の設定はどういう順番で行なっているか。(検索軸の優先順位)
  • どこを注目してみているのか。(スクロール速度の変化や画面での待機時間など)
  • 使いにくそう、操作に戸惑いを感じている箇所の発見。
  • 機能の誤解。

などなど、ログなどから分析しにくい部分も実際に見えたことです。

また、ユーザビリティテストの大きなメリットと感じたのは、プロトタイプ(デザインと画面遷移のみなど)を用いて、新機能に対するユーザの反応を検証できることです。アイデアからデザインに落とし込んで行く過程に「検証」を挟むことによってイテレーション化し、最低限の開発リソース(プロトタイピング)でアジャイルにデザインを磨き込むことができます。

出典:https://note.mu/tsumujikaze/n/n8b5f9cfec2c9

ユーザまたは市場に対する不確実性(リリース後にユーザは新機能を使ってくれるのか、または使うにあたっての不満はあるかなど不確実なこと)が大きい施策や案件の場合、上記の図のように、デザイン段階で「検証」をすることで不確実性を下げてから実装に入ることができます。上記のようにデザイン段階もアジャイル化する開発の重要性については、noteに投稿されている「なぜモダンなプロダクトチームによるリーンなプロダクト開発が必要なのか」という記事も参考にしてみてください。

ビジネス

最後にビジネス理解について取り組んだことを2つ紹介したいと思います。

KPIの理解

まず、KPIのインプットと理解をしました。

PO,PMなどへのヒアリングや分析資料などを元に、売上から分解した時のKPIツリー(要素と関係性)のインプット&理解しました。

・ 要素・・・KPIツリーの各要素の現状の数字と目標数字とその数字はどれくらいまで上げられるのかの勘所。

・ 関係性・・・KPIツリーの各要素の数字が上がるとどの要素の数字が上がるのか?もしくは副作用として下がる可能性があるのかなどの勘所。

これらのインプット&理解とPO/PMとの会話を通して、ビジネス側の現状や目標を理解することができたため、その後の施策を進める時のコミュニケーションなどがよりスムーズになりました。また、各重要指標の数値をインプットをしたことにより自分の中で1つの数値基準ができ、施策内容の見立てや分析結果などがより理解できるようになりました。

また、「自分の実装した機能によって〇〇の数値が△△くらい上がり、結果的に□□くらい売り上げに貢献するかもしれない」などビジネス的な効果を意識しながら開発できるようになりました。さらに、開発要件に対するビジネス背景・目的を意識することで、開発タスクの中で「このKPIの向上が目的なら〜のような実装にした方がいいかもしれない。実装は簡単なので〜の実装にしておきますね。」など、開発要件から漏れてしまうような小さな仕様などを提案できるようになりました。

競合を知る

次に、競合を知ることについてです。

市場には数多くの競合が存在しています。市場で勝ち残っていくためにも、競合を知り、優れた面は取り入れ、劣っているところは改善していかなければなりません。

競合を知るにあたり、以下のことに取り組みました。

  • 社内で調査された競合調査の資料を読む
  • 自分でも実際に競合アプリを利用して、機能やUI/UXを観察・調査する
  • それらを比較し、ユーザ層の違いやアプリの特性を知る

上記の取り組みによって、競合と比べた時の私たちのサービスの強み・弱み、業界のトレンド、各サービスのポジショニングなどが感覚として掴めました。今後グロースさせるには市場でどのポジションを狙っていけば良いか、デザインはこういう風にした方がイケてるのではないか、広告ではもっとここをアピールすべきではないか、など市場や競合を意識できるようになりました。

おわりに

以上、開発・ユーザ・ビジネスに関してこの3ヶ月間の取り組みの紹介でした。

これらの取り組みにより、普段の開発の中でもビジネスとユーザを意識した開発ができるようになり、

プロダクトをグロースさせるためにはどうすれば良いか?

という問いに、より俯瞰的な視点で考えれるようになったと感じています。

今後も技術を磨くとともに、様々な課題に対し真のボトルネックを見つけ、プロダクトをグロースさせる上で全体最適となる解を出せるようになりたいです。

最後になりましたが、本記事が皆さまにとって何か少しでも知見を提供できれば幸いです。ここまでご覧いただきありがとうございました。