fc2ブログ

書籍をつつく146-Coders at Work プログラミングの技をめぐる探求。お得な良作。

 久しぶりに書籍のレビューをするピヨ♪ここ最近僕が読んだのがこの本ピヨ。



この本は著名なプログラマへのインタビュー集ピヨ。なんとあのクヌース先生のインタビューもあるピヨッ♪

【書籍目次】
訳者序文
イントロダクション
謝辞
第1章 ジェイミー・ザウィンスキー
第2章 ブラッド・フィッツパトリック
第3章 ダグラス・クロックフォード
第4章 ブレンダン・アイク
第5章 ジョシュア・ブロック
第6章 ジョー・アームストロング
第7章 サイモン・ペイトン・ジョーンズ
第8章 ピーター・ノーヴィグ
第9章 ガイ・スティール
第10章 ダン・インガルス
第11章 L・ピーター・ドイチュ
第12章 ケン・トンプソン
第13章 フラン・アレン
第14章 バーニー・コーセル
第15章 ドナルド・クヌース
参考文献 

 この本の目玉はインタビューする人も実力者である事ピヨ。そのお陰でディープな話しが聞けるピヨ。といっても、発想そのものは僕たちと変わらないから心配ご無用。殆ど僕と同じ意見だったピヨ。彼らは正真正銘凄い人なのだけど、僕たちと同じ人間ピヨ(僕は鳥だけどね)。だから初心者でも楽しく読めると思うピヨ。
 類似書に実録!天才プログラマー (マイクロソフトプレスシリーズ)があるんだけど、出版年月日を考えると当然のことながらこの本の方が時代に即した事が書いてあるピヨ。例えば並列処理や、現代の技術は階層化しすぎ!なんて話題が出てくる。純粋に読み物として面白いピヨ♪
 ただ一つ気になったのは、思想が少し偏っている事ピヨ。C++好きが独りぐらい居てもいいじゃないかと思うんだけど、この15人はC++にあんまりいい印象を持っていないみたい。Unix思想であるシンプル・イズ・ベストな人ばかりピヨォ。別にそれは間違っていないと思うんだけど、C++の危険さや多様性が好きな僕としてはちょっと不満ピヨ。テンプレートメタプログラミングの魅力を語る著名人の言葉も聞きたいな♪一方Perlの扱いは実に面白い。買った人はPerlについての発言を注目すると面白いと思う。
 その他にも色々面白い話が聞けたピヨ。「プログラミングは若い人に向いているか」とか「デバッグのやり方は?」とか「プロジェクトの管理について」とか「他人がコーディングしたコードの読み方」などツボを押さえた話題が読めるピヨ。
 この本をお勧めするのは、プログラミングに関わる人全員ピヨ。お値段の割にはページ数が多く、おまけに内容も濃いから、色々な楽しみ方が出来ると思う。中身がなくページ数だけが多い本ではないピヨ。もちろんためになる事が沢山書かれているから、直ぐにゲットして休日に読む事をお勧めするピヨ。素敵な休日が約束されているピヨ。
スポンサーサイト



テーマ : プログラミング
ジャンル : コンピュータ

.NETテストプログラミング入門7

 この記事は、.NETテストプログラミング入門6の続きです。前回はGUIプログラムのサンプル(WPF)を提示しました。今回はGUIプログラムをテストする方法を解説します。
 前回例として提示したGUIプログラミングのサンプルをテストするには次のようにします。

using System;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;

class WpfTest
{
    [STAThread]
    static void Main()
    {
        //型を取得(※AssemblyQualifiedNameを使用する)
        Type piyoType = Type.GetType( "PiyoWindow, WpfTest_Target, " +
            "Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" );

        //テストの準備
        Window target = ( Window ) Activator.CreateInstance( piyoType );
        StackPanel panel = ( StackPanel ) target.Content;
        TextBox box = ( TextBox ) panel.Children[ 0 ];
        Button btn = ( Button ) panel.Children[ 1 ];
        Label label = ( Label ) panel.Children[ 2 ];

        //値を設定してからクリックイベントを呼び出す
        string inputValue = "テスト";
        box.Text = inputValue;
        MethodInfo method = typeof( Button ).GetMethod( "OnClick",
            BindingFlags.NonPublic | BindingFlags.InvokeMethod |
            BindingFlags.Instance );
        method.Invoke( btn, null );

        //値をチェック
        string right = inputValue + "ピヨ♪";
        bool result = right.Equals( label.Content );
        Console.WriteLine(
                result == true ? "テスト成功" : "テスト失敗" );
    }
}

