連載
NAgileで始める実践アジャイル開発

第2回 ソフトウェア開発をシンプルにする考え方のコツ

福井コンピュータ株式会社 小島 富治雄
Micosoft MVP 2005 − Visual C#)
2005/11/05

■■「シンプルさ」にコミットする演習 ― 実際のDateクラスのソース・コードの実装■■

さて次は(そのクラス仕様を実現する)「Dateクラスの実装」だ。まず、Dateクラスのコンストラクタの内容だが……。

public Date(int year, int month, int day)
{
  this.year  = year ;
  this.month = month;
  this.day   = day  ;
}

 ここにどういうコードを書き加えようか。

   

えーと、ですから、まず年の値が1以上かチェックして、それから……。

   

待て待て。お前にもう一度いっておく。

「どうやって作ろうか」(How)と思い悩むな。

「何を作ろうか」(What)と考えろ。

 つまりここはこんな感じでいい。

public Date(int year, int month, int day)
{
  this.year  = year ;
  this.month = month;
  this.day   = day  ;

  if (!日付として正しい)
    throw new ArgumentException();
}

 要するにここに書き加えたい処理は、

「日付として正しくなければ例外を投げる」

ということだ。それこそが、ここに書き加えられるべきものだ。だったら、素直にそう書け。書きたいことを日本語で考え、それをそのままC#に直訳して書く。

書きたいこと:
 「日付として正しくなければ例外を投げる」

それをC#に直訳したもの:
「if (!日付として正しい) throw new ArgumentException();」

 それがシンプルな考え方だ。

   

えっ!? でも「日付として正しい」なんて書いてもコンパイル通りませんよ!

   

だったら、取りあえずこう追加するんだ。

private bool 日付として正しい
{
  get { return true; }
}

 そしたら、これ(=Dateクラスの実装)をさっきの「動く設計書」(=Dateクラスの仕様)とともにビルドして、生成された.EXEファイルや.DLLファイルをNUnitで動かして検証だ。すると次のように、設計書と違っている部分が赤く表示される。こんなふうに。

動く設計書と実装コードの食い違い(ほとんどエラー)
赤い部分が「Dateクラスの実装」として満たされていない「Dateクラスの仕様」である。
   

そして次に、いまの「日付として正しい」の実装をこう書き直す。

private bool 日付として正しい
{
  get { return 年が正しい && 月が正しい && 日が正しい; }
}

 これはつまり、

「『日付として正しい』というのは『年が正しくて、月が正しくて、日が正しいこと』」

ということだ。それをそのままC#で書いただけだ。後は、取りあえずビルドが通るように、次のように書き足す。

private bool 年が正しい
{
  get { return true; }
}

private bool 月が正しい
{
  get { return true; }
}

private bool 日が正しい
{
  get { return true; }
}

 またここまでの実装コードを「動く設計書」とともにビルドして再びNUnitでチェック。まだ赤の部分は減っていないことが分かる。

 この後もやることは同様だ。いま追加した3つのプロパティの実装内容を、次のように書き直す。

「『年が正しい』というのは『一年以上であること』」

private bool 年が正しい
{
  get { return year >= 1; }
}

「『月が正しい』というのは『一月から十二月の間であること』」

private bool 月が正しい
{
  get { return (month >= 1 && month <= 12); }
}

「『日が正しい』というのは『一日から月の最終日の間であること』」

private bool 日が正しい
{
  get { return (day >= 1 && day <= 月の最終日); }
}

 で、ビルドが通るように、再び未定義の部分を取りあえず書く。

private int 月の最終日
{
  get { return 31; }
}

 以上の実装コードを「動く設計書」とともにビルドして、NUnitでチェック。だいぶ赤いところが減ってくる。

動く設計書と実装コードの食い違い(かなりエラーが減った状態)
   

次に、月の最終日の中を、

「『月の最終日』は二月なら二月の最終日だし、四・六・九・十一月なら三十日だし、それ以外なら三十一日だ」

と書き換える。つまりこうだ。

private int 月の最終日
{
  get
  {
    switch (month)
    {
      case  2:
        return 二月の最終日;
      case  4: case  6: case  9: case 11:
        return 30;
      default:
        return 31;
    }
  }
}

 この後も同様なので少しとばすぞ。

「『二月の最終日』はうるう年なら二十九日で、そうでなければ二十八日だ」

private int 二月の最終日
{
  get { return うるう年か ? 29 : 28; }
}

「『うるう年か』は、年が4で割り切れてかつ100で割り切れないか、または、400で割り切れるか」

private bool うるう年か
{
  get { return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; }
}

 以上の実装コードと「動く設計書」をビルドしてNUnitでチェック。すると次のように、赤いところがなくなって、すべて緑になる。

Dateクラスの実装コードが動く設計書の仕様を満たして完成(すべて成功)
   

