余白

https://blog.lacolaco.net/ に移転しました

ソフトウェア設計を学びたい人々にまず教えるべきことはテスト技法ではないか

根本の問題意識

  • ソフトウェアの設計スキルはどのように獲得する(させる)ことが効果的であるのか

ソフトウェアアーキテクチャの目的

  • そもそもソフトウェアアーキテクチャはどのような欲望を満たすための方法か

ソフトウェアアーキテクチャの目的は、求められるシステムを構築・保守するための必要な人材を最小限に抑えること である。 (CLEAN ARCHITECTURE)

  • 「求められるシステムを構築・保守するための必要な人材を最小限に抑えたい」
    • => 構築容易性 と 保守容易性 を確保したい
  • 構築容易性
    • 「構築しやすさ」とは?
      • ソフトウェアを構築するとはどういうことか
    • ソフトウェアの2つの価値: 「振る舞い」と「構造」
      • 振る舞い: 要件を満たすこと => いわゆる機能
      • 構造: 振る舞いを簡単に変更できること => いわゆるアーキテクチャ
    • 構築しやすさ=価値の生み出しやすさ
      • 要件を満たしながら振る舞いを変更し続けられること
      • つまり構築容易性は変更容易性が必要になる
  • 保守容易性
    • 「保守しやすさ」とは?
      • 「要件を満たし続けていること」の検証と維持
    • つまりテスト容易性が必要になる

ここまでのまとめ

  • ソフトウェアアーキテクチャとは何のためのどのような方法か
    • 目的: 構築容易性 と 保守容易性 を確保したい
    • 方法: ソフトウェアに変更とテストが容易となる構造を導入する

変更容易性とテスト容易性

Image https://www.thomasalspaugh.org/pub/fnd/ility.html

  • どちらも 保守性 (Maintainability) に含まれる
  • つまり構造の価値とは
    • Portabilityã‚„Usabilityの要求を満たすための「振る舞い」を維持し、新たな要求に応える労力を最小化しつづけること
    • Maintainability: Code possesses the characteristic maintainability to the extent that it facilitates updating to satisfy new requirements or to correct deficiencies. This implies that the code is understandable, testable and modifiable;

  • 変更が容易であるためには、変更が既存の振る舞いを壊さないこと=要件を満たし続けられていることの確証が必要
    • 変更容易性はテスト容易性・理解容易性に支えられている
  • また、変更容易性はソフトウェアを変更しようとしてはじめてわかる
    • 言い換えれば、変更容易性はソフトウェアを変更しようとしたときの抵抗の逆数である
  • だがソフトウェアの変更の契機は要求の変更であり、内発的に始動するものではない
    • また同じソフトウェアに同等の変更が繰り返し加わることはない(それは変更ではない)
  • ゆえに 変更容易性を直接評価することは難しい
    • 間接的にはMTTRやデプロイ頻度が指標になるが、測りたいときに好きに測れる特性ではない
  • 保守性を高めようとする営みは、まず理解容易性かテスト容易性の改善が内発的に始まり、変更容易性はその結果として間接的に改善されることになる

ここまでのまとめ

  • 変更容易性はそれ自体を直接評価することが困難である
    • 変更容易性はテスト容易性・理解容易性に支えられている
    • ソフトウェアの変更の契機は要求の変更であり、内発的に始動するものではない

保守性と複雑性

Image https://speakerdeck.com/twada/agility-and-quality-characteristics-developers-summit-2021-summer?slide=28

  • 複雑性が理解容易性と変更容易性を損なう
  • ところで
    • "変更容易性はソフトウェアを変更しようとしたときの抵抗の逆数である"
  • 同様に、理解容易性はソフトウェアを理解しようとしたときの抵抗の逆数であるといえる
    • フィードバックとして得られるのは抵抗 = 複雑性
    • 変更しようとしないと変更容易性は評価できない
    • 理解しようとしないと理解容易性は評価できない
  • 容易性の問題
    • 人間の問題
      • 3つの容易性は「人間にとって」容易であることを評価するもの
        • なぜならまだ人間がソフトウェア開発をしているから
      • 人間は慣れてしまう
        • 同じ人間が同じ対象で容易性を繰り返し評価することは難しい
    • 偶然性の問題
      • 試行回数が少ないと、偶然性に影響を受けやすい
      • ある変更は容易だが別の変更は困難な構造
      • ある人には理解しやすいが別の人には理解しにくい構造
    • 評価の頻度と観点の多様性が重要