このコードを見れば、GUIのテストが意外と簡単である事が分かると思います。GUIのテストは通常のプログラミング以外のなにものでもありません。リフレクションとWPFを知っていれば自然に思いつく方法です。
 これはテスト対象が簡単である事も影響していますが、テスト対象がサンプルよりも複雑であっても、テストコードの行数が増えるだけで考えそのものは変わりません。GUIテストに於いて重要なポイントは3つしかありません。
 1つめのポイントは、非公開のクラスを呼び出す方法です。大概のアプリケーションは、そのアプリケーションしか使わない独自ウィンドウを公開したくありません。公開していないクラスを呼び出す方法は、.NETやJavaの場合はリフレクションです。他の言語の場合、違う方法でハックすれば同様の事が出来ます。アクセス修飾子の問題はテストに於いてよくある事なので、プログラマは非公開のクラスのインスタンスを生成する方法を習得するべきだと言えます。
 2つめのポイントは、イベントを発生させる方法です。GUIもただのプログラムです。人間がクリックせねば絶対に動かないわけではありません。それどころかコンピュータはOSの働きもあり、イベントを呼び出す相手が人間の操作なのかプログラムなのかを気にしません。どのようなGUIフレームワークにも、コードでイベントを呼び出す方法があるはずです。今回はリフレクションが簡単なのでそうしましたが、他のリフレクションがない言語でも同様の事が出来るでしょう。
 3つめのポイントは、仕様をはっきりさせる事です。どのコントロールが、どのようにして値を付け取り、どのような値を出力するのかを明確にせねばなりません。仕様が明確に定められていないとテストが出来ません。これはあくまでも私個人の感覚ですが、現場ではこの点を見過ごして、「GUIテストは難しいから人がチェックする」と言っている人が多いと感じています。確かにGUIの美的感覚をプログラムをチェックできません。ですが、全てのGUIプログラムの動作はチェックできます。テストできる部分は絶対にするべきです。GUIプログラムはテスト出来ないからバグがあるという言い訳はクライアントに通用しません。
 どうやら、GUIプログラミングはどう見えるのかばかりが意識され、プログラム的にどういう動きなのかを見過ごす傾向があるようです。該当しないチームも多々存在するでしょうが、そうでないプロジェクトチームはそもそもGUIプログラムのテストを実施しているはずです。
 駆け足でテストプログラミングについて書きました。この連載でテストプログラミングが通常のプログラミングである事が分かったと思います。この連載がテストは難しいと忌避する考えを変え、信頼性が高いシステムがつくられる一助になれば幸いです。

テーマ : プログラミング
ジャンル : コンピュータ

実践的オブジェクト指向分析入門27

 この記事は、実践的オブジェクト指向分析入門26の続きです。前回は「クラス間の関係の識別」を解説しました。今回は「オブジェクトの属性の識別」について述べます。
 オブジェクトは様々な性質を持ちます。例えば社員オブジェクトは、氏名・住所・給与・職位などといった性質を持ちます。これらオブジェクトが持つ性質の事を属性と呼びます
 属性はオブジェクトを分析する上で重要なものであり、オブジェクト指向設計で必要とされている情報です。しかしながら、属性の識別は失敗しやすい作業ですので十分に注意しましょう。よくある失敗は問題領域を考慮しない事です。
 先ほどの例を再び取り上げると、社員オブジェクトはDNAを持つ、二足歩行で歩くなどといった属性を数多く思いつくかも知れません。そうした事を考え出すときりがありません。現実は複雑であり、現実を全て模倣するという古来のオブジェクト指向の考え方では問題が発生します。何故ならば、そういった属性は問題領域外だからです。バイオテクノロジー関連のシステムを作っているならば別ですが、通常の業務システムを構築する上でDNAは必要ないはずです。そうした余計な属性の識別は問題を複雑化させ、プロジェクトを混乱させるだけです。
 もうひとつ注意せねばならないのは、オブジェクト指向分析の段階ではオブジェクトに、セキュリティ属性を持つ、並列化するなどといったシステムよりの属性を持たせてはならない事です。くどいようですが、オブジェクト指向は分析・設計・実装の各種段階を意識する必要があります。段階を意識しないと、オブジェクト指向はプロジェクトに混乱をもたらします。この点を常に意識して下さい。

