スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

中の人の徒然草427

もうすっかり寒くなりましたね。毎年のごとく猫と妹が炬燵にへばりついています。私も炬燵に入って本を読む時間が増えてきました。でも本当に寒いのは日本の政治です。
嘘をついても選挙で当選すれば報酬が約束されています。それが原因だと思うのですが、民主党はマニフェストと真逆の行動をし、今は未来への責任と薄ら寒い言葉を連呼しています。でも、彼らには有言実行という言葉がありませんし、責任なんてまともにとったことがありません。いつものように言うだけでしょう。
そもそもおかしいのは、民主主義で国民主権となっている割には、政治家への報酬と人事権がない点です。どこが国民主権なのでしょうか?成果主義が当たり前となっている世の中で、何をせずとも一定の報酬を得る。そんな状態だから政治家は何もしません。そのくせ、復興費を流用したり、100兆円規模の道路を計画したりと余計なことばかりしています。復興費という名目もウソなのでしょうか?
こうした事態を防ぐために、会社は従業員の報酬を自らが決めます。政治家のように自分で決めさせることはしません。また成果も雇い主が判断します。この世の中に、自分で報酬を決め、自分で成果も判断している社員がどこにいるでしょうか?3500円のカツカレーを食べたから庶民感覚がないという、馬鹿げた報道がありました。そんなどうでもいいことよりも、成果型報酬でなく、嘘をついてでも当選すれば一定の報酬が得られるという点のほうが問題です。マスメディアは何でも茶化してワイドショー化しますが、肝心なことは何も報道しません。
そもそも選挙が社会契約でない点がおかしいです。そんな選挙なんていりません。嘘をついてもいいのですから、選挙なんて意味がありません。何を言っても契約としての効力がないので無意味です。民主党がそれを教えてくれました。ただ、どの党にもできる事なので、私は民主党だけを悪く思っていません。
選挙システムを根本から変える必要があります。そもそも今の選挙は意味もなくコストがかかりすぎですから、よりコストがかからずパフォーマンスが良い状態にせねばなりません。というよりも、政治家なんて曖昧で成果も何も判定されない職業いまどき必要なのか大いに疑問です。ようは法律がほしいわけですから、インターネットを通じて全国規模で法律を作ればいいのではないかと思います。オープンソース体制で法律を作るほうが、政治家よりもパフォーマンスがはるかに良いでしょう。
日本の政治家は政局を作るのと選挙活動(就職活動)に忙しくて、肝心の法律を生産する能力が低いと思えてなりません。この状態を放置した我々国民にも責任がありますから、嘘をついてもよく、働かなくてもいいノルマなしの政治家に期待して待つのではなく、立法システムを新しく考えたほうがいいと思います。
勘違いされないように明記しますが、成果が保障されていない政治家という職業そのものが信頼できないということと、立法システムそのものに不備があるということを言っています。政治家個人の事は言及していません。人単位でシステムを考えても無意味ですから、政治家という職業そのものを考えています。
そういった発想の転換がない限り、壊れたOSで動く日本が破綻することはだれの目にも明らかです。日本人は原発事故とかの深刻な出来事が起こるまで何も考えない傾向がありますが、取り返しがつかない事故が起こる前に考えたほうが良いかと思います。何でも想定外、日本が壊れてから考えるでは愚かすぎると私は思えてなりません。日本がなくなったから考えよう、なんて悠長なこと言っている余裕はありません。日本がなくなったとき、後からゆっくりと考えられる状態だとはとてもじゃないけど思えません。
スポンサーサイト

テーマ : 政治・時事問題
ジャンル : 政治・経済

実践的オブジェクト指向設計入門24

 この記事は、実践的オブジェクト指向設計入門23の続きです。前回は、関連の設計について書きました。今回は、オブジェクトの表現について書きます。
 オブジェクト指向方法論OMTは、基本データ型を使う状況と、関係するオブジェクトを組み合わせで使うのはどんな状況なのかを、明確に定義しなくてはならないと説いています。ちょっとわかりにくいので噛み砕いて説明します。
 オブジェクトの属性を表現するとき、大まかにいうと、基本データ型(整数型、実数型、文字列型など)で表現するのか、特別なオブジェクトを定義して表現するのかの2通りの方法が考えられます。例えば、社員オブジェクトの属性・住所に使用する郵便番号は、文字列で表現できますし、オブジェクトでも表現できます。どちらが良いのでしょうか?こうした実装者の疑問に対し設計者は、明確に答えねばなりません。しかし、どちらの方法が良いのかは決まっていません。絶対の答えがないからこそ設計者の腕の見せ所なのです。絶対の答えがないというのが分かりにくいと思いますので、両方法についてちょっとだけ詳しく書きます。
 先程の例でいうと、郵便番号を文字列で表現すると簡単に扱えるように思うでしょう。しかし、実現するシステムにより、簡単か否かは変わってしまいます。社員の住所を表示するぐらいの処理しかなければ、文字列でも問題はないでしょう。ですが、郵便番号を解析して複雑な処理をするようなシステムならば、オブジェクトにしたほうが簡単に実装できます。すなわち、実現しようとしているシステムで可否が決まります。よくいわれる、設計のトレードオフの一つといえます。
 絶対に正しい答えというものがないので、設計者はトレードオフに対して、毅然とした態度で決定を下しましょう。もちろん、そこには設計思想がなければなりません。設計思想がないその場限りの決定は、現場を混乱に陥れるだけです。十分に注意しましょう。
 以上がオブジェクト指向方法論OMTの説明です。私個人の考えを付け加えます。日本の状況を考えると、この作業は余計な干渉のもとになるから注意する必要があると思います。日本では、プログラミングを知らない設計者がいます。そんな設計者がデータ型にまで口を出すと、プログラマーの仕事がやりにくくなるだけです。むろん、プログラミングを知らずとして正しい設計などできないと思いますが、日本の体制ではそうなっているので柔軟に対応するしかありません。
 それともう一つ注意するべき点があります。それは、プログラミングと設計の境が薄くなるという点です。もともと設計と実装は切り離された工程ではなく、数直線のように無限に途切れなく続くものですが、設計と実装の目的の違いを常に意識しなければなりません。やはり、設計と実装は違います。この作業(オブジェクトの表現を考える)をする際には特に注意しましょう。

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