ここまでのまとめ

  • 容易性は実際にやってみようとしたときの抵抗の逆数でしか評価(観測)できない
  • 人間は変化するため同じ対象を繰り返し評価することが難しい
  • 試行回数の少ない事柄の容易性は偶然性の影響を受けやすい
  • ではどうやって保守性を評価し、改善につなげるか

テスト容易性とフィードバックサイクル

  • テスト容易性もテストしようとしたときの抵抗の逆数である
    • テストしようとしないとテスト容易性は評価できない
  • テストは開発者の内発的な始動が可能である
    • 要件が変わっていなくてもテストを書くことはできる
  • 変更・理解・テストのなかで、もっとも試行回数を増やしやすく、学習(抵抗の観測)を素早く行えるのがテスト
  • つまり保守性の中でテスト容易性がもっとも評価と学習の容易な副特性である

ソフトウェアアーキテクチャとテスト

  • テスト容易性は複雑性を評価するひとつの見方であり、そのすべてではない
    • テストしやすさだけに傾倒するあまり、行き過ぎた抽象化で理解容易性を損なうこともある
  • とはいえもっとも手軽に複雑性を軽減するための取っ掛かりを作れるのはテスト容易性である
    • テストされていれば他に問題があってもあとから変更しやすい
  • それゆえにソフトウェアアーキテクチャの方法論は「テストしやすく作る」が語られやすい

設計スキルの向上

Image https://speakerdeck.com/twada/quality-and-speed-2020-autumn-edition?slide=82

  • この経験とは何の経験か
    • アーキテクチャの経験とは構造の経験
    • つまり変更・理解・テストの経験である
  • 「自分で設計したシステムを長い間メンテする」の意味
    • 変更・理解・テストをすべて経験する × 時間
    • 当然経験としての効果が高い
  • そうした機会に恵まれないプログラマーがどのように経験値を稼ぐか
    • 変更・理解・テストのうち日常的かつ自発的に行えるのはテストである
    • たくさんテストを書くことで「どのようなコードがテスト容易性を損なうか」を経験する
    • テスト容易性というひとつの視点からソフトウェアの複雑性を捉える判断力を身につける
  • 「テストを書く習慣」
    • テスト駆動開発は個人の習慣をチームのワークフローとして拡大する
    • さらに進めばテストされていないコードをデプロイさせないルール化(品質管理)へ
  • アーキテクチャに必要な判断力にテストの経験は不可欠
    • より効果的なテストをより早く書けるようになる
      • 早く描くには上手くなる。上手く描くにはいっぱい描く。いっぱい描くには早く描く。(SHIROBAKO)

  • であれば、保守性に優れたソフトウェアの開発を志す人々にまず教えるべきことはなにか
    • 設計技法は複雑性を抑制する方法であって、複雑性を認識する方法ではない
    • 複雑性を認識するには、「抵抗」を観測する技術を身につける必要がある
    • その方法としてもっとも学習に適しているのはテスト技法ではないか
      • もちろんそれだけではないが
        • 理解容易性から学習する方法の例: たくさんのコードを読み、理解しやすさを左右する構造の特徴を感じ取る
        • 変更容易性から学習する方法の例: 要求の変更が頻繁に起こる環境に身を置き、変更しやすさを左右する構造の特徴を感じ取る
      • テスターの経験がプログラマーとしての成長に寄与するようなことも説明がつく
  • 保守性の高い構造を学習するために、たくさんテストを書くことから始める
    • どうテストすればよいかわからないものをどうしてうまく設計できるだろうか

結論

  • ソフトウェアアーキテクチャの目的はソフトウェアの保守性である
    • 保守性のための方法としてソフトウェアに「構造」を導入する
  • 保守性を構成する3つの容易性
    • その中で開発者にとって評価と学習がもっとも容易なのは「テスト容易性」である
    • アーキテクチャの判断力の習得には経験が不可欠
      • 日常的かつ自発的に増やせるのはテストの経験である
  • であれば、保守性に優れたソフトウェア設計を学びたい人々にまず教えるべきことはテスト技法ではないか
    • 設計技法は複雑性を抑制する方法であって、複雑性を認識する方法ではない
      • 自分では知覚できない脅威に備えるための方法論は実感を伴わないおまじないになる
    • 複雑性を認識するには、「抵抗」を観測する技術を身につける必要がある
    • その方法としてもっとも学習に適しているのはテスト技法ではないか
      • 複雑性を認識できるようになることで、それを抑制・制御するための設計技法の必要性を身を持って理解できる
  • 保守性の高い構造を学習するために、テストを書くことから始める
    • まずテストから書き始めるテスト駆動開発は学習の面からも理にかなった方法論であるといえる