マネーフォワード サマーインターン体験記
これはなに?
この記事は、マネーフォワードのサマーインターンシップに参加した後に書いた体験記です。このインターンシップは実務型で、実際の現場に入って社員さんとともに2週間働くという内容です。このインターンシップを通して、実際に何を行なって、どのようなことを学んだのかを書いています。
自己紹介
大学院でCSを専攻している学生です。今まで、実務型のインターンには参加したことがなく、このインターンが初めての実務型インターンとなります。開発経験としては、大学の授業、研究活動、個人開発などです。個人開発では、ReactとNode.jsを用いて、まんからというボードゲームを作っています。
参加までの経緯
マネーフォワードのサマーインターンシップに参加した経緯としては、就職活動の一環でサマーインターンシップに参加しようと企業を探していた中で、たまたま見つけたのですが、強いて言えば、実務型のインターンを探していました。マネーフォワードのサマーインターンシップに参加するためには、コーディングテストを受ける必要があり、スタンダードコースとチャレンジコースがあります。私は、スタンダードコースには落ちてしまったものの、チャレンジコースの方で受かりました。そのため、問題によって解きやすい解きにくいは人それぞれだと思うので、もしスタンダードコースで落ちてもチャレンジコースを受けてみて欲しいです。
サマーインターンシップに参加する前の目標
サマーインターンシップに参加する前に、インターンでの経験をより良いものにするために、事前に目標を立てていました。
エンジニアとしての業務体験
今まで、実際の業務を体験したことがなかったので、実際、どのようなことをしているのか、普段の開発との違いなどを知り、今後に活かしていくことを目標としていました。
技術力の向上
まだまだ技術力として足りていないところはあるし(当たり前)、経験を積んで、技術力をあげることを目標としていました。
キャリア観の見直し
自分の中で、なんとなく色々な技術を知っていて、色々な事ができる人になりたいとは思っていたものの、具体的なところまでは決まっていなかったので、色々な価値観を取り入れつつブラッシュアップしていくことを目標としていました。
タスクの概要
今回配属された部署であるフロントエンド推進部では、マネーフォワードにある様々なプロダクトで使われているUIに一貫性を持たせ、効率よく開発できるようにするための横断的な部署です。そして、この部署では、この目的のために、MFUIというWebプロダクト向けの共通UIライブラリを作成しています。その中で、今回行ったのは、MFUIにおける新規コンポーネント(Accordionコンポーネント)の開発です。このAccordionコンポーネントは実際に他プロダクトから欲しいと要求されたコンポーネントでした。Accodionコンポーネントとは、デザイン図に示しているもので、主な機能として以下の機能を保持しています。
- ユーザはトリガーをクリックすることでコンテンツの表示を切り替えることができる
- ユーザはAccordionを個別に表示を切り替えることができる
- ユーザはコンテンツエリアに任意の要素を配置することができる
このタスクを聞いた時は、めちゃくちゃ難しいわけではなさそうだなと感じたものの、今まで実装したことのないもの(テストケースやストーリー)などもあったので、少し不安もありました。
リリースまでの過程
タスクに着手してからリリースまで、以下の工程を実施しました。
- Design DocとPoC開発
- チームメンバーとのDiscussion
- Discussionをもとに設計の再構築
- 実装とPR作成
Design DocとPoC開発
まず、Accordionコンポーネントを実装する前に、設計をどうするかを考えました。
ここでの設計とは、
- Accordionコンポーネントはサブコンポーネントに分けるのか
- 分けるとしたらどのように分けて名前はどうするのか
- それぞれのコンポーネントに必要なInterface(props)は何か
- 実際に使う際のUsageはどうなるか
- 実際にリリースするまでの計画はどうするか
などを考えることです。
実際に、3個ほど設計案を考えました。長くなりすぎるので、Interfaceの部分は割愛し、UsageとComponent Structureを以下に示します。
- Suggestion1
Usage: <Accordion> <Accordion.Item> <Accordion.Trigger>label</Accordion.Trigger> <Accordion.Target>body></Accordion.Target> </Accordion.Item> <Accordion.Item> <Accordion.Trigger>label</Accordion.Trigger> <Accordion.Target>body></Accordion.Target> </Accordion.Item> </Accordion> Component Structure: Accordion └── AccordionContext.Provider └── children (user-defined) └── Accordion.Item (multiple) ├── AccordionItemContext.Provider ├── Accordion.Trigger │ ├── FocusIndicator │ └── button │ ├── Typography │ └── Icon (Expanded/Collapsed) └── Accordion.Target └── div (content)
- Suggestion2
Usage: accordionList = [ { trigger: "label", target: "<></>" }, { trigger: "label", target: "<></>" } ] <Accordion accordionList/> Component structure: Accordion └── accordionList.map() └── AccordionItem (multiple) ├── AccordionContext.Provider ├── Accordion.Trigger │ ├── FocusIndicator │ └── button │ ├── Typography │ └── Icon (Expanded/Collapsed) └── Accordion.Target └── div (content)
- Suggestion3
Usage: accordionList = [ { trigger: "label", target: "<></>" }, { trigger: "label", target: "<></>" } ] <Accordion accordionList/> Component structure: Accordion └── div └── accordionList.map() └── AccordionItem (multiple) ├── div ├── FocusIndicator ├── button │ ├── Typography │ └── Icon (Expanded/Collapsed) └── div (content)
最初はもう少し違ったのですが、PoCを開発したり色々とチームメンバーからアドバイスをもらいながらこの形になりました。そして、自分の中では、以下の理由でSuggestion2がいいのではないかと考えていました。
- Suggestion1と比べて、Listで管理することで、冗長になったとしても分かりやすい
- Suggestion3と比べて、コンポーネントが適切に分けられており、Reactの考え方に合っている
チームメンバーとのDiscussion
MFUIの開発メンバーの中には、Money Forward Vietnamのメンバーもいるので、Vietnamメンバーも含めて、3個の提案をもとにどの設計がいいかを英語で議論を行いました。
その中で、以下に示すような今まで考えられていなかった様々な観点を知ることができました。
- 拡張性
- パフォーマンス
- 保守性
- ユーザビリティ
- 一貫性
- 提供の仕方
具体的なところだと、
- 今回提供するのは、Accordionコンポーネントだけではなく、ライブラリとして提供しているので、ユーザビリティの観点として、一貫性の部分も必要である
- 経験則的に、Accordionコンポーネントに求められると予想される拡張性について考える必要もある。また、その拡張性に対応するために、どこでステートを管理するべきかなどの設計についても考える必要がある
などの意見が挙げられました。これらの観点は、Design Docを作成している時には出てこなかった観点も多くあったと思います。
Discussionをもとに設計の再構築
Discussionの結論としては、他のコンポーネントとの一貫性を尊重した上で、基本の形としてSuggestion1がいいいのではないかという結論になりました。
そして、Suggestion1を基本の形として、どの程度のスコープで提供するのか、コンポーネントの名前はどうするのか、それぞれのpropsのstateをどこで管理するのかなどを、Discussionで得られた観点をもとに考えました。最初は、どの設計がいいのかというのを頭の中で考えていても分からなかったので、チームメンバーとの話し合いながらアウトプットしていく中で、明確化されていきました。
例えば、Accordionとして提供するスコープとして、1-A、1-Bのどちらの方がいいかを考えました。
1-A: Accordionをリスト全体のコンポーネントとして提供する
<Accordion>
<Accordion.Item>
<Accordion.Trigger>label</Accordion.Trigger>
<Accordion.Target>body></Accordion.Target>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>label</Accordion.Trigger>
<Accordion.Target>body></Accordion.Target>
</Accordion.Item>
</Accordion>
1-B: Accordion.Item単位で単一のコンポーネントとして提供し、別途AccordionListのようなラッパーコンポーネントを提供する
<Accordion>
<Accordion.Trigger>label</Accordion.Trigger>
<Accordion.Target>body></Accordion.Target>
</Accordion>
<AccordionList>
<Accordion />
<Accordion />
</AccordionList>
そしてこの2パターンのPros/Consを考えた結果、1-Bの方が、ユーザがこのコンポーネントを使用する際に、複数のAccordionを実装したい場合はAccordionList、単体のAccordionを実装したい場合は、Accordionを利用すればいいというのが、名前的にわかりやすく、使用用途が分けれられるという点でも良いのではと考えました。
しかし、Accordionで管理しているPropsをAccordionListでも管理したい場合が考えられます。その際に、どちらのPropsを優先するのかという問題が生じ、結果的にAccordionListとAccordionの間に依存関係を生じさせてしまいます。これは、今後の保守性を考えた時に、1-Aと1-BのUXの違いにより得られるメリットよりも大きなデメリットとなってしまいます。そのため、1-Aの形で提供することにしました。
また、今後の拡張性を考えて、どのstateをどこで管理するのかなどについても考えました。例えば、Accodionが開閉しているか、していないかの管理を最上位のコンポーネントで管理することで、今後、複数のAccordionが開閉することを許可するのかしないのかについても対応しやすくなります。
このあたりで、コンポーネントを開発する際の設計の重要さについて実際に体感しました。
実装とPR作成
実際の実装段階では、もともと作っていたSuggestion1のPoCを改良していく形で実装を行いました。実装の際には、JSDocをそれぞれのコンポーネントやPropsごとに書いていくのは初めてで良い経験になったと感じています。
また、コンポーネントの実装に合わせて、ユニットテストの作成、ストーリーの作成などを行いました。
テストケースの作成に関しては、初めてだったので、どの程度の粒度で作成すれば良いのかをチームメンバーに教えてもらいながら学ぶことができました。
PR作成の際には、changesetを用いたバージョン変更についても学ぶことができました。また、チームメンバーによるreviewでは、MFUIで決まっているルールなどについて理解することができました。
そして、reviewをもとに修正を行い、実際にリリースまで行いました。
以下に実際に実装したAccordionのStorybookを示します。
キャリア観の変化
開発タスクと並行して、自分のキャリア観をブラッシュアップするために、何名かの社員さんとの面談や、チームメンバーとの交流の機会を設けてもらいました。その中で、自分のキャリア観が、明確に定まっていなかったものから、根拠を持ってこの軸をもとに考えていくという考え方になりました。
最初は、なりたいエンジニア像というのは具体的には決まっていなかったのですが、様々なバックグラウンドを持つマネーフォワードの社員さんのお話を聞いて、新しい技術領域に対して臆さずに挑戦し、その技術をより早く身につけることができるエンジニアになりたいと思うようになりました。
そのためには、技術の深いところまで知っていることで、他の領域に対しても共通点を見出すことができるようになり、早く理解することができるようになる必要があると思うようになりました。そのために今は、とりあえず自分が面白い、やりたいと思えるような技術を深くまで理解しながら学んでいくことが、モチベーションを保ちながら続けられる最善の方法であるという結論に至りました。
そして、その自分が面白い、やりたいと思える技術を選定する際には、自分の人生の軸に沿って選定していくことにしました。これは、自分の人生の軸に沿うことによって、何かで躓いた時に、振り返ることができるし、納得感も得やすいためです。
自分の人生の軸に関しては、過去を振り返って、自分が今まで何をモチベーションとして動いてきたのか、どんなことをしている時に楽しいと感じてやりがいを感じていたのかを考えました。その結果、人を助けて、何か反応をもらうことが自分のモチベーションになっていると感じました。そのため、今後、この軸をもとに考えていきたいと思っています。
サマーインターンシップに参加して感じたこと
2週間のサマーインターンシップを通してまず感じたことは、本当に楽しかった2週間だったということです。今まで経験したことがないことを色々と経験することができて技術面やコミュニケーションのやり取りなどに関して非常に成長することができたと感じました。
また、会社の雰囲気やコミュニケーションの仕方、頻度などは実際に実務型のインターンでしか感じることができないと思うので、非常に良い経験になったと思いますし、自分の反応をもらえる事がモチベーションになるという点でいえば、マネーフォワードでは非常にslackでのやり取りはもちろん日常の会話の部分でも反応がもらえる事が多いので、自分にあった環境なのかなと感じました。
反省すべき点としては、英語での議論の際に、相手の言っていることを理解しながらの聞き取りや言いたいことをすぐにアウトプットする力などはまだまだ足りていないなと感じたので、そこの部分をもっと伸ばしていきたいと感じました。
また、業務に関することだけではなく、今後の自分のキャリア観を色々な社員さんとの面談をもとに観点を増やしブラッシュアップできた点も非常に良い経験になったと感じています。
まとめ
サマーインターンシップに参加する前に掲げていた目標に関しては、全て達成することができました。
今回のサマーインターンシップは、実務型ということもあり、実務型でしか感じる事ができない、経験する事ができないことを色々と経験できたと感じています。そして、この経験は、今後働いていく上で良い経験になったと感じています。
そして、この経験は、実際に関わってくださったマネーフォワードの社員さんのおかげで得られた経験だと感じているのでここで感謝をさせてください。ありがとうございました。最高に楽しく濃密な経験を得られた2週間でした。
Discussion