ネタつつき147 - 開発者はきつい制約の中で自分を磨こう

 私は日ごろ、学習のときに心掛けていることがあります。それは、暗記して終えないというものです。専門書を読めば、知りたい事が分かったと思いがちです。しかし私は、ページの終わりが終着地点ではなく、出発地点に過ぎないと考えています。分かったと思ってからが本当の勝負です。
 この考えは、私が研究者をしていたことと関係があると思いますが、専門書を読んだり、調べたりして、「終わった」と思ったことがありません。いつも考えるのは「それから先」の事です。「その技術を○○で使用すればどうなるのだろうか?」「この技術に足りないものはないだろうか?」「この技術を発展させると」・・・などと、学んだ事の先を考えます。そのおかげで私は、IT業界が速いと思ったことがありません。正直に言うと遅いと感じています。なぜならば、すべて自分が考えた「その先」の一部でしか過ぎないからです。先に想定していることが新発明されても気になりません。すべて予想内です。
 だったら特許を取得すればいい思う人がいるでしょう。私もそう考えた時があったのですが、日本の特許制度には不備が多く、知的財産泥棒に盗まれるだけなので、得られるのは苦労と被害だけです。何の利益も生み出しません。ですから、日本ではイノベーションとか、特許で商売をするのは無理です。大人の力の勝負になるので、大企業ならばできるでしょうが、私個人には何もできません。日本は遅れている国なので商売がやりにくい国なのですから仕方がありません。日本に住んでいるから、それを前提に商売をするしかありません。経済状況が悪くなるのは至極当然です。明らかに政府が足を引っ張っています。
 ですから私は政府に期待せず、常に自分ができることの一部である、すでに発表されている技術を使ったものでしか商売をしません。盗まれると損失になりますが、盗まれないものならば利益になります。選択肢を減らされている状態ですから、初めは不満でしたが意外とこれも楽しいです。制約が多い中仕事を達成すると喜びもひとしおです。限られた選択肢の中で、創意工夫していると技術力が磨かれさらなる発想を生みます
 私がこの記事で言いたいことは、既存のものに満足せず常に探求心を持ち続け、厳しい制約の中自分を磨く姿勢が大切だということです。日本は閉鎖的で誰しも不満を抱えて生きているでしょう。しかし、その不満の中で喜びを見出し、自分を磨き続けるという考えが人生に世転びをもたらすと思います。日本は技術大国と呼ばれていました。技術大国は昔の事です。しかし、技術者として考えれば、古来から連綿と続く技術者魂を持って生き続けるのが一番幸せだと思います。冷静に経済面だけを考えれば、それが報われることはないでしょう。しかし、その生き方こそが技術者そのものなのではないでしょうか?

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

初心者のためのC#プログラミング本格入門100 - 似たテストも必要。

 この記事は、初心者のためのC#プログラミング本格入門99です。前回は、プログラムを定義するファイルを分割して、関心事を分離する方法について解説しました。今回は、今後必要となるテストの技法を解説します。
 ファイルを分割しやりやすくなったところで、foreachループ対応の件に戻ります。何か新しいことをする前に、テストをしましょう。それがテストファーストです。

class SimpleListTest : Test
{
    public override void ExecuteAllTest()
    {
        this.OneElementAdd();
        this.CurrentTest();
        this.AddElementCheck();
        this.ForeEachTest();
        this.ForeEachTest2();
    }

    //foreachを模倣する
    public void ForeEachTest()
    {
        //準備
        base.Execute();
        for ( int i = 0 ; i < 10 ; ++i ) 
        {
            this.target.Add( i );
        }
        //1 ~ 9 の数値が格納されているはず
        int x = 0;
        System.Text.StringBuilder error = 
            new System.Text.StringBuilder();
        do {
            if ( ie.Current != x ) 
            {
                string message = 
                    "ForeEachTestで予期せぬ値が返されました。" +
                    "予想値:" + x +
                    " 返された値" + ie.Current +
                    System.Environment.NewLine;
                    error.Append( message );
                    base.Error( message );
            }
            ++x;
        } while ( ie.MoveNext() );
        if ( error.Length != 0 ) {
            base.Error( error.ToString() );
        }
    }

