« [.NET] yield return はコードカバレッジでカバーできない | トップページ | [TDD の練習(3)] 和暦年月の文字列を検証する »

2008年12月30日 (火)

[TDD の練習(2)] (すっかり出遅れた) 縦書き祭

わんくま blog での縦書き祭は → このへんから

てことで、 仕様はこんな感じにします。
・ 入力は全角のテキストだとする。 ( そうじゃなかったら、 読み込んだときに変換してね )
・ Console.WriteLine() で出力していくと、 縦書きしてあるように見えること。
・ 無駄な空白 (右端と下端) は、 出力しない。

前回と同様に、 どんなテストコードを書いていけばいいのかを、 文章で書いてみますので、 ユニットテストに書き下してみてください。

  1. 最初に、 どんな使い方をするものなのか、 考えます。
    コードの流れはどんなふうでしょう。 その中で、 今回作るモノはどのように使うでしょう? 分かりにくいときは、 ざっと書いてみます。
    ここは回答例を書いておきましょう。 こんな感じでしょうか…

// 読み込んだら、UNICODE 正規化と全角変換して
List<string> 横書きデータ = new List<string>();
foreach (string 一行 in 横書きデータ元) {
  string 正規化済み
   
= 一行.Normalize(
      System.Text.NormalizationForm.FormC);
  string 全角化済み
    = Microsoft.VisualBasic.Strings.StrConv(
      正規化済み,
      Microsoft.VisualBasic.VbStrConv.Wide,
      0x0411);
  横書きデータ.Add(全角化済み);
}

// 縦横変換機を呼び出して
IEnumerable<string> 変換後データ
  = 縦横変換機.縦書きに直せ(横書きデータ);

// コンソールに書き出させる
foreach (string 横一行分 in 変換後データ) {
  Console.WriteLine(横一行分);
}

上で書いたコードで、 まだ無いモノは 縦横変換機 ってヤツです。 こいつを作るためのテストを書いていきます。

  1. null や空文字のリストを渡すテスト
    ※ ムダな空白を出力しない、 という仕様から、 このテストケースが導かれます。
    • (1-1) null → 1行も出力されないこと。
    • (1-2) リストの各要素が全て null か空文字 → やはり 1行も出力されないこと。

  2. 一行だけのリストを渡す
    その一行の文字数に等しいだけの、 文字列のリスト ( 配列 ) が返ってくればよいですね。 ただし、 行末の空白は出てはダメです。

  3. 二行のリストを渡す
    • (3-1) 一行目が短い
    • (3-2) 二行目のほうが短い
    • (3-3) 先頭の空行は出力されない (連続していても)
    • (3-4) 空行じゃない行が出現したあとの、 空行は出力される
    • (3-5) 空行じゃない行が出現したあとの、 null は空行扱い

…だいたい、 こんなところでしょう。
大きいほうの限界を見ていませんが、 まぁ良しとします。 ( おそらくは、 メモリがパンクするところが限界になるんじゃないかな。 )

回答例 ( C# + NUnit 用のソースコード ) はこちら → DirectionChangerTests.cs [6KB]
ちゃんと自分で書いてみてから、 見てくださいね f(^^;

そして、 このテストコードをパスするように実装とリファクタリングしたコードは、 こうなりました。
C# 2008 ( .NET Framework 3.5 ) なので、 LINQ 式 と yield return を使っています。

public static class 縦横変換機 {

  public static IEnumerable<string> 縦書きに直せ(IList<string> 横書き文章) {
    if (横書き文章 == null)
      yield break;

    int 最大長 = 横書き文章.Max(s => (s == null ? 0 : s.Length));
    if(最大長 == 0)
      yield break;


    for (int rowIndex = 0; rowIndex < 最大長; rowIndex++) {
      string 横一列分 = 横一列分を取り出せ(横書き文章, rowIndex);

      yield return 横一列分.TrimEnd();
    }
  }

  private static string 横一列分を取り出せ(IList<string> 横書き文章, int rowIndex) {
    int 行数 = 横書き文章.Count;
    StringBuilder sb = new StringBuilder(行数);

    for (int arrayIndex = 横書き文章.Count - 1; arrayIndex >= 0; arrayIndex--) {
      string 一行 = 横書き文章[arrayIndex];
      if (一行 == null) {
        sb.Append(' ');
        continue;
      }

      if (一行.Length > rowIndex)
        sb.Append(一行[rowIndex]);
      else
        sb.Append(' ');
    }
    return sb.ToString();
  }
}

上のコードでは、 いっぺん使ってみたかった yield を使ってますが、 使わなきゃいけないってことはありません。 っていうか、 そもそも .NET Framework 2.0 には存在しないですしね。

|

« [.NET] yield return はコードカバレッジでカバーできない | トップページ | [TDD の練習(3)] 和暦年月の文字列を検証する »

プログラミング」カテゴリの記事

-プログラミング ( わんくま )」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/209349/43571568

この記事へのトラックバック一覧です: [TDD の練習(2)] (すっかり出遅れた) 縦書き祭:

» [TDD の練習(3)] 和暦年月の文字列を検証する [biac の それさえもおそらくは幸せな日々@nifty]
とある掲示板より。 号年月(例 H2012)が実在する年月であるかをチェックしたいです。 年号は、H=平成 S=昭和のみを対象とします。 質問者は、 旧 VB の IsDate() 関数と互換のメソッドが使えるような実装が出来た、 というところで終わっています。 そのコードは、 「一部省略しております」 とのことで、 ... [続きを読む]

受信: 2008年12月31日 (水) 00時35分

« [.NET] yield return はコードカバレッジでカバーできない | トップページ | [TDD の練習(3)] 和暦年月の文字列を検証する »