次期グラフシミュレータ(GraphSim3)に関する考察(2)

昨日の続き.今回は,GraphSim2での機能回路記述を考察する.
GraphSim2では,機能のみを記述することに主目的を置いた.すなわち,ユーザーに余計なことは書かせない,である.
まず,入力されるストリームから,0x1eから0x1fの間までを抜き出す機能回路である.

public class ThroughBetween extends DefaultFunctionalModule {
    public static final String[] ipNames = { "in" };
    public static final String[] opNames = { "out" };

    public ThroughBetween(){
        super( ipNames, opNames );
    }

    private boolean output_flag;
    public void init(){
        output_flag = false;
    }

    public void exec() throws InterruptedException {
        try{
            DataObject in = read("in");
            if( output_flag == false ){
                if( in.getValue() == 0x1e ){
                    output_flag = true;
                }
            }
            else {
                if( in.getValue() == 0x1f ){
                    output_flag = false;
                }
                else {
                    write( "out", in );
                }
            }
        }catch( PCAException e ){
            e.printStackTrace();
        }
    }
}

さて,このプログラムの目的に対して(私がいま感じている)問題点を挙げる.

  1. 不必要なコンストラク
  2. 入出力関数でのポート指定
  3. 入出力データの扱いづらさ
  4. 無駄なtry{}catch{}構文
  5. InterruptedExceptionの記述
  6. ステートマシンの分かりづらさ
  7. DefaultFunctionalModule

こんなところか.

不必要なコンストラク

ほとんどの機能回路記述のコンストラクタは同じであり,それはsuper(..., ...)である.なぜこのようなコンストラクタが必要かというと,機能回路ごとに入出力ポートは異なり,機能回路の抽象クラスであるDefaultFunctionalModuleで入出力ポートを管理するためには,その具象クラスから入出力ポートに関する情報を受け取らなければならないということだ.
そして,その情報の受け渡しにコンストラクタを用いたということになる.
この,入出力ポートの情報管理に何か良い手段はないかといま考えている.入出力ポートの明示的な宣言は必要である.そして,その宣言を自動的に抽象クラスへ渡す手段はないだろうか.
一つは,入出力ポートの情報を定義するためのメソッドを用いる方法である.しかし,入力ポート,出力ポートと2つのメソッドを定義しなければならないことになり,あまり利便性があがるとは思えない.
もう一つは,インターフェイスと機能実装の分離である.すなわち,入出力ポートを定義する名前(クラス名,インターフェイス名)をJava言語の文法の範囲内で記述し,その情報を元にDefaultFunctionalModuleが入出力を管理するのである.
下は,インターフェイスを用いた例である.なお,この表現法はまだ実現されていない.OneInputOneOutputで入出力ポートを管理する.そして,ThroughBetween機能回路は,そのインターフェイスの機能回路である.こういう記述.
この記述のメリットは,機能とインターフェイスを分離することができるということだ.また,コンストラクタを減らすことができるのは素晴らしい.
もっとも,新たにインターフェイスを定義しなければならなくなる.しかしこれは,典型的なインターフェイスをいくつか用意しておくことで回避できる.実際,アダマール変換回路を記述したときに,同じインターフェイスを使いまわしてこれに似たようなことを実現した.そのときの感想は,「便利」だ.なにしろ,いちいち変数定義をしなくてすみ,implement FooBarだけで済むからだ.しかもそのときは,同じ機能だが抽象度の違う機能回路を定義して,テストを容易化したため,なおさらそう感じた.
この記述のデメリットは,Javaでは継承関係はツリー構造にしかなり得ないため,入出力定義にインターフェイスしか用いることができないことだ.そのため,インスタンス変数しか記述することができず,インスタンス変数はスーパークラスからは見えないということ.唯一の解法は,リフレクションを使うことか?

public interface OneInputOneOutput {
    public static final String[] ipNames = { "in" };
    public static final String[] opNames = { "out" };
}

public class ThroughBetween extends DefaultFunctionalModule implements OneInputOneOutput {

    private boolean output_flag;
    public void init(){
        output_flag = false;
    }

    public void exec() throws InterruptedException {
        try{
            DataObject in = read("in");
            if( output_flag == false ){
                if( in.getValue() == 0x1e ){
                    output_flag = true;
                }
            }
            else {
                if( in.getValue() == 0x1f ){
                    output_flag = false;
                }
                else {
                    write( "out", in );
                }
            }
        }catch( PCAException e ){
            e.printStackTrace();
        }
    }
}

今日はこの辺で.