    public void ForeEachTest2()
    {
        //準備
        base.Execute();
        for ( int i = 0 ; i < 10 ; ++i ) {
            this.target.Add( i );
        }
        //1 ~ 9 の数値が格納されているはず
        int x = 0;
        System.Text.StringBuilder error =
            new System.Text.StringBuilder();
        foreach ( int value in this.target ) {
            if ( value != x ) {
                string message = 
                    "ForeEachTest2で予期せぬ値が返されました。" +
                    "予想値:" + x +
                    " 返された値" + value +
                    System.Environment.NewLine;
                error.Append( message );
                base.Error( message );
            }
            ++x;
        }
    }
}

この2つの似たテストを実行してみましょう。お察しの通りエラーが出ます。
 あわてず予想値と実際に返された値を比べてみましょう。1つずつずれています。この様子から、配列のインデックスがずれているとわかります。ということで、初期値を変更してみましょう。

private class Enumerator :
System.Collections.Generic.IEnumerable<int>,
System.Collections.Generic.IEnumerator<int>
{
    private int[ ] data;
    private int readIndex; //読み取り位置

    public Enumerator( int[ ] data )
    {
        this.data = data;
        this.readIndex = -1; //0からー1へ変更
    }
    
    //他は省略
}


変更したらまたテストを実行しましょう。今度は止まってしまいます。止まった時、開発ソフトのデバッグ機能で確認すると、readIndexが-1のまま配列にアクセスしてしまっています。配列は0から数えるので、ストップしてしまいます。では、どこが間違っているのでしょうか?答えを見る前に、一度自分で考えてみて下さい。



 分かりましたか?答えは、「テストプログラム自体が間違っている」です。テストをする際は、テストプログラムも視野に入れて点検します。-1のまま配列にアクセスするのが問題なのですから、1つの命令をテストプログラムに追加します。

public void ForeEachTest()
{
    //準備
    base.Execute();
    for ( int i = 0 ; i < 10 ; ++i ) 
    {
        this.target.Add( i );
    }
    //1 ~ 9 の数値が格納されているはず
    int x = 0;
    System.Text.StringBuilder error = 
        new System.Text.StringBuilder();
    ie.Reset(); //ここに注目!
    do {
        if ( ie.Current != x ) 
        {
            string message = 
                "ForeEachTestで予期せぬ値が返されました。" +
                "予想値:" + x +
                " 返された値" + ie.Current +
                System.Environment.NewLine;
                error.Append( message );
                base.Error( message );
        }
        ++x;
    } while ( ie.MoveNext() );
    if ( error.Length != 0 ) {
        base.Error( error.ToString() );
    }
}

1行追加しただけで大丈夫です。今度はテスト成功です。
 初心者の方は、なぜ同じ内容に見えるテストを作ったのか不思議に思ったでしょう。その答えは、実際にやってみてわかったと思います。テスト漏れが生じないように、微妙に違うテストも必要なのです。特に今回のように、手探りで進んでいる状態のときは有効です。学習目的のときは特にこれが言えます。1つだけで済ませようとせず、角度を変えて考える姿勢が大事です。プログラミングはいろいろ試して習得するものです。1つで分かったつもりにならず、色々試してみましょう。続く...

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

中の人の徒然草426 集合に関する自分の考えをプログラムで整理

仕事が一息ついたので、集合をプログラムにして考えてみました。

using System;
using System.Collections.Generic;

//可能性
enum Possibility
{
    Absolutely,
    Possible,
    Impossible,
}

//集合
class Set
{
    //集合の説明
    private string m_explanation;

    //集合の有無
    private bool m_isSet;

    public bool IsSet
    {
        get { return m_isSet; }
    }

    //対応
    private Func<object, Possibility> m_contained;

    //部分集合
    List<Set> m_subSet;

    //保持する元
    List<object> m_elments;

    //説明文および集合と元(要素)の対応を指定する
    public Set( string explanation, Func<object, 
        Possibility> isFunc )
            : this( explanation, isFunc, true ) { }

    //集合の有無も指定する
    public Set( string explanation, Func<object, 
        Possibility> isFunc, bool isSet )
    {
        this.m_explanation = explanation;
        this.m_contained = isFunc;
        this.m_isSet = isSet;
        this.m_subSet = new List<Set>();
        this.m_elments = new List<object>();
    }

