Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

クラウドワークス プロダクトの持続的開発のためのリファクタリング実践アプローチ

6,906 views

Published on

19/07/24開催の「持続可能なプロダクト開発への取り組み ~メドピアとクラウドワークスの事例公開~」における、クラウドワークス側の登壇資料です。
https://connpass.com/event/136791/

Published in: Software

クラウドワークス プロダクトの持続的開発のためのリファクタリング実践アプローチ

  1. 1. CrowdWorks Inc. Product Div. クラウドワークス リファクタリングチーム 「バグハンター」 株式会社 クラウドワークス
  2. 2. CrowdWorks Inc. Product Div. アジェンダ 1. 弊社紹介 2. 目的・課題 3. Fat Modelの技術的負債 4. 解決方法 4.1. 設計手法 4.2. Fat Modelの弱点 4.3. 構造Before/After 4.4. 分析手法 4.5. 作戦方針
  3. 3. CrowdWorks Inc. Product Div. 1. 弊社紹介
  4. 4. CrowdWorks Inc. Product Div. サービス紹介 オンラインで直接つながり マッチング 仕事依頼 業務実行・納品 発注者=クライアント (企業・個人) 40万社 受注者=クラウドワーカー (主に個人) 240万人
  5. 5. CrowdWorks Inc. Product Div. 今日話すこと クラウドワークスの技術的負債に対する取り組み どんな課題があるか 技術的にどのようにアプローチしているか をお話します
  6. 6. CrowdWorks Inc. Product Div. リファクタリングは力学的にどうしても後手後手になりやすい。 そのためリファクタリング専門チームを創設。 チーム人数:2名 意図:既に発生したバグを退治するのは本当のバグ退治ではない。そもそもバグが生ま れない構造に作り変えるのが真のバグ退治。 リファクタリング専門チーム「バグハンター」
  7. 7. CrowdWorks Inc. Product Div. 2. 目的・課題
  8. 8. CrowdWorks Inc. Product Div. Crowdworks.jpをリファクタリングして開発生産性を向上し、「持 続可能な成長」への道筋を作る。 リファクタリングの目的
  9. 9. CrowdWorks Inc. Product Div. 解決したい課題 課題 狙う効果 開発生産性 コード変更にあたり、コード分析コストや変更 検討コストが大きく、生産性に課題。 リファクタリングにより理解容易性向上、影響範 囲局所化等を狙い、開発生産性を高める。 エンジニアス キル 粗悪な設計は質の高い設計導入を阻む。 エンジニアが粗悪な設計を真似、学習する可 能性があり、スキル低下の要因に。 リファクタリングにより質の高い設計の導入を 容易にする。 お手本となるコードによりエンジニアのスキル 向上を狙う。 製品の 信頼性 バグを埋め込みやすい構造。重大インシデ ント化した場合、製品の信頼性を毀損。 バグを埋め込みにくい構造へ昇華させ、弊社の 持続可能成長性を向上させる。
  10. 10. CrowdWorks Inc. Product Div. 現状の構造的課題 View Controller (Skinny Controller) ActiveRecord (Fat Model) Fat Modelが大量に存在する。 Railsのお作法ではFat Modelがある べき姿なのかも知れない。 しかし巨大化複雑化しすぎていて、生 産性低下を招いている。
  11. 11. CrowdWorks Inc. Product Div. 3. Fat Modelが抱える 技術的負債
  12. 12. CrowdWorks Inc. Product Div. Fat Modelが抱える技術的負債 技術的負債 説明 関連コードの 散在(低凝集) 本来業務概念的に関連し合うコードが、様々なクラスにあちこちに 散在している。 あるモデルに対する処理が全く別のモデルに書かれているなど、 責務外の実装が多い。 コードの追跡が困難。 コピペコード 同じ制御コードが至るところにコピペしてある。仕様変更に弱く、修 正漏れがあるとバグ化。 意図不明な コード 何をやらせたいのか意図不明なコード。 理解や修正を妨げる。
  13. 13. CrowdWorks Inc. Product Div. Fat Modelが抱える技術的負債 技術的負債 説明 うねるコード 条件分岐(if, case-when)やループ制御(each do)などが多重に ネストしており、遠くから見るとうねっているように見えるコード。複 雑で理解困難。 共通化に反する Concern 共通処理の定義に便利なConcernに、respond_to?やis_a?な ど特定クラスの場合の条件分岐が大量に入り込んでいて、共通 化に反している。複雑な上、Concernをincludeしているクラス全 てに変更影響があり触ると危険。 異なるコンテキス トの混在 ActiveRecordにあらゆるコンテキストの実装が入り込んでいて、 巨大化の主要因になっている。
  14. 14. CrowdWorks Inc. Product Div. 4. 解決方法
  15. 15. CrowdWorks Inc. Product Div. 4.1. 設計方法
  16. 16. CrowdWorks Inc. Product Div. 技術的負債に対抗する知識 これらの書籍は技術的負債を解消する手法に詳しい。 これら書籍記載のノウハウを複合的に用い、技術的負債に挑む。
  17. 17. CrowdWorks Inc. Product Div. 武器となる設計手法 手法 説明 対応負債 ValueObject ある特定の値と、その演算ロジックをカプセル化する設計パ ターン。業務概念ごとの高凝集化の基本。 消費税、システム利用料など。 ・低凝集 ・コピペコード composed_of ActiveRecordのカラムをValueObjectへマッピングする Railsの構文。カラムを操作するロジックを ValueObjectへ 委譲できる。 同上 ユビキタス言語 チームで概念認識を合わせるために共有する言葉。 対象ドメインの業務概念の認識合わせに用い、ソースコード 上の命名でも表現する。 ・意図不明なコード
  18. 18. CrowdWorks Inc. Product Div. 武器となる設計手法 手法 説明 対応負債 FirstClass Collection ループ制御(each doなど)をカプセル化するパターン。 ・うねるコード RuleObject 複雑な条件分岐をカプセル化するパターン。 ・うねるコード Strategy (区分Object) case-whenで処理切替するロジックを単純化するパターン。 case-whenの条件分岐コピペを削減する。 ・コピペコード ・うねるコード ・共通化に反する Concern 境界付けられた コンテキスト 概念(モデル)は状況(コンテキスト)によって意味や扱いが異 なる場合が多々ある。システムを取り巻くコンテキストを分析 し、各コンテキストに即した特化型ドメインオブジェクトを設計 する。 ・異なるコンテキストの混 在
  19. 19. CrowdWorks Inc. Product Div. 4.2. Fat Modelの弱点
  20. 20. CrowdWorks Inc. Product Div. Fat Modelの弱点 一見難攻不落なFat Modelでも、切り崩しが可能な弱点が存在する。 以下に弱点と、その弱点に対応する設計手法を列挙する。
  21. 21. CrowdWorks Inc. Product Div. 弱点部位 弱点 説明 難易度 用いる設計手法 クラスメソッド そのクラスにいなくても良いメソッド。 結合度が低く、ValueObjectとして容易に引き剥がす ことが可能。 簡単 ValueObject privateメソッド 定義クラスからしかコールされないため、依存度は低 め。 依存パラメータをコンストラクタで渡すようにすれば privateメソッドごとValueObject化可能。 やや簡単 ValueObject ローカル変数 演算の途中経過を格納している中間成果物であること 多い。 中間成果物を、成果物を得る演算処理とまとめて ValueObject化する。 やや簡単 ValueObject
  22. 22. CrowdWorks Inc. Product Div. 弱点部位 弱点 説明 難易度 用いる設計手法 うねるコード 条件分岐やループ制御で多重にネストしたコー ド。 ループ制御はFirstClassCollection化し、条件 分岐はRuleObject化する。 やや簡単 ・FirstClassCollection ・RuleObject has_many ActiveRecordのhas_manyで関連付けられた コレクションに対するループ制御を、 FirstClassCollection化する。 やや簡単 ・FirstClassCollection case-when case-when分岐(特に分岐コピペ)をStrategy 化する 中 ・Strategy
  23. 23. CrowdWorks Inc. Product Div. 弱点部位 弱点 説明 難易度 用いる設計手法 ActiveRecordの カラム Railsのcomposed_ofでValueObject化が可 能。ActiveRecord上のロジックを ValueObjectへ委譲できる。 これができれば理想的には ARから永続化以外 のほとんどのロジックを一掃可能! 難しい composed_of
  24. 24. CrowdWorks Inc. Product Div. 4.3. 構造 Before/After
  25. 25. CrowdWorks Inc. Product Div. 構造Before View Controller (Skinny Controller) ActiveRecord (Fat Model)
  26. 26. CrowdWorks Inc. Product Div. Context B Context C View Controller ActiveRecord (Skinny Model) Context A First Class Collection Value Object Value Object Value Object Value Object Value Object Context D First Class Collection Value Object Value Object Value Object Value Object Value Object ARには永続化責務のみが残る ActiveRecordのロジックを ValueObjectなどに委譲 構造Afterイメージ図 抽出したオブジェクトは コンテキストごとに分ける
  27. 27. CrowdWorks Inc. Product Div. 4.4 分析手法
  28. 28. CrowdWorks Inc. Product Div. サイクロマティック複雑度などメトリクス を解析し、Technical Debt(技術的負 債)の度合いを算出してくれるオンライン ツール。Githubと連携動作する。 チームKPIとしても利用。 本ツールの公開APIを利用し、特定クラ スのメトリクスを自動取得するスクリプト を組み、リファクタの成果を観測してい る。 メトリクス解析ツール Code Climate Quality
  29. 29. CrowdWorks Inc. Product Div. 縦軸:Remediation points。技術的負債の指標値。公開APIで取得可能。 黄色実線:現在リファクタ中の、負債化してるConcernのひとつ。 Code Climate Quality 最近の計測結果
  30. 30. CrowdWorks Inc. Product Div. 静的型チェックツール Sorbet(ソルベ) Rubyの型チェックツール。 静的型付言語と同様に型チェックにより 実装正確性、コードトレーサビリティの 正確性を向上させる。 6月にリリースされたばかりで潜在バグ が多く、クラウドワークスでは試験運用 中。
  31. 31. CrowdWorks Inc. Product Div. クラスの親やincludeしてるmoduleの 一覧を返す、Ruby標準ライブラリのメ ソッド。 共通化に失敗しているConcernを何個 もincludeし、複雑怪奇な構造になって いるクラスの依存関係を調べるのに必 須。 クラス祖先解析API Module#ancestors
  32. 32. CrowdWorks Inc. Product Div. 分析手法 影響スケッチ 書籍「レガシーコード改善ガイド」に記 載の分析手法。 リファクタ対象の影響範囲を知るため の方法である。 右図のように、クラスやメソッドの依存 関係を図式化し、影響範囲を見える化 する。
  33. 33. CrowdWorks Inc. Product Div. 書籍「レガシーコード改善ガイド」に記載の分析手法。 リファクタ対象の影響範囲を知るための方法である。 リファクタ対象を、テストも書かずにいきなりリファクタしてみる。 どの辺までリファクタしなければならないか影響範囲が分かる。 分析手法 試行リファクタリング
  34. 34. CrowdWorks Inc. Product Div. 4.5. 作戦方針
  35. 35. CrowdWorks Inc. Product Div. リファクタリングの候補選定には、価値、難度、リスクの3軸で評価する(書 籍「レガシーソフトウェア改善ガイド」) 価値 チームにとってどれほど有益であるか。理解容易性が上がった、 すぐ機能追加できるようになった、バグを埋め込みにくくなった、 など。 難度 リファクタリングの技術的な難しさ。 リスク リファクタリングに失敗した場合、どれほどのリスクが発生する か。例えばお金周りのデータが壊れるなど。 リファクタリング対象選定基準
  36. 36. CrowdWorks Inc. Product Div. • 依存度の小さい末端ロジックから攻める • いきなりコアな部分から着手すると、他からの依存度が高く影響範囲が広すぎて手 に負えなくなる可能性が高い。 • クラスメソッドやprivateメソッドなど他からの依存度が低い末端ロジックから少しずつ 切り崩していくのが基本。 • 集中攻撃 • 五月雨式にあちこちいろんなクラスをリファクタするのではなく、どれか特定のクラス に絞って集中的にリファクタする。 • 効果①:そのクラスに関する知見が高まる。 • 効果②:思考のスイッチングコストを低減できる。 戦術方針
  37. 37. CrowdWorks Inc. Product Div. start 候補リストから対象選定 影響範囲分析 & 試行リファクタリング リファクタで きそう? 本実装プロセスへ 課題を メモしておく yes no 分析プロセス
  38. 38. CrowdWorks Inc. Product Div. start ドメインオブジェクト 設計 テストコード実装 リファクタリング実行 コードレビュー end 設計before/afterを QiitaTeamで記事化 本実装プロセス デプロイ 動作確認
  39. 39. CrowdWorks Inc. Product Div. ご清聴 ありがとうございました

×