テーマ : ソフトウェア開発
ジャンル : コンピュータ

.NETテストプログラミング入門6

 この記事は、.NETテストプログラミング入門5の続きです。前回は静的プロパティが関係するクラスを、正確かつ並行的にテストする方法および、テストコードの原則について書きました。今回はテストが難しいとされているGUIのテストについて書きます。
 一般的にテストで難しいとされているプログラムは並行処理とGUIです。並行処理については前回述べましたので、今度はGUIのテストについての解説をします。
 先ずはテスト対象となるGUIのコードを見てみましょう。

using System;
using System.Windows;
using System.Windows.Controls;

static class Program
{
    [STAThread]
    static void Main()
    {
        SampleApplication app = new SampleApplication();
        app.Run();
    }
}

class SampleApplication : Application
{
    public SampleApplication()
    {
        this.Startup += ( object sender, StartupEventArgs e ) => 
        {
            PiyoWindow win = new PiyoWindow();
            win.Show();
        };
    }
}

//テストの対象となるクラス
class PiyoWindow : Window
{
    private StackPanel panel;
    private TextBox inputValueBox;
    Button piyoAddButton;
    private Label outPutValueBox;

    public PiyoWindow()
    {
        //Windowの設定
        this.Title = "テスト対象ピヨ♪";
        this.MinHeight = 150;
        this.MaxHeight = 150;
        this.MinWidth = 300;
        this.MaxWidth = 300;
        this.WindowStartupLocation = 
                WindowStartupLocation.CenterScreen;
        
        //各種コントロールの配置
        panel = new StackPanel();
        this.Content = panel;

        inputValueBox = new TextBox();
        inputValueBox.Text = "ここに文字を入力して下さい。";
        panel.Children.Add( inputValueBox );

        piyoAddButton = new Button();
        piyoAddButton.Content = "出力ピヨ♪";
        piyoAddButton.Click += ( object sender, RoutedEventArgs e ) => 
            outPutValueBox.Content = inputValueBox.Text + "ピヨ♪";
        panel.Children.Add( piyoAddButton );

        outPutValueBox = new Label();
        panel.Children.Add( outPutValueBox );
    }
}

このサンプルコードは、ボタンをクリックすると一番上のテキストボックスに入力した文字列に「ピヨ♪」を付け、一番下に表示されるラベルに表示するという実にシンプルなWPFプログラムです。
 このサンプルは単純ですが、GUIテストの本質を知る材料になります。答えを見る前に自分でテストコードをコーディングしてみて下さい。続く...

テーマ : プログラミング
ジャンル : コンピュータ

.NETテストプログラミング入門5

 この記事は、.NETテストプログラミング入門4の続きです。前回はテストを並行処理する場合における静的プロパティに関する問題点を書きました。今回は静的プロパティが関係するクラスを、正確かつ並行的にテストする方法および、テストコードの原則について書きます。
 先ずは解答となるテストコードを掲載し、そのテストコードを元に解説します。

using System;
using System.IO;
using System.Threading;

static class ConsoleTester
{
    private static Semaphore lockObj = new Semaphore(1, 1);
    public static bool ConsoleOutCheck(
        string right, Action proc, bool yield )
    {
        //ロック開始
        lockObj.WaitOne();

        //出力先を変えてテストを行いやすくする
        TextWriter tmp = Console.Out;
        StringWriter writer = new StringWriter();
        Console.SetOut( writer );

        //テスト対象を実行
        Thread.Sleep( 100 );
        proc();

        //出力設定を元に戻す
        if ( yield == true ) Thread.Yield();
        Console.SetOut( tmp );

        //出力値をテスト
        bool result = writer.ToString().Equals( right );

        //ロック解除
        lockObj.Release();

        //テスト結果を返す
        return result;
    }
}

class Piyo
{
    public void Greeting()
    {
        Console.WriteLine( "おはピヨ♪" );
    }
}

class HelloWorld
{
    public void FirstProgramming()
    {
        Console.WriteLine( "Hello World!" );
    }
}