「動く設計書」に書かれたとおりの仕様でDateクラスの実装が完成した、ということだ。つまり、ソース・コードが書き上がったと同時に設計書どおりであることが、NUnitによる検証で明らかにされたわけだ。

 さあ、全体のプログラムは以下のようになった。

public class Date
{
  int year  = 2000;
  int month =    1;
  int day   =    1;

  public Date(int year, int month, int day)
  {
    this.year  = year ;
    this.month = month;
    this.day   = day  ;

    if (!日付として正しい)
      throw new ArgumentException();
  }

  private bool 日付として正しい
  {
    get { return 年が正しい && 月が正しい && 日が正しい; }
  }

  private bool 年が正しい
  {
    get { return year >= 1; }
  }

  private bool 月が正しい
  {
    get { return (month >= 1 && month <= 12); }
  }

  private bool 日が正しい
  {
    get { return (day >= 1 && day <= 月の最終日); }
  }

  private int 月の最終日
  {
    get
    {
      switch (month)
      {
        case  2:
          return 二月の最終日;
        case  4: case  6: case  9: case 11:
          return 30;
        default:
          return 31;
      }
    }
  }

  private int 二月の最終日
  {
    get { return うるう年か ? 29 : 28; }
  }

  private bool うるう年か
  {
    get { return year % 4 == 0 && year % 100 != 0
              || year % 400 == 0; }
  }
}
本稿で作成したDateクラスの実装コードの完成版

■■「シンプルさ」にコミットする演習のまとめ ― シンプルに考えるという態度■■

重要なことは、プログラムのすべての部分がシンプルであることだ。この場合それは、自分の「その部分の処理は何か?」という考え(=仕様)と、実際の実装コードが一致していることだ。

 今日はC#で書いているし、説明を分かりやすくするためにprivateなメソッドは日本語で書いてみた。だが、お前やお前のチーム・メイトにとってC#よりもVB.NETの方が「よりシンプル」ならそうしろ。また、日本語のメソッド名より英語のメソッド名の方が「よりシンプル」ならそうすればよい。

 いいたいのは、「何を書くか決めてそのとおりに書く」ということ。つまり、次のような手順だ。

  1. 何(What)を作ろうか、それをまず記述する → 「動く設計書」に
  2. 何(What)を書こうか考えて、それを書く → C#やVB.NETで
  3. 「動く設計書」が、仕様どおりかどうかを自動で毎回チェックしてくれる!
  4. チェックが全部通ったときには、完成している

 「冷蔵庫にキリンの原則」を思い出せ。「サイバラの原則」もだ。重要なのは、シンプルに考えること。シンプルになる方向に自分を持っていくこと。そういう態度を持つことだ。

 そして実践しろ。実践する過程で、お前の中で「プチ・パラダイム・シフト」が起こるときが来る。

 何度でもいうぞ。大切なのは「何が正解か?」ではない。はっきりいって、こんなDateクラスの書き方がどうあるべきかなんて、この演習ではどうでもいいんだ。「どう書けばよいか?」ということがいいたいんじゃない。書いた順序も内容も重要ではない。お前に伝えたいのは「シンプルに考えるという態度」だ。

 それでは、この演習での「シンプルに考えるという態度」についてまとめておこう。

【「シンプルに考えるという態度」のポイント1】

  • 「仕様やコードの検証方法が明確でない『日付チェック』という問題」 vs. 「自分」

  • 「明確な仕様があり検証も自動で行われる『二月の最終日』や『うるう年か』のような比較的単純な問題」 vs. 「自分」

    → 後者のシンプルに考える方向に自分を持っていこうとする態度が重要だ!

 そして、このようにもいえる。

【「シンプルに考えるという態度」のポイント2】

  • 「すべての問題を考慮し、一度に解こうとする」

  • 「その時点その時点での問題を、1つずつ実際に解きながら、解にたどり着こうとする」

    → 後者のシンプルに考える方向に自分を持っていこうとする態度が本当に重要だ!
   

なるほど。私もNAgileの基本となる「考え方のコツ」をつかんで、アジャイルに考えられるように頑張ります。

“Don't think you are agile, know you are agile.”
(アジャイルに動こうと思うな。アジャイルだと知れ)

 アジャイルな態度を持ちさえすれば、お前もNAgilerだ。

 

 INDEX
  NAgileで始める実践アジャイル開発
  第2回 ソフトウェア開発をシンプルにする考え方のコツ
    1.“NAgile”って何? どうやる?
    2.NAgileにおけるシンプルさの極意“NSimplicity”
    3.「シンプルさ」にコミットする演習 ― シンプルに考えるための問題意識
  4.「シンプルさ」にコミットする演習 ― 実際のDateクラスのソース・コードの実装
    5.“Be Agile. That's my attitude.”という心構えを持とう!
 
インデックス・ページヘ  「NAgileで始める実践アジャイル開発」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間