    //指定した元が集合に属するか判定する
    public bool Contained( object element )
    {
        //基本チェック
        Possibility pos = this.m_contained( element );
        switch ( pos ) {
            case Possibility.Absolutely:
                if ( element is Set &&
                     !this.m_elments.Contains( element ) ) {
                    this.m_elments.Add( element );
                } else {
                    if ( !this.m_elments.Contains( element ) )
                        this.m_elments.Add( element );
                }
                return true;
            case Possibility.Impossible:
                return false;
            case Possibility.Possible:
                break;
        }
        bool result = true; //正しいと仮定

        //元が部分集合かチェック
        Set obj = element as Set;
        Possibility subFlag = Possibility.Impossible;
        if ( obj != null ) {
            if ( this.m_subSet.Contains( obj ) ) {
                return true;
            } else {
                subFlag = this.IsSubSet( obj );
                if ( subFlag == Possibility.Absolutely )
                    this.m_subSet.Add( obj );
                if ( subFlag == Possibility.Impossible )
                    return false;
            }
        } else {
            if ( pos == Possibility.Absolutely &&  
                this.m_elments.Contains( element ) == false ) {
                this.m_elments.Add( element );
            }
        }

        //元が部分集合のものかチェック
        if ( subFlag == Possibility.Possible ) 
            return SubSetCheck( element );

        //最終結果を返す
        return result; 
    }

    //指定された集合が部分集合かチェックする
    private Possibility IsSubSet( Set target )
    {
        bool result = false;
        if ( this.m_explanation.Equals( target.m_explanation ) )
            return Possibility.Possible;
        if ( target.m_subSet.Count == 0 ) {
            result = this.IsElement( target );
            if ( result == false )
                return Possibility.Impossible;
            else return Possibility.Possible;
        }
        if ( this.m_contained( target )
                == Possibility.Impossible ) {
            return Possibility.Impossible;
        } else {
            foreach ( Set sub in target.m_subSet ) {
                if ( this.IsSubSet( sub ) ==
                        Possibility.Impossible )
                    return Possibility.Impossible;
            }
            return Possibility.Possible;
        }
    }

    //自身の要素かチェックする
    private bool IsElement( Set target )
    {
        if ( target.m_elments.Count != 0 ) {
            foreach ( object element in target.m_elments ) {
                if ( this.Contained( element ) == false )
                    return false;
            }
            return true;
        }
        return true;
    }

    //部分集合の要素かチェック
    private bool SubSetCheck( object target )
    {
        foreach ( Set subSet in this.m_subSet ) {
            if ( subSet.Contained( target ) == false )
                return false;
        }
        return true;
    }

    //集合の説明を返す
    public override string ToString()
    {
        return this.m_explanation;
    }
}

class Program
{
    //実験
    static void Main()
    {
        //メタ集合(集合の集合の普遍集合)
        Func<object, Possibility> metaF = ( x ) => {
            if ( x == null ) return Possibility.Possible;
            bool hit = x.GetType() == typeof( Set );
            if ( hit ) return Possibility.Absolutely;
            return Possibility.Possible;
        };
        Set metaSet = new Set( "メタ集合", metaF  ); 

        //全ての集合を元として持つ集合
        Func<object, Possibility> setF = ( x ) => {
            if ( x == null ) return Possibility.Impossible;
            Set y = x as Set;
            if ( y == null )
                        return Possibility.Possible;
            if ( y.IsSet == false )
                        return Possibility.Impossible;
            return Possibility.Possible;
        };
        Set setSet = new Set( "集合の集合", setF );

        /*どの集合にも属しない元からなる集合
         (集合の集合のNOT集合)
          長いからNOT集合とする*/
        Func<object, Possibility> notF = ( x ) => {
            bool result = setSet.Contained( x );
            if ( result == false ) 
                return Possibility.Absolutely;
            return Possibility.Impossible;
        };
        Set notSet = new Set( "NOT集合", notF, false );

        //メタ集合に属するか?
        Action<object, Set> MessageShow =
            ( x, y ) => 
                Console.WriteLine( "{0}は{1}に属するか?:{2}",
                x, y, y.Contained( x ) );
        MessageShow( setSet, metaSet );
        MessageShow( notSet, metaSet );
        Console.WriteLine();

        //自然数の集合は集合の集合に属するか?
        Func<object, Possibility> nf = ( x ) => {
            if ( x == null ) 
                return Possibility.Impossible;
            if ( x is int == false ) {
                if ( x is Set ) return Possibility.Possible;
                else return Possibility.Impossible;
            }
            bool hit = ( ( int ) x ) > 0; //0も含まないとする
            if ( hit ) return Possibility.Absolutely;
            else return Possibility.Impossible;
        };
        Set N = new Set( "自然数の集合", nf );
        int a = -1;
        MessageShow( a, N );
        int b = 0;
        MessageShow( b, N );
        int c = 1;
        MessageShow( c, N );
        Console.WriteLine();

        //自然数の集合はどこに属する?
        MessageShow( N, setSet );
        MessageShow( N, notSet );
        MessageShow( N, metaSet );
        Console.WriteLine();

        //自然数の奇数の集合
        Func<object, Possibility> of = ( x ) => {
            if ( x is int == false ) 
                return Possibility.Impossible; 
            int value = ( int ) x;
            bool result = (  value > -1 && value % 2 == 1 );
            if ( result ) return Possibility.Absolutely;
            else return Possibility.Impossible;
        };
        Set oddSet = new Set( "自然数の奇数の集合", of );
        int d = 0;
        MessageShow( d, oddSet );
        int e = 1;
        MessageShow( e, oddSet );
        int f = 2;
        MessageShow( f, oddSet );
        Console.WriteLine();

        //奇数集合はどこに属する?
        MessageShow( oddSet, N );
        MessageShow( oddSet, setSet );
        MessageShow( oddSet, notSet );
        MessageShow( oddSet, metaSet );
        Console.WriteLine();

        //集合の集合は2つの集合を含むか?
        MessageShow( notSet, setSet );
        MessageShow( metaSet, setSet );
        Console.WriteLine();

        //終了
        Console.WriteLine();
        Console.WriteLine( "終了しました。");
        Console.WriteLine( "Enterキーを押して下さい。" );
        Console.ReadLine();
    }
}