class Test
{
    static void Main( string[] args )
    {
        //Piyoクラスのテストを実行
        string piyoMessage = null;
        Thread pt = new Thread( () => {
            Piyo piyo = new Piyo();
            string right = "おはピヨ♪" + Environment.NewLine;
            bool result = ConsoleTester.ConsoleOutCheck(
                right,
                () => piyo.Greeting(),
                false );
            piyoMessage = result == true ?
                "Piyoテスト成功" : "Piyoテスト失敗";
        } );

        //HelloWorldクラスのテストを実行
        string helloMessage = null;
        Thread ht = new Thread( () => {
            HelloWorld hello = new HelloWorld();
            string right = "Hello World!" + Environment.NewLine;
            bool result = ConsoleTester.ConsoleOutCheck(
                right,
                () => hello.FirstProgramming(),
                true );
            helloMessage = result == true ?
                "HelloWorldテスト成功" : "HelloWorldテスト失敗";
        } );

        //並行的にテスト
        pt.Start();
        ht.Start();
        pt.Join();
        ht.Join();

        //テスト結果を表示
        Console.WriteLine( piyoMessage );
        Console.WriteLine( helloMessage );

    }
}

以上のように前回のテストコードを少し改良するだけで、並行的にテストが出来るようになります。このテストコードはポイントが3つあります。
 1つめのポイントは、同期オブジェクトを使用し排他制御をしている事です。ConsoleクラスのOutプロパティのように静的プロパティを使用する場合、並行処理の結果を仕様通りにする為に排他制御をせねばなりません。複数のスレッドが同時に静的なプロパティの値を変更すると、静的な値に依存するクラスは整合性のある結果を出せません。詳しくは今後.NET並行処理プログラミングの記事を連載しますのでそちらの方を読んで下さい。
 2つめのポイントは、テストを実行するクラスのメソッドを静的にする事です。テストコードもまた普通のプログラムです。他者が理解しやすいように考慮せねばなりません。このテストは静的な値に依存するので、分かりやすいように静的メソッドにせねばなりません。そうしないとこのテストコードを書いていない人は、オブジェクト指向プログラミングは通常インスタンスを使用するので、インスタンスな値に依存するテストだという前提を持ちます。従って、注意を促すために静的メソッドにする必要があります。
 3つめのポイントは、テストを実行するクラスを静的にする事です。コンソールの入出力機能を使用するこのクラスは明らかに静的なものです。何故ならば、Consoleクラスの静的なOutプロパティが関係するからです。コンソールはそもそもグローバルかつ共有的なものです。それを他者に伝える為に静的なクラスでなければなりません。
 2つめと3つめのポイントは、テストを並行処理しない場合でも同じ事が言えます。テストコードを漫然とコーディングしてはなりません。テストの性質に応じたテストクラスを設計&実装せねばなりません。何故ならば、テストコードは仕様書としての役割も果たすからです。テストの性質と異なるテストコードはプログラマに誤解を与えます。意外とテストコードを意識しない人が多々見受けられます。しかしながら、テストコードは仕様を示す大切な資産です。よく考えてテストコードをコーディングしましょう。

テーマ : プログラミング
ジャンル : コンピュータ

.NETテストプログラミング入門4

 この記事は、.NETテストプログラミング入門3の続きです。前回は、関数型プログラミングの技法を使って、テストコードをより汎用的なものにする方法を解説しました。今回は、前回紹介したテストコードの問題点を解説します。
 前回紹介したテストコードにはある問題があります。それは、並行的にテストを行う時露呈します。

using System;
using System.IO;
using System.Threading;

class Tester
{
    public bool ConsoleOutCheck( string right, Action proc, bool yield )
    {
        //出力先を変えてテストを行いやすくする
        TextWriter tmp = Console.Out;
        StringWriter writer = new StringWriter();
        Console.SetOut( writer );

        //テスト対象を実行
        Thread.Sleep( 100 );
        proc();

        //出力設定を元に戻す
        if ( yield == true ) Thread.Yield();
        Console.SetOut( tmp );

        //出力値をテスト
        bool result = writer.ToString().Equals( right );

        //テスト結果を返す
        return result;
    }
}

class Piyo
{
    public void Greeting()
    {
        Console.WriteLine( "おはピヨ♪" );
    }
}

class HelloWorld
{
    public void FirstProgramming()
    {
        Console.WriteLine( "Hello World!" );
    }
}

