認定スクラムデベロッパー研修(CSD)に参加してきました。
2020/3/2~6に開催された、アギレルゴコンサルティングさん主催『認定スクラムデベロッパー研修(CSD)』に参加してきました。
業務多忙の中、またコロナウィルス関連でいろいろな混乱の中で、参加を快諾していただいたプロジェクトメンバーと、家族に感謝です。
(追記:あと当然ですが、こんな状況の中で来日していただき、講師を努めてくれたデビット・バーンスタインさん、開催&会場提供していただいたアギレルゴコンサルティングさんにも感謝です!!書き忘れてた・・)
認定スクラムマスター研修(CSM)を2019年04月に受講していたので、自分にとっては2つ目の認定研修でした。 ちょっと研修から日程が経過してしまいましたが、改めて思い出しながらアウトプットしていきたいと思います。
参加までの思い
アジャイルにはスクラムのようなプロセスのフレームワークと、XP/TDDのようなテクニカルなプラクティスがあって、CSD研修はこのうちの後者のテクニカルな部分を5日間どっぷり学ぶ研修ということで、参加前からとても楽しみにしていました。
アジャイル開発というと、とかくスプリントやリリースサイクルのほうに話が向かいがちで、技術の部分が置き去りになってしまう傾向にあるような気がしていました。
スクラムをしっかり実践するのは重要ですが、それはテスト駆動開発やXPをしっかり実践することが前提となっていて、その上にでないと成立しないだろうという考えがずっと自分の中にありました。
動作可能なインクリメントを追加し続けて、変更前のプロダクトに影響がないことを確認するには、テストコードとCI環境が不可欠で、それがないとイテレーションが進むたびにリグレッションテストの工数が膨張するし、問題発生時の影響調査もどんどん複雑化します。
自分としては、テクニカルな部分がアジャイルを実践する上で基礎にあたる部分だと思ってます。
しかし、スクラムガイドにはテストコードを書けとは書いていないし、その部分について語られる機会も少ないように思います。
実際、テストコードの効果を感じたことのない人にテストコードの価値を説明するのは想像以上に大変です。非エンジニアのマネージャーとかだともっと大変です。
テストコードはあればあったに越したことはない、でも書きすぎるとテストコードのメンテナンスコストも上がるから微妙、といった意見もよく聞きます。
テストコードは早起きみたいなものだという例えはとても的を射た表現だと思います。
そういう意見のある中でテストコードを推進しつづけるというのはなかなか消耗するし、自分の思いをうまく言語化できないことにも無力感を感じていました。
テストコードのメリットを受け続けながら、greenなコードをメンテしつづけるにはどうしたらいいのか。
テストコードを書きたがらないチームメンバーにどう説得するのか。
テストコードのためのコストをマネージャにどう説明するのか。
こういうことを人に説明するには、まず自分がもっと体系立ててロジカルに理解する必要がある、という思いがありました。
前フリがだいぶ長くなってしまいましたが、研修参加前の自分の心境はこんな感じでした。
研修メモ
ここからは研修時の主に講義の部分のメモです。
保守可能なコードをどう書くか
- 技術的負債のないコードとはどういうものか
- 他のだれかが保守できるようにするとはどういうことか
- それは、ソフトウェアを未来に渡って価値のあるものにするということ
- ふつうに動作するプログラムを書くだけなら誰でもできる
- 他の人が理解できる美しい書き方をするというのはとても難しい
- ほとんどの人はそれがあまりできていない
- でもそれは創造的で面白いこと
- リファクタリングについて
- 自分が美しいコードを書いたと思っても、何がうまくいっているのか、正しく行われているか。
- リファクタリングのゴールが見えない問題
- そのリファクタリングは他の人にとっても、うまくいっていると言えるのか
- じゃあどうリファクタリングすればいいのか
- 自分が美しいコードを書いたと思っても、何がうまくいっているのか、正しく行われているか。
- その一つの答えが、デザインパターンを使うこと
ユーザーストーリー
- ユーザーストーリーを作成し、それをさらに分割して下に伸ばしていく
- ストーリーをどうやって分割するか
- サイズを小さくする
- INVEST
- ストーリー間の依存関係を排除する
- ストーリーに詳細は入れない。あとでいい。
- ユーザーストーリーとは、、
- 話し合うことを「約束」すること
- ユースケースとは違う
- 要件とも違う
- 複合型のストーリー
- 分解してシンプルにすべき
- 複雑なストーリー
- 未知の要素があるから複雑になる
- 知っていることとわからないことを分離する
- 未知のところに対してイテレーションする
- 知っていることが増えるほど、複雑でなくなる
- 良いストーリーはテストしやすく、コーディングしやすい
デザインパターン
デザインパターンとは
- 抽象化によって世界をシンプルにして理解しやすくするための方法
- デザインパターンは本質を理解することが大事
- 本質さえ理解してしまえば暗記する必要はない
- もしかしたら既に使っているかもしれないし、まだ名前のないものもあるかもしれない
継承よりも集約
- 伝統的に継承を使いすぎてしまっている
- なぜ継承を多用してしまったか?
- 歴史が浅かったため、継承による弊害が見えていなかった
- なぜ継承を多用してしまったか?
- 実際に使わないメソッドまで作ってしまう(getterやsetterはcode smell)
デザインの第一原理
- オープンクローズドの原則
- 拡張のために開かれていて、変更には閉じられている
- できれば、何も既存のコードを変えずに、新しい機能を追加する
- 拡張のために開かれていて、変更には閉じられている
- 単一責任の原則
- 変更する理由が一つ
- 変更を加えるために必要な変更は一箇所になる
- 変更する理由が一つ
- 依存関係逆転の原則
- 呼び出し側が何を欲しがるのか
- APIが呼び出し側に合わせるほうがかんたん
パターンとは知恵
- アイデアが詰まっているが、理解しにくい
- 3D立体視のようなもので、普通に見てもなかなか見えないが、コツがわかればある日突然浮かび上がってみえるようになる
- 再利用できるソリューション
- 問題の中にパターンを見つける
- デザインパターンを学ぶことでオブジェクト指向をより深く理解できる
- パターンは高品質なコミュニケーションツールとして使うことができる
- 概念化
- 説明のしやすさ
- コーディングのしやすさ
- デザインを他者に伝達のしやすさ
パターンをうまく利用するためのいくつかのフォース
- 「文脈」的なフォース
- いつ、どんな状態のときにそのパターンが発生するか
- メタファを用いる
- 使い分けが必要
- 拡張性が必要ならストラテジーが使えるが、そうでないならコストの無駄
- いつ、どんな状態のときにそのパターンが発生するか
- 「実施」のためのフォース
- 問題解決のために仕様するパターンの種類
- パターンの適用のしかたは一つではない
- 問題解決のために仕様するパターンの種類
- 「帰結」のフォース
- パターンを適用した後の結果の良し悪し
- 何をカプセル化することで、どれくらい保守性が向上するか
- パターンを適用したらテストができるようになった、など
- 何をカプセル化することで、どれくらい保守性が向上するか
- パターンを適用した後の結果の良し悪し
- そして一番重要なフォースは「意図 - intent」
- 「意図」を通してパターンを眺めることで、より深く理解できる
XP
アジャイルをエンジニアに取り戻せ
- アジャイルマニュフェストは17人エンジニアが作った
- 17人は全員エンジニア
- 継続的デリバリーやテスト駆動開発といった「技術的な卓越」がなければアジャイルはできない
- クリーンなコードを書く習慣が重要
- いつしかアジャイルはマネジメントに利用され、認定マシンと化してしまった
TDDメリット
- デザインの原則
- 関心事の分離
- タスク分割
- 回帰テスト
TDDの失敗
- TDD is dead?
- テストのリファクタリングに時間がかかる
- テストもコードなので、製品コードと同様に品質をもとめるべき
- コードカバレッジに意味のある数字は100%
- 単純なgetterもsetterも中に入っている
- 80%にするとどうなるか?
- カバレッジを保つために単純なメソッドテストコードを集中して、複雑で重要な部分を後回しにしてしまう
- ただし、テストする意味のないコードに対してまで100%である必要はない
- ようは、ちゃんと説明できればいい
XPのプラクティス
- who->what->why->howの順でやる
- 細かく指示しない
- what->ビジネス側
- how->開発者
- howをビジネス側の人間に握らせない
- 彼らがソフトウェア開発をしてはいけない
- ビジネスの専門家、テクニカルレベルが一番低い人が要求をつくる
- お客さまが必要なものをソフトウェアに翻訳する能力があるのは開発者
- 共に働く
- コミュニティ開発が必要
- swarming
- ペア
- 重いものをみんなで運ぶようなもの
- コミュニティ開発が必要
- クリーンなコード
- CREATE CLEAN
- テストで振る舞いを特定する
- コンセンサスが得られるTDDのやり方
- マネージャーだけでなく、他のデベロッパーも説得する必要がある
- 合意可能なしきい値を設ける
- 振る舞いを特定する部分にのみテストを書く
- テストのやりすぎは、やらなすぎより悪い
- コンセンサスが得られるTDDのやり方
- TDDは設計のためのもの
- 設計は最後に実装する
- レガシーコードをリファクタリングする
ソフトウェア開発は社会的活動である
- チームメンバーは一緒に意思疎通をしながら働く必要がある
- 共通理解
- 共通言語
- 助け合い
- ペアプログラミング
- この効果について、マネージャーの説得が最も難しい
- よいコードが書ける
- 楽しい
- スピードが上がる
- どうやってペアを組むか
- ランダムにペアを組む
- 自分と考えが違う人、視点が違う人など
- ストロングスタイルペア
- "頭の中のアイデアがコンピューターの中にいくには、他の誰かの手を通していかなければならない"
- ピンポンペア
- 片方がテストを書いて、もう片方がそれをパスするコードを書く
- ペアプログラミングの恩恵
- プログラム時間が15%増加
- 集中できて、割り込みも発生しなくなる
実習のメモ
ここからは3日目〜5日目に行った実習のメモと思ったこと
TDDの3ステップ
- red
- 期待を定義
- green
- 動作させる
- gold
- きれいに仕上げる
レッドバーをグリーンに変える
- 必ず最初に失敗させることが大事
- なぜ失敗させるか
- テストがちゃんと稼働して、エラーの場合にちゃんと失敗が検出されることが保証されていることを確認する
- celebrate the red bar
- 失敗するテストに価値がある
- being green
- グリーンを保つことが難しい
- セーフティネット
refactor code
- 冗長性を排除
- カプセル化
- デザインパターンを追加
- デザインはリファクタリングのフェーズで実装する
- テストもリファクタリングする
- 3ステップを守ることで、いつごまかしのコードを実装して、いつ正しいコードを埋め込むかのリズムを教えてくれる
良いテストの条件
- 常に既知の理由で失敗する
- 他の理由で失敗しない
- ユニークである
- 同じ理由でシステム内の他のテストが失敗することはない
ユニットテストとは「振る舞い」に対するテスト
- よくメソッド向けにテストを書きがち
- 振る舞いは「what」
- howではない
レガシーコードクライシス
- コードを書き直すと、新旧の2つのコードを保守する必要がうまれる
- リファクタリングはコードをクリーンにするだけで新機能を生み出さないので投資効果がない
- マネージャーが理解できることは2つ
- コスト
- 利益
- 変更のコストが下がるということがメリット
- マーティンファウラーは「リファクタリング」で、コードを安全に変えられることを証明した
- 「ユニットテストコードのないコード」をレガシーコードと定義
まとめ・感想
師に会える機会って人生でそんなに多くない
テストの書き方とかデザインパターンとかをちゃんと教えてくれる先輩に恵まれた人は、きっと相当ラッキーな人で、普通はなかなかそういう人に巡り合うことはないと思います。
私もずっと独学でやってきたので、もっといい方法があるだろうなとずっと思ってきたし、コンフォートゾーンにいるとなかなか新しいテクニックを身につける機会はないと思います。
davidさんに直接レクチャーしてもらえる機会は自分にはとてもプライスレスな時間でした。
デザインパターンは自分的には「カンフー」
スクラムの文脈では合気道がよく引き合いに出されて、守破離とか型の話がよく出てくると思いますが、今回デザインパターンで私が思ったのは「カンフー」かなと。
問題に対してパターンを適用して対応する様子はかっこいいし、パシッとハマった時の気持ちよさがあると思いました。
そしてデザインパターンは、davidさんも言うようにとてもわかりにくい。
でも本質を押さえてさえおけばそんなに全部覚える必要もないし、上段・中段・下段くらい覚えておけばある程度対応できるんだなーというのがわかったのが、とてもいい収穫でした。
TDDは設計のためのもの
ウォーターフォールの現場だとテストは品質保証のために行うものになっているので、テストコードにもそれと同等の価値を求めがちだけど、もともとのテストコードは設計のためのもの、という本来の目的を体験できる研修でした。
テストコードが振る舞いを保証してくれるからこそアグレッシブな内部実装の変更を行えるし、パターンの適用でコードの見通しがよくなり、保守性が上がっていく。
そして、品質を高めるのはあくまでコードであって、テストは振る舞いを定義するもの。
こうすることで修正変更時のテストコードの変更が最小限でよくなり、テストコードが変わるということは振る舞いが変わったということなので変更もしやすいという、とてもわかりやすい考え方だと思いました。
ストーリーの完成度
ラボでdavidさんが用意してくれた実習の課題がよく考えられてるなーと思いました。
コードしやすく、テストも書きやすい単位で分割されていて、なるほどこういうふうにバックログを作ると開発チームはとても楽だなという、模範的なストーリーでした。
責務が分割されていて適度なサイズでテストもコードもしやすく、そういうところはさすがという感じでした。
まとめ
いろいろとダラダラ書いてしまいましたが、5日間の中でデベロッパーとしての大切なお作法が凝縮されているとても高密度な研修とラボでした。
なぜTDDなのか、なぜデザインパターンなのか、それをどう適用するのか、実際にやってみるあたりを一気通貫で体験できて、世界的な第一人者に教えてもらえるっていうのは、ほんとに贅沢な時間でした。
自分の中でもやもやしていた部分についても自信がついたと感じています。
今後学んだことを現場で生かしていきたいし、若いエンジニアに少しでも広めていきたいという思いが強くなりました。
あと、マネージャーに対してもより説得力のある説明ができるように、今後も深堀りしていきたいと思います。
davidさんに教えてもらったマネージャーに説明するメタファがこちら
レガシーコードに対して修正を加えるということは、シンクが洗い物でいっぱいになったキッチンでディナーの準備をするようなもの。まずは洗い物をしないとパーティーはできない。
洗い物は溜めずに都度洗いましょう。