私が考えた事は・・・

1.集合は対応を調べる手段を持たねばならない。
持たなければ、元を調べられないと言う事であり、集合の原理に反する。
2.1により集合を写像もしくは対応そのものと看做す事ができる。
3.あらゆる集合は集合演算ができなければならない。
出来なければそれは集合ではない。
プログラムでは型システムでチェック。
4.3により全ての集合にNOT集合と普遍集合がなければならない。
5.部分集合の定義(※1)により、部分集合の全ての元は上位集合の写像範囲内でなければならない。
※1:部分集合の定義は「全てのAの元がBに属する時、AはBの部分集合である。」

プログラムにして再認識したのですが、1と5が意外と難しい問題です。集合の集合に数値が属するか否かは、部分集合を調べないと分かりません。つまり、部分集合で元を判定しないと分からない集合が存在すると言う事です。そもそも、集合の集合なのですから、元が集合に含まれるかを考えなければならないのです。
あと、メタ集合(集合の集合の普遍集合。集合演算に必要)が集合の集合に含まれない事がはっきりしました。仮に含むとすると、メタ集合は集合でない元を含むので、部分集合の定義に反します。すなわち、メタ集合は集合の集合とは呼べません。
あと、集合の集合のNOT集合である、集合でない元で構成される集合は、集合の集合で属するか否かに依存する対応を持つ事もはっきりしました。
これらは予想がついたのですが、1つ予想外の事実が分かりました。それは、ファジイ集合が自ずと出てくる事です。ファジイ理論は少しだけ調べた事があるのですが、ファジイ集合の存在は忘れていました。しかし今回、属することの意味を考えたとき、「可能性がある」「可能性がない」「絶対に属する」という3値が必要となりました。それで昔調べたファジイ理論を思い出し、調べてみるとファジイ集合の存在が分かりました。あとでファジイ理論を復習する必要がありますね。
それと、本題とは関係がありませんが、なんとなくC#でプログラミングしたのですが、関数の定義が多いからF#の方が美しいかもしれないと後で思いました。数学の検証はF#にするべきかもしれません。
やはり、集合論のパラドックスは、属するという意味が厳密に定義されていない点に問題あるようです。また、濃度も曖昧です。プログラミングできるほど厳密に定義されていません。代数的に演算できるぐらいにならないと、実務的な観点から言うと不足しています。まだ不完全な理論です。しかし集合論に矛盾は存在しないと思います。部分集合の定義からメタ集合の属性がはっきりしました。詳細に定義を追うと自ずと答えが見えてきます。従って、矛盾ではなく定義不足だと思います。
ちなみに、今のところツェルメロの「大きすぎる集合は考えない」という立場は反対です。集合論は数学の範囲を超える理論です。それを狭める必要はないと思います。システム開発で似たような理論を自然に使っているしね。システム開発は数学の範囲外の事が多すぎます(自分の勉強不足も否めない)
「全て今までどおりしたいが、利益を出したい。」なんて依頼も頻繁にあります。それは、人間として当たり前の感覚なので否定するつもりは毛頭ありませんが、冷静に考えて理論的には難しいです。今まで通りしていて利益が出るのならば、現在利益が出ているはずです。こうした場合、仕方がないのでその旨を丁寧に伝えて、今まで通りに見えるけどちょっと変えて利益を出すシステムを提案します。この様な現在の数学で解明できない事を、集合論は定義できる可能性があります。それを捨てるのは余りに惜しいです。
数学に限らず、出来ないと思考停止したり、小さくまとまったりするのではなく、常に出来るように変えるのがよいと私は考えています。今まで人類はそうしてきました。これからもそうするべきではないでしょうか?

テーマ : 日記
ジャンル : 日記

書籍をつつく149 - Windowsに関わる全ての人が読むべき聖書。インサイドWindows 第6版 上

情報システムの開発に関わる人は絶対に読むべきだと思う本があります。
それが、この世界で名高い



です。この本はWindowsの内部と調査方法について詳しく書いています。



とセットで読むと、開発能力UP間違いなしです。

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

