このビデオでは インスペクターを使って
システムの内部を掘り進めていきながら 理解していくための
方法をお見せします。
インスペクターは いわば顕微鏡のようなもので
システムの内部に行って 探検することができます。
また、システムを修正していくための
プローブのようでもあります。
バクテリアを操って反応させる 生物学者になったかのようです。
Smalltalk globals の探検を 楽しんでいきましょう。
これは実際には名前空間です。 Pharo の全てのクラスが
格納された場所です。
つまり辞書です。 SystemDictionary は辞書です。
興味深いことに
インスペクターを使って見ると
値が埋め込まれた
大きなテーブルに見えます。
例えば、そうですね…
Breakpoint を見てみると
ここにオブジェクトがあって
キーと値があります。
インスペクターで
例えばこの テーブルの
2 の要素をみると
グローバル変数と呼ばれるものを 捕まえることができます。
グローバル変数というのは
キーと値からなるオブジェクトで
キーはというと、クリックしてみると
ByteSymbol になっています。 これが名前です。
一旦戻って、値を見てみると
クラスが得られます。
ではクラスの内部に進んでいきましょう。
ここでスタート地点に戻ります。
Pharo の新しいインスペクターは
開発したチームに因んで GT Inspector と呼ばれていますが
対象ごとに専用のタブを
提供してくれます。
SystemDictionary に対しては どんな専用タブがあるかというと
キーと値のペアを
表示するタブや
キーのみを表示するタブがあります。
キーのみのほうは
クラス名を表示するだけになるので
今回はあまり面白くないです。
このインスペクターの
ブラウズの仕方を
例で説明しましょう。
オブジェクトから別のオブジェクトに
対象の構造からパスを選択して ブラウズしています。
キーのことを知りたい場合には、こう。
値について知りたい時は、こうして クラスを掴んで
さらにこのクラスのメソッド辞書に 進んでいくことができます。
メソッド辞書から
コンパイル済みメソッド(CompiledMethod) 等に進んでいくことができます。
このツールでブラウズしていく過程のうち
表示する部分を変えて フロー全体を見ることもできます。
さらに良いことに
フローの中で分岐を作ることもできます。
ここでやってみましょう。
スタート地点に戻ります。
さて、ではここで
Point クラスに興味があるとします。
通常、Point クラスに アクセスするためには
Smalltalk globals at: #Point とすれば良いことは分かっています。
さてここで、それを実行して
インスペクターで開くように
インスペクターの内部でやってみましょう。
すると突然
元のナビゲーションから
これから進んでいくナビゲーションが 分岐します。
こうすることで
いくつも表現式を入力して ナビゲーションを開始することができます。
ここでは
Point クラスを見ています。
インスペクターは
クラスを見る専用のタブを 表示しています。
ここでは、Raw タブは
Point クラスは
Kernel カテゴリーで定義されていて environment は同じ空間を指していて
インスタンスのフォーマットや
layout があります。
端的に言えば、これがクラスというものの Pharo での実装です。
このインスペクターを使って
例えば定義や
コメントを見ることができます。 参照(All Ref)などの他のタブもあります。
All Ref をクリックすると
Point は @ メソッドで
使われていることがわかります。
さらに見てみると
これがメソッドを表現するオブジェクトの
生(Raw)の情報です。 ここにソース(Source)があります。
使う状況にあわせて
タスクに最適な表現を 選ぶことができます。
では戻ってみましょう。
クラスを見て
メソッド辞書に行きたくなったとします。
メソッド辞書というのは
メソッドの名前がキーで
コンパイル済みメソッドが値となっている 辞書です。
コンパイル済みメソッドのインスタンスを
生(Raw)で見てみると ちょっと厄介な感じです。
対話するためには
メソッド辞書が どう実装されているのかを
理解していなければなりません。 しかし実装には興味ありません。
コンパイル済みメソッドを 見たいだけなのです。
コンパイル済みメソッドを見るためには
例えば degrees を選びます。
これでコンパイル済みメソッドを 掴むことができます。
コンパイル済みメソッドは
これまた専用のインスペクター上の 表示を提供しています。
コンパイル済みメソッドを見ると
これは実際にはデータのフレームワークで
テーブルになっています。
具体的にはバイトコードとリテラルを 持っています。
リテラルというのは
コード中に asFloat や arcTan や degrees や radianToDegrees がありますが
これらのメッセージ名がどこかに 格納されていなければなりませんが
それがリテラルとしてここに格納されています
コンパイル済みメソッドの 最初のほうに見えます。
バイトコードは何をするのかというと
スタックにオブジェクトを入れて
メソッドを起動したりします。
ここでは例えば
ビューを最小化しますが Bytecode ビューを見ると
そこでは
PushRcvr してからスタックに 0 を入れて それから = をしています。
これと対応しているのは何でしょう？
よく見てみます。
表示モードは本当にとても便利です。
何ができるのかというと
こうしてソースコードを見る時
あちらで Bytecode を選んで
こちらで Source を選ぶと 対応するもの同士が
表示されます。
すごいですね。
つまりレシーバーの インスタンス変数 0 番をプッシュして
0 をスタックに置いて
そして = メッセージを送ります。
つまりコンパイラを開発する人は
生成されたバイトコードを
コードの構造に対応付けて
見ることができるのです。
同様に
戻って
self をクリックすると
ここにコンパイル済みメソッドの 表示が 2 つあります。
ここにコンパイル済みメソッドの 表示が 2 つあって、これで
AST（抽象構文木）を見ます。
これとソースを見ます。
これで内部をブラウズすることもできます。
例えば、抽象構文木は
このメソッドのものは複雑ですが 表示を開いていって
一時変数 tan を選択すると
それと対応する
コード片が選択されます。
これもすごいですね。 さらに
x に 0 を引数として送るメッセージは
この抽象構文木のこの部分ですが
この部分に対応しています。
インスペクターを使って
木のノードを選択することで
テキストの選択部分を 管理することができます。
Pharo のコンパイラを開発する 人たちにとって
とても素晴らしいツールになります。
このアプローチを使って
様々なドメイン、つまりあなたの ドメインオブジェクトに対しても
意味が解りやすいような表示を 提案するように
インスペクターを拡張することが できるのです。