class Test
{
    static void Main( string[] args )
    {
        //テストの準備
        Tester tester = new Tester();

        //Piyoクラスのテストを実行
        string piyoMessage = null;
        Thread pt = new Thread( () => {
            Piyo piyo = new Piyo();
            string right = "おはピヨ♪" + Environment.NewLine;
            bool result = tester.ConsoleOutCheck(
                right,
                () => piyo.Greeting(),
                false );
            piyoMessage = result == true ? 
                "Piyoテスト成功" : "Piyoテスト失敗";
        } );

        //HelloWorldクラスのテストを実行
        string helloMessage = null;
        Thread ht = new Thread( () => {
            HelloWorld hello = new HelloWorld();
            string right = "Hello World!" + Environment.NewLine;
            bool result = tester.ConsoleOutCheck(
                right,
                () => hello.FirstProgramming(),
                true );
            helloMessage = result == true ? 
                "HelloWorldテスト成功" : "HelloWorldテスト失敗";
        } );

        //並行的にテスト
        pt.Start();
        ht.Start();
        pt.Join();
        ht.Join();

        //テスト結果を表示
        Console.WriteLine( piyoMessage );
        Console.WriteLine( helloMessage );
    }
}

※このサンプルコードは、並行処理による問題が発生しやすいようにしています。
 このサンプルを実行すれば、前回紹介したテストコードは並行処理時に問題がある事が分かります。もし、問題が発生しない場合は、Sleepに引き渡す値を大きくしてみましょう。
 この問題が発生する原因は、静的プロパティを使用している点です。静的プロパティであるOutプロパティを静的メソッドで設定しているため、個々のスレッドの出力ストリームの変更が、他のスレッドに影響を与えています。この状態ではまともにテストが出来ません。
 今後並行的にテストを処理する機会が多くなるでしょう。ですから、テスト対象となるクラスが持つ性質をよく考えなくてはなりません。問題の解決方法は次回解説します。続く...

テーマ : プログラミング
ジャンル : コンピュータ

スレッド数決定問題15

 この記事は、スレッド数決定問題14の続きです。今回は、いよいよ並列処理システムの設計法について解説します。
 これまでの記事の内容を前提とした上で、高度な並列処理技術を使用するシステムの設計について述べていきます。並列処理システムを設計するには、先ず並列処理はどのような分類があるのかを知らねばなりません。並列処理を大別すると、データの並列化とタスクの並列化の2つです。
 データの並列化は、対象のデータを並列的に処理する事を指します。企業における情報処理システムは、データが増える事はあっても減る事はありません。その大量のデータを並列的に処理するのは自然な考え方です。
 タスクの並列化は、データではなく処理そのものを並列化する方法です。タスクの並列化は、仕事の現場において多々見受けられる光景です。殆どの仕事は、複数の人が同じ内容の仕事をしています。それがタスクの並列化と考えると分かりやすいかと思います。タスクの並列化もまた、自然な考え方だと言えます。
 現実をモデル化する上で、データの並列化とタスクの並列化は容易に見出す事が出来ます。コンピュータの世界とは違い、現実はあらゆる出来事が並列的に起こっています。それ故、初めて並列処理システムを設計する人は、簡単な事だと思うでしょう。しかし、現実とコンピュータの世界のギャップがシステム設計を困難にします。その困難さについては、今で述べてきたので、改めてこの連載を読むと分かるかと思います。
 現実とコンピュータのギャップを埋める並列処理システムの設計に於いて重要なのは、依存性を明らかにする事です。普段我々人間は、日常では依存性を気にしませんが、コンピュータ上では意識しなくてはなりません。全ての処理には何らかの前提と順序的な依存性があります。それを明確にしないと、並列処理システムの設計は行えません。続く...

テーマ : 情報処理技術
ジャンル : コンピュータ

.NETテストプログラミング入門3

 この記事は、.NETテストプログラミング入門2の続きです。今回は、前回紹介したオブジェクト指向なテストコードを、関数型プログラミングの流儀を持って改良します。
 前回のテストコードは、シンプルを前提にすると、オブジェクト指向プログラミングでは限界に近いと思います。しかし現代的なプログラム言語には、もっとスマートな方法があります。それは、関数型言語の要素を取り入れる事です。
 関数型プログラミングの考え方を取り入れると、いとも簡単にテストを行うための前提が減ります。

using System;
using System.IO;