VBオブジェクト指向プログラミング講座 第10回 小さなオブジェクトを合成して作ろう

 この記事は、第9回 クラスだけが能じゃないインターフェイスも視野に入れようの続きです。前回は、インターフェイスについて解説しました。今回は、オブジェクトの大きさと、オブジェクト指向プログラミングの基本ついて解説します。
 オブジェクト指向プログラミングの初心者は、巨大なクラスを作る傾向があると思います。小さなオブジェクトはあまり便利に見えませんし、初心者の人は作っているという実感が得られないと思います。しかし、小さなオブジェクトを組み立てる考え方こそ、オブジェクト指向プログラミングの王道です。そうはいっても、目で確認しないと納得できないでしょう。そこで、目で分かるサンプルを用意しました。
 前回までのサンプルを流用します。

Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media '追加
Imports System.Windows.Shapes '追加

Friend Class MessageWindow
    '他のプログラムは省略
    Public Sub New(Optional ByVal msg As String = "Hello World")
        '他のプログラムは省略
        '..........
        
        'ボタン
        Dim btn = CreateEllipseButton() 'ここを変更
    End Sub
        
    '楕円ボタンを作成する関数を追加
    Private Function CreateEllipseButton() As Button
        '原型となるボタン
        Dim btn As Button = New Button()

        'ファクトリーオブジェクトを用意
        Dim mainFact As FrameworkElementFactory =
            New FrameworkElementFactory(GetType(Grid))

        '楕円を用意
        Dim brush As LinearGradientBrush = New LinearGradientBrush()
        brush.EndPoint = New Point(0, 1)
        brush.GradientStops.Add(
            New GradientStop(Color.FromArgb(100, 255, 255, 0), 0))
        brush.GradientStops.Add(
            New GradientStop(Color.FromArgb(255, 0, 255, 0), 1))

        Dim ellipseFact As FrameworkElementFactory =
            New FrameworkElementFactory(GetType(Ellipse))
        ellipseFact.SetValue(
            Ellipse.StrokeThicknessProperty, 5.0)
        ellipseFact.SetValue(
            Ellipse.FillProperty, brush)
        mainFact.AppendChild(ellipseFact)

        '楕円の位置
        Dim position As FrameworkElementFactory =
            New FrameworkElementFactory(GetType(ContentPresenter))
        position.SetValue(
            ContentPresenter.HorizontalAlignmentProperty,
            HorizontalAlignment.Center)
        position.SetValue(
            ContentPresenter.VerticalAlignmentProperty,
            VerticalAlignment.Center)
        mainFact.AppendChild(position)

        'ボタンにテンプレートを適用
        Dim tmp As ControlTemplate =
            New ControlTemplate(GetType(Button))
        tmp.VisualTree = mainFact
        btn.Template = tmp
        Return btn
    End Function
End Class

サンプルを実行すると、メインとなるボタンの形が、楕円に変化している事が一目で分かります。WPFを知らないとプログラムの詳細が分からないと思いますが、今は気にしないでください。今回の記事は、オブジェクト指向プログラミングの考え方がテーマです。
 プログラムの細かい意味は分からないかもしれませんが、小さなオブジェクトでボタンが作られている事は分かって頂けると思います。マイクロソフト社にいる凄く優秀な人が設計しただけあって、理想的なオブジェクトで構成されています。WPFは小さなオブジェクトを組み合わせて、柔軟かつ強力なプログラミングが出来ます。これこそが、オブジェクト指向プログラミングの魂だと言えます。
 オブジェクト指向プログラミングの基本は、「小さなオブジェクトを作って大きく組み立てる」です。もちろん、意味がないオブジェクトを定義しても駄目ですが、大きなオブジェクトを作ると、逆に使い勝手が悪くなります。オブジェクトは小さく作る事を心掛けましょう。続く...

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

中の人の徒然草425 濃度とカントールに思いをはせる

