Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
リファクタリングのための第一歩
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
NearMeの技術発表資料です
PRO
November 29, 2024
Programming
180
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
リファクタリングのための第一歩
リファクタリングに関する勉強会資料です!
NearMeの技術発表資料です
PRO
November 29, 2024
More Decks by NearMeの技術発表資料です
See All by NearMeの技術発表資料です
PosthogのA/Bテスト機能の紹介
nearme_tech
PRO
1
21
AIフレンドリーなプロダクトに向けて
nearme_tech
PRO
1
50
初めてのLean言語
nearme_tech
PRO
0
76
Apache Airflow Workflow orchestration without turning cron into spaghetti
nearme_tech
PRO
1
21
実務で役立つ幾何学 ボロノイ図の基礎から グラフ・ネットワーク応用まで
nearme_tech
PRO
1
59
SQL/ID抽出タスクから考える 実践的なハルシネーション対策
nearme_tech
PRO
1
67
OpenCode & Local LLM
nearme_tech
PRO
0
200
OpenCode Introduction
nearme_tech
PRO
0
59
【Browser Automation × AI】 Stagehandを試してみよう
nearme_tech
PRO
0
160
Other Decks in Programming
See All in Programming
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
610
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
140
AI時代の仕事技芸論〜ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ(スクフェス仙台 2026バージョン)
kuranuki
0
710
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
1
270
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
160
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
0
330
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
440
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
320
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
AIが無かった頃の素敵な出会いの話
codmoninc
1
220
GitHubCopilotCLIのスラッシュコマンドを自作してみる
htkym
0
100
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
150
Featured
See All Featured
Discover your Explorer Soul
emna__ayadi
2
1.2k
Product Roadmaps are Hard
iamctodd
55
12k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
150
How to Talk to Developers About Accessibility
jct
2
430
Building an army of robots
kneath
306
46k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Un-Boring Meetings
codingconduct
0
350
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
Everyday Curiosity
cassininazir
0
260
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Transcript
0 リファクタリングのための第一歩 2024-11-29 第109回NearMe技術勉強会 Kaito Asahi
1 ⽬次 1. リファクタリングとは? 2. リファクタリングの例2つ a. メソッドチェーンの利⽤ b. ポリモーフィズム
3. リファクタリングは本当に必要か? 4. リファクタリングのユースケース 5. まとめ ※細かいリファクタリング⼿法については触れていません!
2 リファクタリングとは?
3 リファクタリングとは? • リファクタリング(Refactoring) ◦ 外部的な振る舞いはそのままで、内部のコードの可読性を⾼めるなどの 内部構造の改善のこと Ex) - 不要な定数の削除
- 異なるがカプセル化できる様な関数群をまとめる - あるキャンペーン⽤の料⾦計算ロジックなど - ifロジックなどでのネストの深いコードの改善 - early return などでネストを減らす etc…
4 コードリファクタリングの 具体例を少しだけ挙げます
5 リファクタリングの例 • 汎⽤的な for ループをメソッドチェーンに置き換える Ex) 配列 nums から、偶数であるものを取り出して表⽰する
const nums = [1, 2, 3, 5, 8, 13] const result: number[] = [] for (const num of nums) { if (num % 2 === 0) { result.push(num) } } console.log(result)
6 リファクタリングとは? • 汎⽤的な for ループをメソッドチェーンに置き換える Ex) 配列 nums から、偶数であるものを取り出して表⽰する
const nums = [1, 2, 3, 5, 8, 13] const result: number[] = [] for (const num of nums) { if (num % 2 === 0) { result.push(num) } } console.log(result) forの中全体を確認することで、 フィルタする処理だということがわかる
7 リファクタリングとは? • 汎⽤的な for ループをメソッドチェーンに置き換える Ex) 配列 nums から、偶数であるものを取り出して表⽰する
const nums = [1, 2, 3, 5, 8, 13] const result: number[] = [] for (const num of nums) { if (num % 2 === 0) { result.push(num) } } console.log(result) forの中全体を確認することで、 フィルタする処理だということがわかる フィルタすることは分かりやすく示したい!
8 リファクタリングとは? • 汎⽤的な for ループをメソッドチェーンに置き換える Ex) 配列 nums から、偶数であるものを取り出して表⽰する(filterメソッドの利⽤)
const nums = [1, 2, 3, 5, 8, 13] const result: number[] = [] for (const num of nums) { if (num % 2 === 0) { result.push(num) } } console.log(result) const nums = [1, 2, 3, 5, 8, 13] const result = nums.filter( (num) => num % 2 === 0 ) console.log(result)
9 リファクタリングの例 • ポリモーフィズムの利⽤ Ex) Dog, Catクラスにて、鳴き声を出⼒する class Dog {
makeSound(): string { return "Woof"; } } class Cat { makeSound(): string { return "Meow"; } } function playWithDog(dog: Dog) { console.log(dog.makeSound()); } function playWithCat(cat: Cat) { console.log(cat.makeSound()); } const myDog = new Dog(); const myCat = new Cat(); playWithDog(myDog); playWithCat(myCat);
10 リファクタリングの例 • ポリモーフィズムの利⽤ Ex) Dog, Catクラスにて、鳴き声を出⼒する class Dog {
makeSound(): string { return "Woof"; } } class Cat { makeSound(): string { return "Meow"; } } function playWithDog(dog: Dog) { console.log(dog.makeSound()); } function playWithCat(cat: Cat) { console.log(cat.makeSound()); } const myDog = new Dog(); const myCat = new Cat(); playWithDog(myDog); playWithCat(myCat); やっていることは同じ (コードの重複)
11 リファクタリングの例 • ポリモーフィズムの利⽤ Ex) Dog, Catクラスにて、鳴き声を出⼒する abstract class Animal
{ abstract makeSound(): string; move(): void { console.log("Moving..."); } } class Dog extends Animal { makeSound(): string { return "Woof"; } } class Cat extends Animal { makeSound(): string { return "Meow"; } } function playWithAnimal(animal: Animal) { console.log(animal.makeSound()); } const myDog = new Dog(); const myCat = new Cat(); playWithAnimal(myDog); playWithAnimal(myCat); コードの重複の解消 抽象クラスの作成
12 リファクタリングの規模 • ⽇常のコーディング中でのリファクタリング ◦ あるPull Requestにて、⾃分の修正したコードを振り返ったときに、デグレードが 確認できたらすぐロールバックする程度のリファクタリング • プロジェクトとしてのリファクタリング
◦ 1つのリポジトリ、複数のFeature単位での⽐較的⼤きなリファクタリング ◦ コードが作成されてから時間が経った後でのリファクタリング
13 リファクタリングの規模 • ⽇常のコーディング中でのリファクタリング ◦ あるPull Requestにて、⾃分の修正したコードを振り返ったときに、デグレードが 確認できたらすぐロールバックする程度のリファクタリング • プロジェクトとしてのリファクタリング
◦ 1つのリポジトリ、複数のFeature単位での⽐較的⼤きなリファクタリング ◦ コードが作成されてから時間が経った後でのリファクタリング 明らかに難易度が高い
14 プロジェクトとしてのリファクタリング (1) 現状の課題の分析‧集約 → 現状、コードロジックで何が課題であるのかを洗い出す (2) リファクタリングにより期待できる成果 → リファクタリング後にどの様な良いことが起こるのか
(3) リファクタリングコスト → どのくらいの時間がかかることが予測されるか
15 そもそも、 分析に必要なリソースはあるか?
16 リファクタリングのための現状分析 可読性の低そうなコードを発⾒ ↓ どの様な経緯でこの様なコードになったのかの追跡 ↓ 改善策を⽴てて、リファクタリング計画に加える
17 リファクタリングのための現状分析 可読性の低そうなコードを発⾒ ↓ どの様な経緯でこの様なコードになったのかの追跡 ↓ 改善策を⽴てて、リファクタリング計画に加える これ、探し出せますか?
18 リファクタリングのための現状分析 • 該当コードになった経緯の追跡⽅法 (1) Git Blame - コードベースで blame
から対象PRを探し出して、そこからタスクチケットなどを頼り に当時のコンテキストを追う
19 リファクタリングのための現状分析 • 該当コードになった経緯の追跡⽅法 (1) Git Blame - コードベースで blame
から対象PRを探し出して、そこからタスクチケットなどを頼り に当時のコンテキストを追う → PRのDescriptionや、元のタスクチケットなどが整理されていない場合、どうしてその 様なコードになったのかなどは追いきれない可能性がある → Design Docや、タスクチケットは、どちらかというと意思決定の最終段階に偏っている ことが多い
20 リファクタリングのための現状分析 • 該当コードになった経緯の追跡⽅法 ⭐ (2) ADR - Architectural Decision
Record - 意思決定のプロセスをドキュメントとして保存しておくもの
21 リファクタリングのための現状分析 • 該当コードになった経緯の追跡⽅法 ⭐ (2) ADR - Architectural Decision
Record - 意思決定のプロセスをドキュメントとして保存しておくもの → 過去のコンテキスト、意思決定のための⽐較検討、ステータスを確認できる! → 過去の意思決定を踏まえて、そもそもリファクタリングの必要性、作業にかかりそうな コスト予測がよりしやすくなる!
22 リファクタリングのための現状分析 • 該当コードになった経緯の追跡⽅法 ⭐ (2) ADR - Architectural Decision
Record - 意思決定のプロセスをドキュメントとして保存しておくもの → 過去のコンテキスト、意思決定のための⽐較検討、ステータスを確認できる! → 過去の意思決定を踏まえて、そもそもリファクタリングの必要性、作業にかかりそうな コスト予測がよりしやすくなる! ※ADRについては過去の勉強会で扱っています → https://speakerdeck.com/nearme_tech/architecture-decision-record-adr
23 リファクタリングには、 コードだけでなく ビジネスサイドの理解も不可⽋
24 ビジネスサイドの理解とリファクタリング • ビジネスロジック ◦ 企業の運営ルールやプロセス、ワークフローを反映したコード部分 ▪ キャンペーン計算ロジック、税制対応、カスタム割引ルール
25 ビジネスサイドの理解とリファクタリング • ビジネスロジック ◦ 企業の運営ルールやプロセス、ワークフローを反映したコード部分 ▪ キャンペーン計算ロジック、税制対応、カスタム割引ルール → ビジネスロジックを⼗分に理解していないと、ビジネス要件を満たさないままリファク
タリングをしてしまう恐れがある
26 ビジネスサイドの理解とリファクタリング • リファクタリングとビジネス要件の衝突例 Ex) キャンペーン計算ロジック • 現状 ◦ 複雑なキャンペーンロジックがコードベースに埋め込まれている
◦ 新⼈エンジニアが「コードが汚い」という理由だけでリファクタリングを実施 • 結果 ◦ ビジネス要件(特定条件での割引適⽤など)が失われる ◦ 顧客への請求ミスや収益減少などの重⼤な問題につながる
27 もちろん、常に起こるわけではない
28 ビジネスサイドの理解とリファクタリング • 技術とビジネスのバランスを取る⽅法 (1) ビジネス背景の把握 (2) リファクタリング計画にビジネス要件を反映 (3) テストでの動作保証
29 ビジネスサイドの理解とリファクタリング (1) ビジネス背景の把握 • 前提 ◦ 意思決定は、ADRやその他ドキュメントなどでまとめておく • やること
◦ 過去のドキュメント(ADRや設計書)やGit履歴から背景を追跡 ◦ 関係者(プロダクトマネージャー、営業チームなど)との対話を通じて、コードに埋め込ま れたビジネスルールを確認
30 ビジネスサイドの理解とリファクタリング (2) リファクタリング計画にビジネス要件を反映 • やること ◦ 改善対象のコードがどの様なビジネス価値を生み出しているのか を明確化 ◦
リファクタリング前後でその価値が維持されている 様に設計
31 ビジネスサイドの理解とリファクタリング (3) テストでの動作保証 • やること ◦ ビジネスロジックに関するテストケースを充実させて、可能な限り全てのパターンに対して の動作保証がされている ことを示す
32 複雑性の良し悪しを⾒極める
33 リファクタリングの際に考慮する「複雑性」 リファクタリング → 複雑に絡み合っているものを解いて管理しやすいようにする but… 複雑さを解く → ビジネス要件を満たさずに崩壊する可能性もある... →
良い複雑性と悪い複雑性を⾒極めることが⼤事!
34 リファクタリングの際に考慮する「複雑性」 • 良い複雑性 ◦ ⽬的が明確 ▪ 複雑性がビジネス価値や競争優位性を⽣み出すために存在している • Ex)
特定顧客向けのカスタマイズ機能や業界特化のルール ◦ ⾃律性がある ▪ 各コンポーネントが独⽴しており、他に影響を与えず変更‧運⽤可能 ◦ 明瞭さ ▪ コードや設計が⾃⼰説明的であり、意図がすぐに理解できる ◦ ユニークさ ▪ 各部分が特定の役割を持ち、他と重複していない
35 リファクタリングの際に考慮する「複雑性」 • 悪い複雑性 ◦ ⽬的不明確 ▪ なぜそのコードや設計が存在するのか理解できない ◦ 相互依存性が⾼い
▪ ⼀部を変更すると他の部分に影響が波及する ◦ 不透明さ ▪ コードや設計が分かりづらく、意図や動作が把握困難 ◦ 冗⻑性 ▪ 同じような機能や処理が複数箇所に存在
36 「複雑性」をフレームワークで分類する • クネビン‧フレームワーク 問題の種類を性質別に分類をし、それぞれの分類に対してプロセスを体系づけるもの https://hirolaboratory.com/%E3%82%AF%E3%83%8D%E3%83%93%E3%83%B3%E3%82%AB%E3%83%8D%E3%83%B4%E3 %82%A3%E3%83%B3%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%8 1%A8%E3%81%AF%EF%BC%9F%E5%88%86%E9%A1%9E%E3%82%84/
37 「複雑性」をフレームワークで分類する 〜クネビン‧フレームワーク〜 1. 単純(Simple) - 問題例 - コード内のハードコーディングされた定数を削除し、設定ファイルに移動する -
特徴 - 解決策が明確で、標準的な⼿順で対応可能 - 対応策 - 定数を設定ファイルに移動し、コードから参照するように変更
38 「複雑性」をフレームワークで分類する 〜クネビン‧フレームワーク〜 2. 困難(Complicated) - 問題例 - ⼤規模なクラスが単⼀責任の原則を犯しているため、リファクタリングして責務を 分割する必要がある
- 特徴 - 専⾨知識が必要で、複数の設計オプションが存在 - 最適な解決策を⾒つけるためには分析が必要 - 対応策 - クラスの役割を分析し、関連する機能ごとに新しいクラスやモジュールに分割
39 「複雑性」をフレームワークで分類する 〜クネビン‧フレームワーク〜 3. 複雑(Complex) - 問題例 - ユーザーインターフェースの改善によるユーザーエクスペリエンス向上を⽬指すリ ファクタリング
- 特徴 - 因果関係が不明瞭で、ユーザーの反応が予測しづらい - 試⾏錯誤による学習が必要 - 対応策 - プロトタイプを作成し、ユーザーテストを繰り返してフィードバックを得る。
40 「複雑性」をフレームワークで分類する 〜クネビン‧フレームワーク〜 4. 混沌(Chaos) - 問題例 - リリース直前に発⾒された重⼤なバグの修正 -
特徴 - 即座の対応が求められ、原因究明よりもまずはバグ修正が優先される - 対応策 - 迅速に修正を⾏い、テストを実施して影響範囲を確認 - 根本原因を分析し再発防⽌策を講じる
41 「複雑性」をフレームワークで分類する 〜クネビン‧フレームワーク〜 5. 無秩序(Disorder) - 問題例 - 複数の異なる技術スタックやアーキテクチャが混在しているプロジェクトで、どこ から⼿をつけるべきか不明
- 特徴 - 問題がどの領域に属するか不明確で、どこから⼿をつけるべきか判断しづらい - 対応策 - 状況を整理し、それぞれの領域に分類してから適切な対応策を決定する
42 リファクタリングユースケース
43 リファクタリングユースケース • メルペイの「あと払い」サービスリファクタリング - コンテキスト - ⻑年のコーディングによるコードの負債の積み重ね - アプローチ
- SOLID原則に基づき、コードの責務を明確化し、依存関係を整理 - マイクロサービス化を進め、独⽴性と可読性を向上 - 成果 - コード変更時の影響範囲が明確になり、⽣産性が向上 - テストスタブを⽤いたユニットテストの効率化に成功 https://engineering.mercari.com/blog/entry/20221221-refactoring-along-solid/ S : 単⼀責任の原則(SRP) O :オープン‧クローズドの原則(OCP) L : リスコフの置換原則(LIP) I : インタフェース分離の原則(ISP) D: 依存関係逆転の原則(DIP)
44 リファクタリングユースケース • PIP-Makerの⼤規模リファクタリング - コンテキスト - Adobe FlashからHTML5やJavaScriptへの移⾏が必要となり、⼤規模な技術移⾏が 求めらていた
- アプローチ - フロントエンドとバックエンドでTypeScriptを採⽤し、技術的親和性を⾼める - IaaSからPaaSへの移⾏を通じて、システムの拡張性と保守性を向上 - 成果 - 成果処理速度と操作性が⼤幅に改善され、ユーザー満⾜度が向上 https://sg.wantedly.com/companies/company_641519/post_articles/515613
45 リファクタリングユースケース • ラクスによる技術的負債解消プロジェクト - コンテキスト - ⻑年放置されていた技術的負債が開発効率を低下させていた - アプローチ
- リファクタリング対象をパターン分けし、優先順位を設定 - 開発チームとビジネスサイドで共有しながら進⾏ - 成果 - 可読性の向上により、レビュー効率が改善 - 開発チーム全体で納得感を持ちつつリファクタリングを実施 https://logmi.jp/brandtopics/323993
46 参考⽂献(1/2) • 糞コードは直すな。 ◦ https://qiita.com/kotauchisunsun/items/d03c1e6936ffb250e4a1 • 新卒エンジニアが3ヶ⽉間のリファクタで学んだこと ◦ https://techblog.openwork.co.jp/entry/2022/05/20/121238
• リファクタリングをする際にソースコードの設計からはじめてはいけない ◦ https://tech-blog.monotaro.com/entry/2023/11/28/090000 • ラクスによる技術的負債解消プロジェクト’ ◦ https://logmi.jp/brandtopics/323993 • PIP-Makerの⼤規模リファクタリング ◦ https://sg.wantedly.com/companies/company_641519/post_articles/515613
47 参考⽂献(2/2) • メルペイの「あと払い」サービスリファクタリング ◦ https://engineering.mercari.com/blog/entry/20221221-refactoring-along-solid/ • クネビン(カネヴィン)フレームワークとは?分類やスクラム開発導⼊時の活⽤例を解説 ◦ https://hirolaboratory.com/%E3%82%AF%E3%83%8D%E3%83%93%E3%83%
B3%E3%82%AB%E3%83%8D%E3%83%B4%E3%82%A3%E3%83%B3%E3%83 %95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%8 2%AF%E3%81%A8%E3%81%AF%EF%BC%9F%E5%88%86%E9%A1%9E%E3% 82%84/ • リファクタリング(第2版)- 既存のコードを安全に改善する - ◦ https://www.ohmsha.co.jp/book/9784274224546/
48 Thank you