class Tester
{
    //関数(この場合はプロシージャ)を渡せばいい
    public bool ConsoleOutCheck( string right, Action proc )
    {
        //出力先を変えてテストを行いやすくする
        TextWriter tmp = Console.Out;
        StringWriter writer = new StringWriter();
        Console.SetOut( writer );

        //テスト対象を実行
        proc();

        //出力設定を元に戻す
        Console.SetOut( tmp );

        ////出力値をテスト
        bool result = writer.ToString().Equals( right );
        return result;
    }
}

class Piyo 
{
    public void Greeting()
    {
        Console.WriteLine( "おはピヨ♪" );
    }
}

class HelloWorld 
{
    public void FirstProgramming()
    {
        Console.WriteLine( "Hello World!" );
    }
}

class Test
{
    static void Main( string[] args )
    {
        //テストの準備
        Tester tester = new Tester();

        //Piyoクラスのテストを実行
        Console.WriteLine( "これからPiyoテストを実行します。" );
        Piyo piyo = new Piyo();
        string right = "おはピヨ♪" + Environment.NewLine;
        bool result = tester.ConsoleOutCheck(
            right,
            () => piyo.Greeting() );
        string message = result == true ? "テスト成功" : "テスト失敗";
        Console.WriteLine( message );
        Console.WriteLine();

        //HelloWorldクラスのテストを実行
        Console.WriteLine( "これからHelloWorldテストを実行します。" );
        HelloWorld hello = new HelloWorld();
        right = "Hello World!" + Environment.NewLine;
        result = tester.ConsoleOutCheck(
            right, 
            () => hello.FirstProgramming() );
        message = result == true ? "テスト成功" : "テスト失敗";
        Console.WriteLine( message );
        Console.WriteLine();
    }
}

このテストの要件はあるコンソールへ文字列を出力するメソッドの正しさをチェックしたいという事です。ならばテストコードは、任意のメソッドが実行できればよいのであって、オブジェクトに拘る必要は何もありません。
 なお、このテストコードにおいて、Actionデリゲート引数が最後になっているのは、Funcデリゲート引数などのオーバーロード(多重定義)メソッドを増やす事が予測できるからです。正しい値を後にすると読み難いので、オーバーロードされると予測できるパラメータは最後にします。
 このテストコードで完成と思った人も多いかと思います。ですが、これはまだ不完全なテストコードです。コンソールの性質を考慮すると十分とは言えません。まだ問題点があります。その問題点は・・・次回へ続く。  

テーマ : プログラミング
ジャンル : コンピュータ

.NETテストプログラミング入門2

 この記事は、.NETテストプログラミング入門1の続きです。今回は前回紹介したテストコードを、オブジェクト指向プログラミングの流儀に従って再利用できるように改善します。
 前回述べたようにテストコードが長く再利用できない状態は、オブジェクト指向プログラミングとしては問題です。具体的に言うと、特定のクラスに依存している事が問題です。どのクラスのメソッドであってもテスト出来るように改良せねばなりません。この場合、オブジェクト指向プログラミングの考え方では、インタフェースを使用してテストコードを改良します。

using System;
using System.IO;

interface IConsoleOut
{
    void MessageOutPut();
}

class Tester
{
    public bool ConsoleOutCheck( IConsoleOut target, string right )
    {
        //出力先を変えてテストを行いやすくする
        TextWriter tmp = Console.Out;
        StringWriter writer = new StringWriter();
        Console.SetOut( writer );

        //テスト対象を実行
        target.MessageOutPut();

        //出力設定を元に戻す
        Console.SetOut( tmp );

        ////出力値をテスト
        bool result = writer.ToString().Equals( right );
        return result;
    }
}

この様にインタフェースを使用すると、親子関係がない多数のクラスのメソッドを、テスト出来るテストコードへ生まれ変わります。
 親クラスを指定していない点に注目して下さい。コンソールへ文字列を出力するクラスが親子関係を持つ事は、オブジェクト指向設計の観点から言って不自然なので、この場面ではインタフェースが適しています。特に多重継承が出来ない.NETでは、コンソールへ文字列を出力する為だけに、親クラスを定義して継承するのは得策ではありません。

class Piyo : IConsoleOut
{
    public void MessageOutPut()
    {
        Console.WriteLine( "おはピヨ♪" );
    }
}

class HelloWorld : IConsoleOut
{
    public void MessageOutPut()
    {
        Console.WriteLine( "Hello World!" );
    }
}