集合論を学んで一番不思議に思ったのが濃度の概念です。全単射を考えると言う発想そのものは、元々個数を数える事から始まっているので普通なのですが、部分集合と集合の濃度が同じになると言う部分が腑に落ちません。
確かに全単射だから、無限に数えるという行為をしている限り無限は無限なのですが、ℵ0と名前をつけただけで終えないで、ℵ0の性質を分類するところまで考えを進めなければ気持ちが悪いです。私の美意識に反しているので、納得しかねるのです。
定義域と値域の大きさが考慮されていない点と、有限と無限の対応が無い点が気になります。例えば、奇数の集合を無限に付番できるのでℵ0とされています。しかし、奇数と言うもの自体は無限であり、無限は無限としかいいようがありませんが、無限の要素を分析するために、無限の集合を微分する(ある一定範囲の変化率を分析した場合)に同じ濃度と定義すると支障が出ます。一例をあげると、ビット数が限られている時に問題が出ます。
整数と自然数のデータ型を同じすると問題が生じます。集合論がいうように、0,1,-1,2,-2,と言う風に付番しても1方向の写像ならば問題がありません。しかし、その値を逆写像する時、同じデータ型にしてしまうとビット数が足りないので演算が閉じません。それに加えて、数値の順序が維持されていないので気持ちが悪いです。これはプログラミングでよくある問題です。その様なよくある問題に対応できないのは美しくありません。この件はもちろん、プログラミングだけに限った話ではありません。
この世にある全ての物事は無限と言ってもよいでしょう。空も宇宙もあらゆる事象も全てが途切れなく連なっています。有限の存在である人間が出来るのは、論理的視点により有限の元として分析する事だけです。高度100キロメートルを超えると宇宙と定義するとか、物質を元素の集まりとして捉えるだとか、人間が出来る事は、無限の一部を取り出して、部分的な事実から無限なる事象を思考する事だけです。従って、集合論の濃度も、無限の要素を有限の要素との対比を加味するべきです。
そもそも数学で扱うオブジェクトは基本的に無限です。2次元関数のグラフですから無限に続きます。しかし、微分する(細部に着目する)ことにより性質を分析できます。数学のOSと呼ばれる事もある集合論は、その様な当たり前の出来事に対応した方がよいかと思います。
私が集合に対して合成関数(対応)を定義したように、濃度についても代数的計算が出来るようになるべきだと思います。そうすれば、データ型問題(域値問題)の様なものも集合論で演算して分析する事が出来るようになります。その辺の定義が足りないから、集合論のパラドックスが生じていると思います。
私の好みを言うと、整数の濃度は 2ℵ0 + 1 (自然数に0を含めない場合)と言う風に演算したいです。この式は、0を中点として、マイナス方向へℵ0、プラス方向へℵ0の濃度を持つ集合という意味です。こうした演算が出来れば、物事を集合に直して、値域と集合の対応を演算で解く事が出来るようになります。これに加えて、私が言っているように、集合を対応(合成関数)と捉えれば、論理演算を出来るので、この世のすべてのオブジェクトを演算で解けます。
学問はこうした思考遊戯を自由に出来るので楽しいです。カントールもきっと、自分の集合論にまだ発展の余地があると考えていたと思います。その証拠に、集合論のパラドックスに対しても前向きでした。彼は信仰心があつい人でしたから、神様がくれた問いだと考えていたのでしょう。この様な素晴らしい能力を持つ人が死んでしまったのは、本当に惜しいです。いま彼が生きていたら、この辺の事を尋ねる事が出来たのにな・・・
そう考えると、インターネットは偉大な発明です。でも、英語が苦手だから、現在の偉人にすら話しかけられません。英語をもっと勉強して、現在の偉人と話しをしようと思います。

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

初心者のためのC#プログラミング本格入門99 - ファイルを分割して関心事を分離しよう

 この記事は、初心者のためのC#プログラミング本格入門98の続きです。前回は、プログラムの修正箇所を減らす方法について解説しました。今回は、プログラムを定義するファイルを分割して、関心事を分離する方法について解説します。
 以前この連載で、関心事の分離について解説しました。おさらいすると、プログラミングで実現しようとしている物事の1つ1つを、ちゃんと分けるという考え方の事です。物足りない説明ですが、初心者の頃は下手に細かい所にクビを突っ込まず、イメージを固める所から始めるのがベストです。厳密な定義を暗唱しても、実際に使えなければ意味がありません。ですから最初は、分かりやすい言葉を使って、頭にイメージを定着させます。厳密な定義は、イメージを持ってから、より深く学習する時に利用します。
 話を戻します。以前、インナークラス(内部クラス)の概念を適用して、foreachループに対応するために必要なインターフェイスの定義を分けて、サンプルプログラムを定義しました。しかしこの方法には1つ問題があります。それは読み難い事です。プログラムが読みにくいと、プログラミングをする人の集中力を殺いでしまう恐れがあります。そうなってしまうと、関心事の分離が実践できません。幸いC#には、この状況で役立つ文法があります。
 C#にはpartialキーワードがあります。このキーワードを使用すると、プログラムファイルを分割できます。どういう事かと言いますと・・・

//ファイルSimpleList.cs
partial class SimpleList : 
  System.Collections.Generic.IEnumerable< int >
{
	//プログラムは省略
}


//ファイルSimpleList_Enumerator.cs
//※ファイル名は人間が分かれば何でもよい
partial class SimpleList :
  System.Collections.Generic.IEnumerable< int >
{
    public System.Collections.Generic.IEnumerator< int >
      GetEnumerator()
    {
        return ( System.Collections.Generic.IEnumerator< int > )
            new Enumerator( this.data );
    }

    System.Collections.IEnumerator
      System.Collections.IEnumerable.GetEnumerator()
    {
        return ( System.Collections.IEnumerator )
            new Enumerator( this.data );
    }

    private class Enumerator :
    System.Collections.Generic.IEnumerable< int >,
    System.Collections.Generic.IEnumerator< int >
    {
    	//プログラムは省略
    }
}

