Upgrade to Pro — share decks privately, control downloads, hide ads and more …

レガシーなフロントエンド環境との向き合い方

 レガシーなフロントエンド環境との向き合い方

Next.js、TypeScriptなど新しい技術も積極的に取り入れる弊社ですが、型やテストコードがないリポジトリや読み解くのが難しい Fat Controller など、技術的負債も抱えています。レガシーな環境とどう向き合い、どのようにアップデートして品質を保つ開発を続けているのか、実際のリファクタリングについてはコードを添えて説明し、チームの意識改革のためにやっていることも合わせてお話ししたいと思います。

12f1df700403004c52f295da0463f28a?s=128

Mayuka Fujino

July 05, 2021
Tweet

Transcript

  1. レガシーなフロントエンド環境への 向き合い方 2021/06/30 藤野真由佳

  2. 2 自己紹介 藤野 真由佳(Fujino Mayuka) • フロントエンドエンジニア • 2019年8月スペースマーケット入社 • ゲーム、料理が趣味

    ◦ Switchでよく遊んでます
  3. 3 アジェンダ

  4. 4 アジェンダ • スペースマーケットのフロントエンド環境について ◦ サービス共通UIリポジトリ • 古いリポジトリとの向き合い方 ◦ どの点がレガシーで改修しにくいのか

    ◦ TypeScript化・リファクタリングをどう進めるか ▪ コーディングガイドラインの紹介 ▪ Container/Presenter/Styled Component • メンバー技術力底上げ・意識改善に向けた取り組み ◦ 輪読会、意見交換
  5. 5 スペースマーケットのフロントエンド環境について

  6. 6 サービス共通UIリポジトリ • 各サービスのリポジトリと、サービス共通 UIリポジトリが存在 • コンポーネント設計は Atomic Designを採用 スペースマーケットのリポジトリ構成

    SPACEMARKET SPACEMARKET DASHBOARD SPACEMARKET EVENT SPACEMARKET BUSINESS SPACEMARKET ACCOUNT フロントエンド共通リポジトリ サービス共通UIリポジトリ(frontend_component) 各サービスリポジトリ
  7. 7 今回お話するレガシーな環境について • 創業時から使われているリポジトリの中でも更新頻度が高いもの • 当時はベストな選択をしていたが、技術進化と共に負債と化してしまった スペースマーケットのリポジトリ構成 SPACEMARKET SPACEMARKET DASHBOARD

    SPACEMARKET EVENT SPACEMARKET BUSINESS SPACEMARKET ACCOUNT フロントエンド共通リポジトリ サービス共通UIリポジトリ(frontend_component) 各サービスリポジトリ
  8. 8 古いリポジトリとの向き合い方

  9. 9 どの点がレガシーで改修しにくいのか

  10. 10 どの点がレガシーで改修しにくいのか • props(渡ってくるプロパティ) ◦ 基本的に型がない ◦ 一部Flowで書かれているが型が正しくないこともある ◦ 不要になったpropsが放置されている

    • ファイルが大きすぎる ◦ ロジックとHTML構造の責務が分かれていない ▪ キャッチアップに時間がかかる • テストコードがない ◦ 実装から仕様を読み解くしかない 課題:仕様がわかりにくい
  11. 11 TypeScript化しよう リファクタリングしよう どの点がレガシーで改修しにくいのか 課題:仕様がわかりにくい テストコード書こう🦁 • props(渡ってくるプロパティ) ◦ 基本的に型がない

    ◦ 一部Flowで書かれているが型が正しくないこともある ◦ 不要になったpropsが放置されている • ファイルが大きすぎる ◦ ロジックとHTML構造の責務が分かれていない ▪ キャッチアップに時間がかかる • テストコードがない ◦ 実装から仕様を読み解くしかない
  12. 12 TypeScript化をどう進めるか

  13. 13 TypeScript化をどう進めるか • 新規ファイルは .ts(x) で作成する ◦ テストコードを書く工数も確保しておく • any

    をどこまで許容するか ◦ 新規ファイルは any を使わない ◦ 既存ファイルのみ許容する場合あり ▪ Flow型の整合性チェック時に「今は不要になったのでは ...?」 というpropsが現れた時は、一旦 any を置いて対応する ▪ Flow型で要素定義がされておらず、 ただのObjectとされている中身が大きすぎる Object(調査工数が大きい) ルールを決める
  14. 14 TypeScript化をどう進めるか • TypeScript化する際、メンバーに迷いを与えないように 「コーディングガイドライン」 を作成している ◦ 例)明示的にEventの型をつけること ▪ onClickの型

    • NG 󰢄:React.MouseEvent<HTMLElement> ◦ aタグと認識されない • OK 󰢐:React.MouseEvent<HTMLAnchorElement> ◦ aタグと認識される ルールを決める
  15. 15 リファクタリングをどう進めるか

  16. 16 コーディングガイドラインの一部を紹介 Container/Presenter/Styled Component

  17. 17 リファクタリングをどう進めるか 目的 • ロジックとHTML構造の責務が分かれていない「大きすぎるファイル」を小さくすること 期待する結果 • ロジックとHTML構造、スタイル(CSS)の責務が分割される ◦ 可読性が高まる

    ◦ キャッチアップの時間を短縮できる ◦ リファクタリングしやすくなる ◦ 開発スピードが上がる Container/Presenter/Styled Component に分割する
  18. 18 リファクタリングをどう進めるか • ロジックに責務を負うコンポーネント • HTML構造、Styleに対する関心を持たない。(動的Stylingは除く) • Hooks を使用できる •

    Stateを保持できる ◦ 必ず持つ必要がある訳ではない • State及び Propsを扱う関数を持ち、Presenter Componentに渡す • 小要素として別のContainer Component / Presenter Componentを持てる ◦ Styled Componentは持てない • export は default exportで行う • ファイル名は Hoge.{jsx|tsx} Container/Presenter/Styled Component に分割する
  19. 19 リファクタリングをどう進めるか • HTML構造に責務を負うコンポーネント • ロジック、Styleに関する関心は持たない • Hooksは使用しない、Stateは保持しない • コンポーネントの情報、関数は

    Propsで受け取る • export は default exportで行う • ファイル名は HogePresenter.{jsx|tsx} Container/Presenter/Styled Component に分割する
  20. 20 リファクタリングをどう進めるか • 見た目に責務を負うコンポーネント • HogePresenter.jsxと同じファイルに記述する ◦ 外部からの想定外の importを避けるため •

    ロジックに関する関心は極力持たない ◦ styled-componentsの特性上、HTMLに対する関心は持つ ◦ Propsによる軽微なスタイル変更は許容 • Styled ComponentのCSSセレクタはネストしない ◦ CSSの優先順位を均一にするため ◦ ant-designのoverwriteは許容 Container/Presenter/Styled Component に分割する
  21. 21 リファクタリングをどう進めるか Container/Presenter/Styled Component に分割する(before) ひとつのファイルで完結 (例なので小さめのファイル)

  22. 22 リファクタリングをどう進めるか Container/Presenter/Styled Component に分割する(after) CSSに関する部分。 PrefixにStyledを付けることで HTML構造を作るコンポーネントと 区別しやすくなっている。

  23. 23 リファクタリングをどう進めるか Container/Presenter/Styled Component に分割する(after) 共通Styleのコンポーネント

  24. 24 リファクタリングをどう進めるか Container/Presenter/Styled Component に分割する(after) propsによる分岐への責務 のみ持つ

  25. 25 リファクタリングをどう進めるか Container/Presenter/Styled Component に分割する(after) 最終的に出力される部分

  26. 26 リファクタリングをどう進めるか Container/Presenter/Styled Component に分割する(after) 並びはHTML構造に関するので Presenterの責務

  27. 27 メンバーの技術力向上・ 意識改善に向けた取り組み

  28. 28 なぜ技術力向上・意識改善が必要か • 「技術的負債」にはいくつか種類がある ◦ 開発スピードを重視して早くできる実装で妥協してしまった ◦ 技術そのものがアップデートされ、当時は良い選択であったが 今となっては古く使いにくいものになってしまった ◦

    当時の開発者にとってはベストな選択であったが、 経験から技術力が向上し、より良い選択をできるようになった 技術的負債とは知識のアップデートによって解消に繋がるから
  29. 29 なぜ技術力向上・意識改善が必要か • 「技術的負債」にはいくつか種類がある ◦ 開発スピードを重視して早くできる実装で妥協してしまった ◦ 技術そのものがアップデートされ、当時は良い選択であったが 今となっては古く使いにくいものになってしまった ◦

    当時の開発者にとってはベストな選択であったが、 経験から技術力が向上し、より良い選択をできるようになった 技術的負債とは知識のアップデートによって解消に繋がるから
  30. 30 なぜ技術力向上・意識改善が必要か • 「技術的負債」にはいくつか種類がある ◦ 開発スピードを重視して早くできる実装で妥協してしまった ◦ 技術そのものがアップデートされ、当時は良い選択であったが 今となっては古く使いにくいものになってしまった ◦

    当時の開発者にとってはベストな選択であったが、 経験から技術力が向上し、より良い選択をできるようになった 技術的負債とは知識のアップデートによって解消に繋がるから つまりチームのスキル底上げが技術的負債の解消につながる ...!
  31. 31 無理をしない輪読会

  32. 32 メンバーの技術力向上・意識改善に向けた取り組み • 隔週で実施(45分) • 全員が事前に決められた章( 50ページくらい)を読み、感想や疑問点をコンフルに記載 ◦ 技術書を指定図書として定期開催している ◦

    話題になった記事がテーマになることも(例: 良いコードとは何か) • 輪読会というより感想共有会で、意見交換や疑問解消のために議論したりする • 「無理をしない」がポイント!! ◦ 施策で忙しい場合は遠慮せずにメンバーに伝えることをルールにしている ◦ 複数人が欠席の場合はスキップとする 無理をしない輪読会
  33. 33 あるべき姿ディスカッション

  34. 34 メンバーの技術力向上・意識改善に向けた取り組み • Slackで気軽に技術雑談してます あるべき姿ディスカッション そうだ、聞いてみよう!

  35. 35 メンバーの技術力向上・意識改善に向けた取り組み あるべき姿ディスカッションの一部 各々で意識していることの共有から 目から鱗が落ちることも

  36. 36 メンバーの技術力向上・意識改善に向けた取り組み あるべき姿ディスカッションの一部 Slackで聞くこともありますし、 定例で議題にあげて議論することも。 気軽に意見交換できる文化があります。

  37. 37 まとめ

  38. 38 まとめ • レガシーなフロントエンド環境の何が問題であったかを洗い出す • 膨大すぎるファイルが一番の問題であった ◦ 仕様のキャッチアップに毎回工数がかかってしまう • 対策としてTypeScript化、リファクタリングを進める

    ◦ ルールを決める、コーディングガイドラインの作成 • 技術的負債について考える ◦ チームのスキル底上げが技術的負債解消に繋がる • 技術力向上・意識改善に向けて ◦ 無理のない輪読会や気軽な「あるべきディスカッション」
  39. ご静聴ありがとうございました!