レガシーコードからの脱却

2019年10月4日のAWS DevDay / 2019年10月31日のEOF2019 / 2020年2月14日のDevelopers Summitで登壇した際のスライドです。

1. レガシーコードからの脱却 2020/2/14 株式会社アトラクタ 吉羽龍太郎 (@ryuzee) ✤ ✤ ✤ 初版: 2019/10/03 AWS DevDay 改訂: 2019/10/31 EOF2019 改訂: 2020/02/14 Developers Summit 2020
2. 株式会社アトラクタについて ✤ 社名:株式会社アトラクタ 英文表記:Attractor Inc. / https://www.attractor.co.jp ✤ 設立:2016年12月 ✤ 所在:東京都港区 ✤ 開発プロセスに関するコンサルティングやトレーニングを提供 ✤ アジャイル開発 / DevOps / チーム育成 / クラウドコンピューティング / ドメインモデリングなどが専 門領域 2
3. 登壇 各種イベントでの登壇 コーチング オンサイト トレーニング アジャイル開発やDevOps に関するオンサイトコーチ ング アジャイル開発や組織づくり に関するオンサイト トレーニング 認定研修 認定スクラムマスター研修 Suitable for all categories 等の主催 business and personal 執筆・翻訳 技術書やドキュメントの 執筆や翻訳 などなど
4. 自己紹介 ✤ 吉羽龍太郎 (@ryuzee) ✤ 株式会社アトラクタ取締役CTO/アジャイルコーチ ✤ ✤ 野村総合研究所、Amazon Web Servicesなどを経てアトラクタを創業 開発プロセス/アジャイル開発/DevOps/クラウドコンピューティングが専門 ✤ Scrum Alliance Certified Team Coach (CTC) ✤ ✤ コーチングを受けることで認定スクラムマスター取得可能 Microsoft MVP for Azure 4
5. 著書・訳書(買ってね) 5
6. 【宣伝】 新しい書籍が出ます!! ✤ 『みんなでアジャイル』 ✤ レガシーコードからの脱却の訳者4人による翻訳 ✤ 2020/3/19 発売予定 ✤ こちらもよろしくお願いします!! 6
7. 今日のお話 ✤ レガシーコードからの脱却 ―ソフトウェアの寿命を 延ばし価値を高める9つのプラクティス ✤ 2019/9/19 発売 3刷御礼 ITエンジニア本大賞 2020 技術書部門大賞!! ありがとうございます! 7
8. レガシー本といえば 8
9. レガシーコードとは? ✤ 『レガシーコード改善ガイド』による定義 ✤ レガシーコードとはテストのないコード ✤ 「テストのないコードは悪いコードである。どれだけうまく書かれているかは関 係ない。どれだけ美しいか、オブジェクト指向か、きちんとカプセル化されてい るかは関係ない。テストがあれば、検証しながらコードの動きを素早く変更する ことができる。テストがなければ、コードが良くなっているか悪くなっているの かが本当にはわからない」 ✤ きれいなコードは有益だが、それだけでは不十分 9
10. レガシーコードとは ✤ 『レガシーソフトウェア改善ガイド』による定義 ✤ 保守または拡張が困難なコード ✤ 「保守または拡張が困難な既存のプロジェクトなら、なんでもレガシーと呼ぶこ とにしている。ここでの話題は、単にコードベースだけではなく、プロジェクト全 体であることに注意していただきたい」 10
11. レガシーコードとは ✤ ✤ つまり定義はさまざま ✤ 同じ用語を使っていても、中身の認識に相違がでることが多い ✤ 議論のときはまず共通認識は何かを確認するとよい 本セッションでは以下のように定義する ✤ 理由は問わず修正、拡張、作業が難しいコード ✤ つまり保守に多額のお金がかかる 11
12. ソフトウェアと変更 変更する 挑戦? 成長 使われない 使われる 塩漬け? 完成? 変更しない 12
13. 使われるソフトウェア ✤ 使われるソフトウェアは変更が必要になる 実はソフトウェアに限ら ない。 データ、マクロ、ドキュメントなどに もあてはまる! ✤ 必要な変更をすべて予測するのは無理 ✤ よって変更可能となるように書くべき ✤ その逆がレガシーコード(修正、拡張、作業が難しいコード) ✤ 必要になったときに対応できるエンジニアリングプラクティスが必要 ✤ 変更のコスト(ソフトウェアの保有コスト)を下げたい 13
14. ところが実際の時間の使い方には問題が… 『ソフトウェアがバグに悩まされる理由の1つは、増し続ける複雑さである。千行単位で 計測されてきたソフトウェア製品のサイズは、今や百万行単位で計測されるように なっている。ソフトウェア開発者はすでにほぼ80%の開発コストを障害の特定と修正の ために使っている。それでも、ソフトウェアほど不具合が多い状態で出荷されている製 品はほぼない。』 国立標準技術研究所(NIST), 2002 14
15. ここにも10億ドル、あそこにも10億ドル ✤ ✤ ソフトウェアの障害が米国経済に年間600億ドルのコストになっている ✤ 世界の180か国のうち、GDPが600億ドル以下の国は70% ✤ マーク・ザッカーバーグとジェフ・ベゾスの総資産合計がおよそ600億ドル 失敗のコストは恐ろしく高い 15
16. なぜこのような問題が起こるのか ✤ 急ぎすぎている ✤ たくさん作ろうとしすぎている ✤ 読みやすさより書きやすさを優先している ✤ …… ✤ つまり品質を犠牲にしている 16
17. 品質は検査では上がらない Quality comes not from inspection, but from improvement of the production process.. Edwards Deming 17
18. やるべきことは問題を作り込まないこと、 つまり、レガシーコードを最初から作らないようにすること
19. ではどうすればいいのか? → 開発プロセスに着目する
21. Scrum 21
22. エクストリームプログラミング(XP) 初版(1999) 【12】 2nd Edition(2004) 【24】 現在 【19】 主要プラクティス (13) 導出プラクティス (11) 共同のプラクティス (4) 管理者のプラクティス (5) 計画ゲーム 全員同席 本物の顧客参加 イテレーション 責任の受け入れ 短期リリース チーム全体 インクリメンタルなデプロイ 共通の用語 援護 メタファ(比喩) 情報満載のワークスペース チームの継続 オープンなワークスペース 四半期ごとの見直し シンプルな設計 いきいきとした仕事 チームの縮小 ふりかえり ミラー テスト ペアプログラミング 根本原因分析 リファクタリング ストーリー コードの共有 開発のプラクティス (6) ペアプログラミング 週次サイクル コードとテスト テスト駆動開発 顧客のプラクティス (4) 共同所有 四半期サイクル 単一のコードベース ペアプログラミング ストーリー 継続した統合 ゆとり デイリーデプロイ リファクタリング リリース計画 40時間労働 10分ビルド 交渉によるスコープ契約 ソースコードの共同所有 受け入れテスト オンサイトのユーザ(顧客) 継続的インテグレーション 利用都度課金 継続的インテグレーション 短期リリース コーディング規約 テストファーストプログラミング インクリメンタルな設計 最適なペース YAGNI 22
23. ソフトウェアが生み出す成果を決める要素 問題設定力 開発力 チーム力 ✤ 適切な問題設定 ✤ ドメイン知識 ✤ 開発プロセス習熟 ✤ 明確なビジョン ✤ アーキテクチャ設計力 ✤ 心理的安全性 ✤ マーケットの理解 ✤ 開発言語 ✤ 透明性 ✤ 取捨選択 ✤ 性能 ✤ 検査と適応 ✤ 良いプロダクトバックログ ✤ セキュリティ ✤ ムダをなくす ✤ 優先順位付け ✤ インフラストラクチャー ✤ 学習 ✤ ステークホルダー管理 ✤ 自動化 ✤ リーダーシップ ✤ リスク・コスト管理 ✤ 品質・テスト ✤ オーナーシップ ✤ … ✤ … ✤ … 23
24. 共同のプラクティス 開発のプラクティス 管理者のプラクティス 顧客のプラクティス XP Scrum 反復 スプリント 共通の用語 (XPを活用) 開けた作業空間 (XPを活用) 頻繁なふりかえり スプリントレトロスペクティブ テスト駆動開発 (XPを活用) ペアプログラミング (XPを活用) リファクタリング (XPを活用) ソースコードの共同所有 (XPを活用) 継続的インテグレーション (XPを活用) YAGNI (XPを活用) 責任の受け入れ コミットメント 援護 スクラムマスター 四半期ごとの見直し スプリントレビュー ミラー デイリースクラム、スクラムボード 最適なペースの仕事 (XPを活用) ストーリーの作成 プロダクトバックログ リリース計画 スプリントプランニング 受け入れテスト 受け入れ基準 短期リリース リリース判断可能なインクリメント 24
25. レガシーコードを最初から作らないようにするには 具体的にはどうすればよいか?
26. レガシーコードを作らない9つのプラクティス 1. やり方より先に目的、理由、誰のためかを伝える 2. 小さなバッチで作る 3. 継続的に統合する 4. 協力しあう 5. CLEANコードを作る 6. まずテストを書く ScrumとXPからプラクティスを抽出。 全部やらなければいけないわけではないが 各項目は相互に関係性がある 7. テストでふるまいを例示する 8. 設計は最後に行う 9. レガシーコードをリファクタリングする 26
27. ✤ 今日はそのうちいくつかを紹介します 27
28. 1 やり方より先に目的、理由、誰のためかを伝える
29. 役割の違い ✤ プロダクトオーナーの責任 ✤ 開発チームの責任 ✤ ビジネス価値を最大化する ✤ リリース判断可能なプロダクトを作る ✤ プロダクトビジョンを周りに理解させる ✤ 設計、開発、テストをする プロダクトの結果責任 ✤ 決められた品質を満たす ✤ 合意したプロダクトバックログ項目を完成 させるように最善を尽くす ✤ ✤ プロダクトバックログの順番の最終決定 ✤ ステークホルダーをマネージする ✤ プロダクトオーナーにフィードバックする ✤ 予算を管理する ✤ 集中して仕事に取り組む ✤ リリース日を決める ✤ 問題があればそれを明らかにする ✤ 開発チームの成果物の受け入れ可否 ✤ 常に改善する など… など… 29
30. WhatとHowを分離する ✤ 何をほしいか、なぜ欲しいか(What)は顧客やプロダクトオーナーの領域 ✤ やり方は開発者の領域(How) ✤ 物事のやり方は1つではなく、やり方ごとにトレードオフがある ✤ やり方を明示されると選択や交渉の余地が減る ✤ 結果として手続き的なコードになりがち ✤ 双方が創造的に協調することで、無駄な時間や機能が減る ✤ 作る上で重要なのは、まず「コンテキスト」を共有・理解すること 30
31. ユーザーストーリー ✤ 「何が」「なんのために」「誰のために」存在するかを1文で表したもの ✤ (例) 映画ファンとして、チケットをオンラインで購入したい。そうすれば劇場で 列に並んで待つ必要がない 31
32. ユーザーストーリー ✤ 機能について会話できるくらいの辛うじて十分なドキュメント(仕様書ではない) ✤ 会話によってソフトウェアを作るための理解を深める ✤ 開発プロセスを円滑にするのは会話 ✤ 知識は詳細なドキュメントではなく、コード(テストも含む)にまとめるべき ✤ ストーリーが限定的であることで、テスト可能になる (受け入れ基準と自動化) ✤ ✤ 実例によるふるまいのテストが可能に シンプルに始めて追加はあとで行う (=> 2. 小さなバッチで作る) ✤ 漸進的に進めることで、良い設計が浮かび上がってくる 32
33. 2 小さなバッチで作る
34. 鉄の三角形 ✤ SCOPE スコープ QUALITY 品質 COST コスト DELIVERY 時間 ✤ 三角形の要素 ✤ Q => 品質 (Quality) ✤ C => コスト (Cost) ✤ D => 時間 (Delivery) ✤ S => スコープ (Scope) すべてのものを同時には満たせない 34
35. QCDSの何を調整するか ✤ 品質(Q)を調整する(下げる)と、あとから手直しに何倍もの時間を使うことになる 35
36. QCDSの何を調整するか ✤ コスト(C)を調整するとは、すなわち人を増やすことに繋がる ✤ だが、人を増やしても、オーバーヘッドによって成果はリニアには増えない ✤ 人月の神話 「遅れているプロジェクトに人を追加すると、更に遅れる」 ✤ 時間(D)を調整してもよいが、多くのビジネスは「時間」が重要 ✤ つまり、いちばん調整すべきなのは「スコープ」 ✤ およそ半分の機能はほとんど使われない ✤ スコープを調整して、価値あるものから順番に進める 36
37. タイムボックスによるアプローチ ✤ ✤ タイムボックス ✤ 固定の期間(リズム)の中でタスクに取り組む ✤ タスクの分割になれるまでは機能しやすい ✤ ScrumやXP 長い期間で大きなウソをつくのではなく、短いイテレーションで小さなウソをつく 37
38. 同じリズムを刻むことで負担を少なくして、異常に気づく 日々の仕事も同じ 38
39. リソース効率とプロセス効率 ✤ ✤ 1サイクルのリズムが長くなると、リソース効率化を目指しやすい ✤ 同時に着手するものが増える / タスク切換えが増える ✤ 役割分担が増える ✤ 最後にテストフェーズや統合フェーズが増える リリースサイクルのリズムが プロセスを制御する 1サイクルのリズムを短くすると、プロセス効率があがる ✤ 同時に着手するものを減らす必要(つまり1個流しのようなもの) 39
40. モブプログラミング = 究極の1個流し https://www.youtube.com/watch?v=p_pvslS4gEI https://www.youtube.com/watch?v=dVqUcNKVbYg 40
41. ソフトウェアの評価 ✤ ✤ ソフトウェアの評価は、顧客にとって価値あるものにもとづいて評価すべき ✤ 価値は「完成」して初めて価値になる ✤ 本当に価値が実現できているか? ✤ 価値実現までの時間が期待したとおりか? ✤ 部分最適化を避ける 効率より効果 41
42. フィードバックサイクル ✤ ✤ 小さなバッチのほうがフィードバックの回数は増える ✤ スプリントレビュー、レトロスペクティブ、継続的統合… ✤ 顧客やPOと同席することで、フィードバックの回数を増やす ✤ ビルドを高速化する フィードバックへの対応をサポートする文化が必要 ✤ ✤ 価値やリスクに応じて取捨選択する フィードバックをバックログに取り込む フィードバックによって価値を高める 42
43. 4 協力しあう
44. コミュニケーションと相互作用 ✤ ソフトウェア開発は社会的な活動で、 多くのコミュニケーションと相互作用を伴う ✤ 一緒に働くことでお互いから学ぶ(継続的学習) ✤ そのためにはオープンな空間が必要 44
45. ペアプログラミング ✤ 共通認識の形成(私だけのコード、私だけの秘伝の手順などをなくす) ✤ 良いプラクティスに従いながらお互い学び合う。新人の速度があがる ✤ 常にメンターであれ、常にメンティーであれ ✤ 多少時間がかかっても、複雑な問題を解決できるし、不具合も減少する ✤ 割り込みの削減 ✤ 変化型 ✤ ✤ バディプログラミングやモブプログラミング 効率より効果 昔は知識を独占することでキャリアを守っ たが、今は知識を共有することが重要に 45
46. ペアプログラミング ✤ 共通認識の形成(私だけのコード、私だけの秘伝の手順などをなくす) ✤ 良いプラクティスに従いながらお互い学び合う。新人の速度があがる ✤ 常にメンターであれ、常にメンティーであれ ✤ 多少時間がかかっても、複雑な問題を解決できるし、不具合も減少する プログラミングだけに限らず、すべての作業でペアは有効!! ✤ 割り込みの削減 ✤ 変化型 ✤ ✤ バディプログラミングやモブプログラミング 効率より効果 昔は知識を独占することでキャリアを守っ たが、今は知識を共有することが重要に 46
47. ペアプログラミングの7つの戦略 ✤ とりあえず1度試しにやってみる ✤ ドライバー(キーボードを操作する人)とナビゲーター(全体を見通す人)が参加する ✤ 役割は頻繁に交代する ✤ エネルギーを十分に保つ ✤ すべてのペアの組み合わせを試してみる ✤ 詳細はチームで決める ✤ 成果を測定してみる 47
48. レトロスペクティブ(ふりかえり)の7つの戦略 ✤ 小さな改善を繰り返す ✤ 人を責めずに、プロセスを責める ✤ なぜなぜ5回(5 Why) ✤ 根本原因を直す ✤ 全員の意見を聞く ✤ 改善に必要な権限を与える ✤ 進ちょくを測る 48
49. 5 CLEANコードを作る
50. 品質は検査では上がらない(再掲) Quality comes not from inspection, but from improvement of the production process.. Edwards Deming 50
51. よくないコードの特徴 ✤ 重複したコード ✤ データの群れ ✤ 仲介人 ✤ 長すぎるメソッド ✤ 基本データ型への執着 ✤ 不適切な関係 ✤ 巨大なクラス ✤ スイッチ文 ✤ ✤ 長すぎるパラメータリス ト ✤ パラレル継承 クラスのインタフェース 不一致 ✤ 怠け者クラス ✤ 未熟なクラスライブラリ データクラス ✤ 変更の偏り ✤ 疑わしき一般化 ✤ ✤ 変更の分散 ✤ 一時的属性 ✤ 相続拒否 ✤ 特性の横恋慕 ✤ メッセージの連鎖 ✤ コメント 『新装版 リファクタリング―既存のコードを安全に改善する』より 51
52. ✤ よくない例をあげると数限りなし… ✤ ✤ チームで理解して、よくない例を避ける必要はある 一方で、従うべきガイドラインも必要 52
53. CLEANコードとは? ✤ よいソフトウェアの土台となる5つのコード品質のこと ✤ 「オブジェクトは、特性が明確に定義されていて、はっきりした責務を担い、実装は隠 ぺいされているべきだ。オブジェクトの状態は自分自身が管理し、オブジェクトの定 義は一度だけにすべきだ。 」 53
54. CLEANコードとは? ✤ Cohesive (凝集性) ✤ Loosely Coupled (疎結合) ✤ Encapsulated (カプセル化) ✤ Assertive (断定的) ✤ Non redundant (非冗長) これらはテストしやすさと 密接な関係がある 54
55. Cohesive(凝集性) ✤ それぞれの部品は1つのことだけを扱う ✤ クラスが1つの責任に集中する ✤ つまり名前をつけられるアイデアや概念になる ✤ ✤ 名前重要 複雑なものはコンポジション ✤ 概念をネストする 55
56. Loosely Coupled(疎結合) ✤ オブジェクト間の関係を明確な意図をもった状態に保つ ✤ サービスを直接呼び出すのではなく中間層を経由する ✤ ✤ コードにつなぎ目を入れておく 全てが悪なわけではない ✤ 意図的な結合と不慮の結合 ✤ 不慮の結合はコード品質が低いときによく現れる ✤ なんでもできる神APIを避ける ✤ 再利用という名目のもとにコードの品質を犠牲にしてはいけない 56
57. Encapsulated(カプセル化) ✤ 実装の詳細は外から見えなくなっている ✤ オブジェクト指向の最大の利点 ✤ インターフェースと実装を切り離す ✤ アウトサイドインプログラミング ✤ ✤ コンシューマー(呼び出し側)の観点で機能を設計する ✤ 何をやっているかを示す名前をつけて、どう動くかは隠す ✤ 全体と詳細を行き来するが、まずは全体から始める 公開しているものを隠すより、非公開のものを後から公開するほうが簡単 57
58. Assertive(断定的) ✤ 自分自身の責任は自分で管理する ✤ オブジェクトがフィールドなどを持つなら、それらを管理するふるまいも持つ ✤ 好奇心旺盛すぎてはいけない ✤ ほかのオブジェクトの状態を頻繁に参照するのを避ける ✤ 特性の横恋慕、不適切な関係 58
59. Non redundant(非冗長) ✤ 同じことを繰り返してはいけない(DRY原則) ✤ 意図的に冗長性を組み込むことはあるが、それはあくまで意図による ✤ 冗長さは状態やふるまいだけに限らない ✤ ✤ 冗長なテスト、冗長な概念、冗長な解釈、冗長なプロセス… コードが違うから冗長でないというわけではない 59
60. CLEANのメリット テストしやすさが 設計や実装の品質を計測する 基準になる ✤ (C) 凝集性があれば、理解もバグを見つけるのも簡単 ✤ (L) 結合度が低ければ、副作用が減り、テストや再利用、拡張が簡単 ✤ (E) カプセル化されていれば、呼び出し元が実装の詳細を知らなくてもよいように 維持できる。あとから変更するのも簡単 ✤ (A) 断定的であることは、ふるまいを配置する場所が依存データがある場所である ことを示す ✤ (N) 冗長でなければ、バグ修正や変更は1箇所で1回だけやればよい 60
61. CLEANとテストでバグ発見の時期をシフトレフトする Capers Jones, Applied Software Measurement: Global Analysis of Productivity and Quality 61
62. 明日のベロシティのために今日品質を上げる ✤ 速度は日々の積み重ねによってしか実現できない ✤ CLEANコードは理解しやすく取り組みやすい ✤ 高品質のコードは拡張しやすい ✤ 高品質のコードはデバッグしやすく保守しやすい ✤ 結果的に総所有コストが下がる ✤ 逆の状態が「技術的負債」 62
63. https://flickr.com/photos/joanbrebo/38646019434 63
64. https://flickr.com/photos/joanbrebo/38646019434 すばやく働くということは「きれいに働く」ということ 64
65. これって5Sだった ✤ 整理 => いらないものを捨てる ✤ 整頓 => 決められた物を決められた場所に置き、いつでも取り出せる状態にする ✤ 清掃 => 常に掃除をする ✤ 清潔 => 3S(上の整理・整頓・清掃)を維持し職場の衛生を保つ ✤ 躾 => 決められたルール・手順を正しく守る習慣をつける 65
66. 8 設計は最後に行う
67. ソフトウェアは書く回数より読む回数の方が多い
68. あくなき追求 ✤ いかにバグを取るかではなく、いかに保守しやすいかという設計に注意を払う ✤ ✤ 良いコードとは変更しやすいコード 変更しにくいコードをみつけて、それらを取り除いていく ✤ カプセル化の欠如、継承の過度の利用、具体的すぎる実装、インラインコード、 依存性、自身によるオブジェクトの新規生成 ✤ テストがあれば安全にコードをクリーアップできる ✤ コードが動作して、テストのサポートがある状態から設計を良いものにする ✤ コーディングとクリーニングは分離する 68
69. 持続可能な開発 死んだコードを消す コメントアウトされたコード、呼び出されないコード、使わない機能は全部消 す。存在しても注意が散漫するだけ 名前を更新する メソッドやクラスの名前を意図のわかる良い名前に更新する。 開発を進めて 分かったことが増えると機能が変わる。今やっていることを反映する名前に 判断を集約する 判断を集約し、1 回だけで済むようにする。冗長なコードも削除できる 抽象化する すべての外部依存性には抽象を作成し利用する。モデルに欠けているエンテ ィは作成する クラスを整頓する 利用範囲においてモデ ルが完全であることを確認する。そうすることで、正し いふるまいと正しい属性を持つようにクラスを整頓できる 69
70. 持続可能な開発 死んだコードを消す コメントアウトされたコード、呼び出されないコード、使わない機能は全部消 す。存在しても注意が散漫するだけ 名前を更新する メソッドやクラスの名前を意図のわかる良い名前に更新する。 開発を進めて 分かったことが増えると機能が変わる。今やっていることを反映する名前に 抽象化する すべての外部依存性には抽象を作成し利用する。モデルに欠けているエンテ ィは作成する クラスを整頓する 利用範囲においてモデ ルが完全であることを確認する。そうすることで、正し いふるまいと正しい属性を持つようにクラスを整頓できる ソフトウェア開発はあとから分かることが多い それを随時反映していく 判断を集約する 判断を集約し、1 回だけで済むようにする。冗長なコードも削除できる 70
71. レガシーコードからの脱却 (まとめ) ✤ 使われるソフトウェアは変更が必要になるので、コードは変更可能になるように書くべき ✤ プロダクトオーナーは、目的、必要な理由、誰のためのものかが伝わるようにする ✤ 要求は意味のある小さな単位にして、重要なものから作る ✤ 小さなバッチで関係者が協力しながら作っていく ✤ コードはテストコードも含めてCLEANを維持し、常に品質を満たすように作っていく ✤ 必要に応じて設計を見直したりコードを見直したりする。良い設計は創発する 71
No comments...
Attractor Inc. Founder / CTO / Agile Coach / Certified Team Coach / Certified Scrum Professional / Certified ScrumMaster / Certified Scrum Product Owner Twitter : @ryuzee Web : https://www.attractor.co.jp/ Web : http://www.ryuzee.com/

Related Slides