こうすることにより、foreachループ対応の事ならSimpleList_Enumerator.cs、本題ならばSimpleList_Enumerator.csと言うふうに読めばよいように出来ます。こうすれば、混乱する可能性が減ります。
 実はこの文法C#で多用されています。具体的には、開発ソフトで自動的に生成されたファイルで使用されています。試しに、メニューの「ファイル」→「新規作成」→「プロジェクト」で表示される画面の中から、Windowsフォームを選んで下さい。その後、ソリューションエクスプローラーの中から、ファイルForm1とForm1.Designer.csを探して中身を見て下さい。もし表示されない場合は、ソリューションエクスプローラーの上の方にある「全てのファイルを表示」をクリックして下さい。この2つのファイルを読むと、Form1クラスにpartialキーワードが付いている事と、デザインと内容が分離されている事が確認できます。
 開発ソフトは、何故1つのオブジェクトの定義を2つのファイルに分けているのでしょうか?それは、デザインと機能を分離できるからです。大半の人は開発ソフトを使って画面をデザインします。この場合、もし1つのファイルでプログラムを定義していると、自動生成されたプログラムと、自分で書いたプログラムがごちゃ混ぜになってしまいます。そうなってしまうと、プログラミングに意識を集中できません。その事態を敷設ために、マイクロソフトの開発ソフトは、この様にしています。
 初心者の人はまだファイルを分割することの何がよいのか分からないと思いますが、ファイルを分割する立点がもうひとつあります。それは、分業が出来る事です。複数の人間でソフトを作るとき、役割に対応してファイルを用意できます。もしファイルが分割できなければ、「画面のデザインをしたいからそのファイル貸して」とか「おいおい、デザインを変える筈が俺が打ったプログラムまで変更されているぞ。」などといった事件が起きてしまいます。そういったトラブルを避けるために、ファイルを分割するのはよい事です。
 ただし、だからと言って無暗に分割すればいいというものでもありません。分割しすぎるとファイルの管理が大変です。どんな便利な文法でも、考えずに多用すればなんらかの問題が必ず発生します。続く...

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

中の人の徒然草424 連休に中に考えた事の続き「集合と何かについて考えた」

 3連休に考えた事の続きです。集合論の矛盾と言われているもの(カントール曰く課題)は、集合とは何かについて厳密に定義していないから発生するものだと思います。私達技術者は、集合オブジェクトを定義する場合、集合オブジェクトは何かについてよく考えます。また、「属する」という言葉の意味もよく考えます。そうしないと実装できません。
 そうした結果、集合オブジェクトが直ぐに思い浮かびます。

class Set
{
    private Func< object, bool > m_contained;

    //集合と元(要素)の対応を指定する
    public Set( Func< object, bool > isFunc )
    {
        this.m_contained = isFunc;
    }

    //指定した元が集合に属するか判定する
    public bool Contained( object element ) 
        { return this.m_contained( element ); }

}

つまり私が考えたのは、集合とは元の対応の事ではないかと言う事です。個々の元は、規則も有用な利用法もありません。しかし、対応を持たせるとそこに有用性が見いだせます。集合とは元の対応を定めることにより、その性質を分析したり、目的に応じて有効に使用したりするものではないでしょうか?
 こうした考えを持てば、集合演算の正体が自然と分かります。例えば和演算は・・・

public Set Join( Set otherSet )
{
    Func< object, bool > f = ( x ) => 
      this.Contained( x ) || otherSet.Contained( x );
    return new Set( f );
}

ようするに、{ f( x ) 論理演算 g( x ) }の合成関数〈対応/写像〉で集合は定義できると思うのです。そう考えれば、部分集合や、集合の集合の正体についても厳密に分かります。また、集合を合成関数で定義できると言う事は、集合論が自然と広がる事も意味します。
 研究者の習性で、私は常にこうした事を考える習慣があります。それに、メタ集合(集合の集合)は仕事でよく遭遇します。例えば、社員オブジェクトが部下を表す社員オブジェクトを持つ場合があります。そうした自己を持つオブジェクトは、自己参照の無限構造を持ちます。しかし数学的に考えると難しい無限構造も、情報技術で考えるとよくあるオブジェクトです。ですから、集合論の矛盾と言われてもあまりピンときません。ごく普通のオブジェクトですから、それをもって集合論の矛盾になるとは到底思えません。ただ人間が記号の限界で想像出来ないだけだと思います。きっとカントールは、だから矛盾とは思わず、上手い方法があると考えたのでしょう。おそらくカントールは、無限を扱うための新しい記号を定義すれば、集合論が本当の意味で活用できると考えたのだと思います。
 ちなみに、私が思うにメタ集合(集合の集合)の正体は、集合を表す元と、集合でないものを表す元を持つ集合だと思います。従ってメタ集合の冪集合とは、集合でないものに集合を組とした集合なのではないでしょうか?だから別に冪集合の濃度が大きくても不思議だと思いません。集合の集合と言う言葉に惑わされているだけであり、集合と集合でないものを合成関数で定義した集合だと思うと別に不思議なものではありません。
 他にも説明がつきます。順序数の集合を元として持つ順序集合も、集合オブジェクトが集合オブジェクトを持っているだけだから、行列で表現できると思います。数学は専門でないから、矛盾がよく分かりません。実務的に困らなくても、数学的には困るのかな?でも、実務で困らないから私は気にしません。
 なにはともあれ、こうした思考遊戯は面白いです。秋の夜長に数学の本を読むのは如何でしょうか?きっと楽しい時間を過ごせると思います。お受験の死んだ数学は面白くありませんが、本当の数学は面白いです。

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

プロフィール

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カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。