class Test
{
    static void Main( string[] args )
    {
        //テストの準備
        Tester tester = new Tester();

        //Piyoクラスのテストを実行
        Console.WriteLine("これからPiyoテストを実行します。");
        Piyo piyo = new Piyo();
        string right = "おはピヨ♪" + Environment.NewLine;
        bool result = tester.ConsoleOutCheck(
            ( IConsoleOut ) piyo,
            right );
        string message = result == true ? "テスト成功" : "テスト失敗";
        Console.WriteLine( message );
        Console.WriteLine();

        //HelloWorldクラスのテストを実行
        Console.WriteLine( "これからHelloWorldテストを実行します。" );
        HelloWorld hello = new HelloWorld();
        right = "Hello World!" + Environment.NewLine;
        result = tester.ConsoleOutCheck(
            ( IConsoleOut ) hello,
            right );
        message = result == true ? "テスト成功" : "テスト失敗";
        Console.WriteLine( message );
        Console.WriteLine();
    }
}

短いサンプルでは便利さが分かり難いかもしれませんが、長い文字列を処理結果に応じて出力するメソッドであっても、同様にテストできる点を考えると便利なテストコードだと言えます。
 しかしながら、このテストコードもまだまだ改善するべき余地があります。テストのためだけにインタフェースを実装するのは大変おかなしな事です。テスト対象はテストの事を考えず、適切なメソッドを定義できる様にするべきです。テストコードはテスト対象を変えるものではあってはなりません
 この問題点に対処する方法は・・・次回へ続く。

テーマ : プログラミング
ジャンル : コンピュータ

.NETテストプログラミング入門1

 この記事は、.NETテストプログラミング入門の続きです。前回から引き続き、コンソールへ文字列を出力するプログラムのテストを解説します。
 前回のサンプルコードを理解するには、コンソールが何をするものなのかを理解せねばなりません。System.ConsoleについてMSDNを調べると「コンソール アプリケーションの標準入力ストリーム、標準出力ストリーム、および標準エラーストリームを表します。」と書かれています。この文章を読むと、標準入出力ストリームについて知る必要がある事が分かります。
 各種標準ストリームの概念は古くからあり、私が知る限りでは初期のUNIXに存在していました。UNIXの設計思想は、小さいツールを組み合わせて使う事であり、個々のプログラムは単独で使用せず、組み合わせて使用するのが常識となっていました。それ故UNIXユーザ達は、UNIXパイプを使用し複数のプログラムを組み合わせて使っていました。
 UNIXパイプを使用する為に、各プログラムはデータのやり取りをせねばなりません。そこで、全てのデータをストリームとして考え、入出力およびエラーをストリームとして扱いました。ストリームとして扱う事の利点は、入力または出力先を柔軟に変更できる事です。この概念は非常に有効なものであり、今もなお使用されているので、標準入出力ストリームという言葉はプログラマ間で一般的に使用されています。
「標準」出力ストリームと言った場合、コンソールを指します。何故「標準」と付けるのかと言いますと、ストリームは柔軟に変更できるからです。コンソールへ出力するのを止め、メモリやファイルへ出力する事も可能です。ですから、コンソールクラスの説明に標準と書かれているのです。
 これを踏まえて、前回のテストコードを見れば意味が分かると思います。

//出力先を変えてテストを行いやすくする
TextWriter tmp = Console.Out;
StringWriter writer = new StringWriter();
Console.SetOut( writer );

 先ほど説明したように、出力ストリームは変更できます。そこで、テストが行いやすいように、メモリ上へデータを出力するように変更しています。これが出来れば後は簡単です。

//出力値をテスト
Piyo target = new Piyo();
target.Greeting();

//テスト結果を表示
string right = "おはピヨ♪" + Environment.NewLine;
bool result = writer.ToString().Equals( right );

 そして、上記コードでテスト対象となるPiyoクラスを実行し、メモリ上へ文字列を出力させ、その値を取得してチェックしています。なお、正しい文字列にEnvironment.NewLineを加算しているのは、Console.WriteLineメソッドは改行文字列が必ず付加されるからです。改行文字は忘れやすいので注意しましょう。
 このテストコードは一応作動しますが、テストコードとしては不十分なものです。テスト対象よりも多いコードを一々コーディングするのは時間の無駄です。テストコードも普通のコードなので、オブジェクト指向プログラミングの考えを適用し、再利用できるように改善せねばなりません。続く...

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター