次期グラフシミュレータ(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(); } } }
さて,このプログラムの目的に対して(私がいま感じている)問題点を挙げる.
- 不必要なコンストラクタ
- 入出力関数でのポート指定
- 入出力データの扱いづらさ
- 無駄なtry{}catch{}構文
- InterruptedExceptionの記述
- ステートマシンの分かりづらさ
- 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(); } } }
今日はこの辺で.