類似した振舞いのオブジェクトのグループ化によるクラス動作シナリオの可視化
宗像 聡 ††

石尾 隆 †

井上 克郎 †

大阪大学 大学院情報科学研究科

オブジェクト指向システムにおいて，あるクラスの動作を理解するには，そのクラスのオブジェクトの実際の振舞いをシーケンス図として可視化する手法が有効である．しかし，1 つのクラスから多数のオブジェクトが生成される場合，オブジェクトごとにその動作を逐一確認することは現実的ではない．そこで本研究
では，振舞いの類似性に基づいてオブジェクトをグループ化し，そのクラスの代表的な振舞いのみを可視化する手法を提案する．ケーススタディとして，ある Java プログラムの動作理解へと提案手法を適用し，その有効性を確認した．

Visualization of Representative Class Interaction Scenarios
based on Clustering of Object Behavior

Satoshi Munakata††Takashi Ishio†

Katsuro Inoue†

Graduate School of Information Science and Technology, Osaka University

Visualizing an execution trace of an object-oriented system as sequence diagrams is eﬀective to understand the behavior of a class. However, a class may create a large number of instances; a developer
is hard to read sequence diagrams for each object. In this paper, we propose to classify objects into
groups based on their behavior, and visualize only representative behavior of objects. As a case study,
we have applied our approach to understand a Java program.

-1-

はじめに1の工夫がとられる．

2.2

オブジェクト指向プログラミングでは，クラス動作シナリオの抽出が基本的なソフトウェア部品であり，システムの実用的なオブジェクト指向システムでは，出現動作を理解するにはクラスの動作を理解する必要するオブジェクトの振舞いをすべて確認することがある．特に保守作業においては，その遂行に必は困難である．そのため，特定のクラスの各オブ要な少数のクラスの動作だけを効果的に理解するジェクトの振舞いから，クラスの動作シナリオをための手法が必要とされている．

抽出する手法が提案されている．

オブジェクト指向システムでは，複数のオブジェ代表的な手法に，特定のメソッド呼び出し系列クトが相互にメッセージ通信を行うことで処理がを受理する有限状態オートマトンを用いて，クラ行われる．オブジェクトとメッセージはシステムのスの動作シナリオを表現する手法がある [4, 6]．あ

実行時に動的に生成されるため，クラスの動作をるクラスのすべてのオブジェクトのメソッド呼び理解するには，そのクラスのオブジェクトの実際出し系列を受理する有限状態オートマトンを構築の振舞いを可視化することが有効である [2, 7, 8]．

することで，そのクラスが取りうるすべての振舞しかし，解析対象のクラスのオブジェクトが多数いを表現することができる．しかし，これは実際ある場合，それぞれの動作を逐一確認することはの振舞いの近似であり，オブジェクトの具体的な現実的ではない．同じクラスのオブジェクトが多振舞いを確認することはできない．

数存在したとしても，その多くは互いに振舞いがSalah らは，特定のクラスのオブジェクトのメ類似していると期待されるため，代表的な振舞いソッド呼び出し系列を，互いの類似度にに基づきのみを可視化することで，より効果的に理解を行クラスタリングすることで，代表的なクラスの動うことができると考えられる．

作シナリオを抽出する手法を提案している [3]．しそこで本研究では，特定クラスの複数のオブジェかし，このクラスタリングに必要な時間計算量はクトを，その振舞いの類似性に基づいてグループ厳密解法で指数時間と大きい．また，動作シナリ化することで，代表的な振舞いのみを可視化する

オは正規表現に似た形式で提示されるが，これも手法を提案する．ユーザは各振舞いを比較するこまた実際の動作の近似である．とで，クラスの動作を効果的に理解することがで本手法では，特定のクラスのオブジェクトを振きる．ケーススタディとして，ある Java プログラ舞いの類似性に基づいてグループ化し，それぞれムに提案手法を適用し，その有効性を確認した．の代表オブジェクトの振舞いを可視化することで，以降では本手法を提案するにいたった背景を説

このクラスの代表的な動作シナリオを提示する．こ明し，次に 3 章で本手法について，4 章で実装にの動作シナリオはオブジェクトの実際の振舞いでついて，5 章でケーススタディについて述べる．最あるため，繰り返し構造の反復回数などの詳細を後に 6 章でまとめと今後の課題を述べる．

確認できるほか，他のクラスとの相互作用を確認

2

背景することもできる．

2.1

オブジェクトの振舞いの可視化

3

提案手法

オブジェクトの振舞いの可視化には，UML の本研究では，開発者が注目するクラスのオブジェシーケンス図が有効である [1, 7, 8]．シーケンス

クトをその振舞いの類似性に基づいてグループ化

図による可視化の利点は，オブジェクト間の相互することで，そのクラスの代表的な振舞いのみを作用を時間軸に沿って直観的に確認できることで可視化する．具体的には，実行履歴から特定クラある．しかし実用的なシステムでは，実行履歴にスのオブジェクトが関係したメソッド呼び出し系

は膨大な数のメソッド呼び出しが記録されており，列を抽出，それらの属性に基づいてオブジェクト単純に可視化すると図は大規模になり読解が困難をグループ化し，各グループから選んだ代表オブになる．そのため，メソッド呼び出し系列内のルージェクトの振舞いのみをシーケンス図として可視プ構造や再帰構造を検出して圧縮処理を行うなど化する．

-2-

提案手法は，ある 1 つのクラスの動作例を抽出

3.3

グループの構築するだけでなく，2 つのクラス間の相互作用例を抽

本手法では，クラス ck のオブジェクトをグルー出するためにも使用できる．基点となるクラスとプ化する基準として，関連クラスに基づくグルー相互作用する他のクラスについても同様にグループ化 Gc (ck ) と，関連メソッドに基づくグループ化

プを構築し，互いのグループ間の呼び出し関係をGm (ck ) を用いる．

解析する．グループの組み合わせごとに，呼び出

関 連 ク ラ ス に 基 づ く グ ル ー プ 化 Gc (ck )={G1 , · · · , Gl } は，以下の条件を満たすようにオブジェクトをグループに分類する．

し関係のあるオブジェクトのペアを代表として選択し，その動作をシーケンス図として可視化する．
ループごとの代表的な振舞いと，他のクラスとの∀o1 , o2 ∈ Gi (1 ≤ i ≤ l) ↔ U se(o1 ) = U se(o2 )∧U sed(o1 ) = U sed(o2 )相互作用の例がシーケンス図として可視化される．

これはある 1 つのグループに属しているどんなユーザはこれらの図を比較することで，すべてのオブジェクトの動作を逐一確認することなく，ク2 つのオブジェクトも，相互作用するクラス群が完全に一致するということを意味する．どのようなラスの実際の動作についての理解を深めることがクラスと相互作用するかは設計時に作成されるクできる．

ラス図やシーケンス図に明記されているが，実際提案手法により，実行履歴から特定クラスのグ

3.1

実行履歴の取得のオブジェクトの動作では，相互作用する可能性

本手法は，オブジェクト指向プログラムの実行のあるクラスのすべてではなく，いくつかのクラ時情報を用いる動的解析手法の 1 つである．利用

スとのみ相互作用する場合がある．たとえば，画者は，解析したいソフトウェアを実行し，動作中面に表示されるデータとそうでないものなど，オに行われた各メソッド呼び出しについて，実行さブジェクトごとの性質の違いから，相互作用するれたスレッドの識別子，タイムスタンプ，呼び出クラスの組み合わせが異なることが期待され [5]，し元（呼び出した）オブジェクトのクラスと ID，Gc (ck ) はこのような振舞いの差を認識する．
一 方 ，関 連 メ ソッド に 基 づ く グ ル ー プ 化

呼び出し先（呼び出された）オブジェクトのクラGm (ck ) = {G1 , · · · , Gl } は，以下の条件を満たすようにオブジェクトをグループに分類する．

スと ID，メソッドシグネチャの情報を実行履歴として取得する必要がある．本研究では，Java を対∀o1 , o2 ∈ Gi (1 ≤ i ≤ l) ↔ M ethods(o1 ) =M ethods(o2 ) ∧ Called(o1 ) = Called(o2 )Gm (ck ) で同一のグループに分類されたオブジェ象として実装を行っており，Amida[1] を用いて実行履歴を取得している．

3.2

各オブジェクトの動作コンテキストの抽出

クト群は，呼び出されたメソッド，呼び出したメ

本手法では，あるオブジェクト o の振舞いを，そソッドが完全に一致する．この分類基準は，Gc (ck )の相互作用に関わるクラスやメソッドの集合に近による分類と異なり，どのクラスから呼ばれてい似する．具体的には，実行履歴から，各オブジェても，呼び出されるメソッドが一致するとき，オブクトについて以下の 4 つの集合を計算する．なお，ジェクトを同じグループへと分類する．ユーティリ

コンストラクタ呼び出しはメソッド名が ⟨init⟩ でティクラスのように多くのクラスから利用されてあるメソッド呼び出しとして扱う．

いるクラスでは，どのクラスから利用されていて• U se(o) ：オブジェクト o に対してメソッド呼び出しを行ったクラスの集合．
• U sed(o) ：オブジェクト o からメソッド呼び出も，振舞いはほぼ同じであることが期待され，利用のされ方の違いをグループ化に反映する．
なお，これらのグループ化は，同値類としてのしを行なわれたクラスの集合．

性質を満たしている．そのため，解析対象のクラ• M ethods(o) ：オブジェクト o の呼び出されたメソッドの集合．

スのオブジェクト数を n ，グループ化後のグループ数を g とすると，グループの構築を単純に行っ• Called(o) ：オブジェクト o が呼び出したメソッドの集合．

た場合の時間計算量は O(gn) で済む．オブジェク
トが多数あるときは g ≪ n であることが期待され-3-るため，実質的な時間計算量は O(n) である．

3.4

グループの振舞いの可視化

オブジェクトのグループ化結果を用いて，グループに含まれたオブジェクトの振舞いを明らかにする．本研究では，2 種類の可視化手法を用いた．

1 つは，各グループから代表オブジェクトをランダムに選択し，直接呼び出し関係のあるオブジェ

図 1: Scheduler のスクリーンショット

クト群との相互作用に関するイベントだけを実行スとの呼び出し関係グラフを抽出し可視化する手履歴から抽出，シーケンス図として可視化する手法を用いる．

法である．この手法はあるグループについて，1 つ4の具体的な動作例を読解したい場合に有効である．

実装

ただし，グループ内に含まれているオブジェクト

本手法を Amida-OGAN というツールに実装しがまったく同一の振舞いをしているとは限らない．

た．我々のグループでは既に，Java プログラムか適切な代表オブジェクトをグループ内から選択すら実行履歴を取得しシーケンス図として可視化する手法は，今後の課題である．

る Amida を開発している [8]．実行履歴の取得にはトの各グループと周辺クラスとの呼び出し関係を，Javassist[9] を用いており，実行時情報を出力する
コードを解析対象のプログラムに埋め込んで，プ有向グラフとして可視化する手法である [2]．このログラムを実行している．シーケンス図による可視

もう 1 つは，Salah らが提案した，オブジェク

化機能は Amida の機能をそのまま使用しており，有向グラフは，頂点として，オブジェクトのグループと，周辺のクラスを用いる．ある頂点のグルー

メソッド呼び出し関係の可視化には GraphViz¶1 をプあるいはクラスに属するオブジェクトの内 1 つ用いている．

でも，ある別の頂点に属するオブジェクトへと 1

5

ケーススタディ度でもメソッド呼び出しを行っていた場合に，そ実装した Amida-OGAN を用いて，Java プログ

れらの頂点間に有向辺を作成する．このグラフは，

ラム Scheduler の動作を分析するケーススタディ

グループごとに相互作用するクラス群の差異を効を実施した．

果的に提示する．

Scheduler は小規模の予定管理用カレンダープログラムである．図 1 に起動直後のウィンドウのス

3.5

クラス間の相互作用例の抽出

3.4 節の可視化手法は，あるクラスのグループごとの振舞いの差異を可視化するが，グループ間のクリーンショットを示す．ユーザが予定を記入した呼び出し関係を用いて，2 つの異なるクラス cs , ct

イアログが開き，予定を編集できる．

い日付に対応するセルをクリックすると新たにダの間の相互作用を分析することも可能である．具体本ケーススタディでは，予定データの管理方法

的には，グループ G(cs ) = {s1 , · · · , sm }, G(ct ) =を分析するというシナリオで，実際に Scheduler を{t1 , · · · , tn } に対して，P (si , tj ) = {(o1 , o2 )|o1 ∈si ∧ o2 ∈ tj ∧ Reachable(o1 , o2 )} を抽出する．た

起動し，それぞれ異なる日付に計 3 つの予定を追だし，Reachable(o1 , o2 ) は，実行履歴中で，少なソッド呼び出しイベントと，1975 個のオブジェクト

くとも 1 回，o1 からのメソッド呼び出しが o2 にが含まれていた．ただし，java,javax,sun,com.sun,（直接あるいは推移的に）到達するという条件を意パッケージに含まれるクラスのイベントは除外し味する．ている．

加した．この動作で得た実行履歴には 7523 個のメ相互作用例の可視化には，オブジェクトのグルー

Scheduler は 2 つのクラス，DateCell と Calen-プ G(ck ) の場合と同様に，P (si , tj ) からオブジェ

darDate を用いて予定の管理を行っている．DateCell はカレンダーの各日付を表現するセルの役割

クトのペアをランダムに選択，シーケンス図として可視化する手法と，グループ間および関連クラ¶1 GraphViz. http://www.graphviz.org/-4-Group ID
s1
s2
s3s4

表 1: グループ Gc (DateCell) = {s1 , s2 , s3 , s4 }#Instances U se(o), U sed(o)(o ∈ sk )882{MonthTableModel},{}33{MonthTableModel,DateCellRenderer},{}90{MonthTableModel,DateCellRenderer},{CalendarDate}
3{MonthTableModel,DateCellRenderer,CalendarFrame},{CalendarDate}
S1[882]scheduler.gui.MonthTableModel

S3[90]

scheduler.gui.DateCellRendererS2[33]

scheduler.gui.RegisterDialog

scheduler.domain.FixedScheduleS4[3]scheduler.domain.CalendarDate

scheduler.domain.ScheduleList

scheduler.gui.CalendarFramescheduler.domain.Scheduler
scheduler.domain.CalendarMonth

図 2: DateCell をグループ化したクラス間の呼び出し関係グラフ．Gc (DateCell) = {s1 , s2 , s3 , s4 }を担うクラスであり．CalendarDate は各日付の予定データを保持するクラスである．取得した実行
履歴中には 1008 個の DateCell オブジェクト，730個の CalendarDate オブジェクトが出現しており，単純に可視化するには多すぎる．そのため，この2 つのクラスに対して提案手法を適用し，動作シナリオおよび代表的な相互作用の可視化を試みた．
5.1

関連クラスに基づく DateCell の振舞いの分析
図 3: DateCell クラスのグループ s2 に属するオ

DateCell クラスの代表的な動作シナリオを可視

ブジェクトの振る舞いを可視化したシーケンス図．

化するために，関連クラスに基づくグループ化を

DateCellRenderer からの描画情報の要求に応じている．

適用したところ，DateCell のオブジェクトは 4 グ
ループ Gc (DateCell) = {s1 , s2 , s3 , s4 } に分類された．グループの関連クラスとオブジェクト数を表 1 に，グループに属するオブジェクトと他のクケンス図で振舞いを可視化した．結果を図 3, 図 4,ラスとの呼び出し関係を図 2 に示す．DateCell ク

図 5 に示す．s1 に含まれるオブジェクトの振舞い

ラスと他のクラスの呼び出し関係は，グループ化は，システム起動時に MonthTableModel オブジェを行わなければ一見多くのクラスと関係するようクトからコンストラクタ呼び出しを 1 回受けていに見える．しかし，グループ化を行うと，大多数のるだけの単純なものだったため省略した．

オブジェクトを含む s1 は MonthTableModel オブ

どの図においても，DateCellRenderer オブジェジェクトから呼び出されているだけであり，また，クトからセルの描画情報を得るために呼び出されCalendarDate オブジェクトに対して実際にメソッド呼び出しを行っているものは s3 ,s4 だけであるていることが確認できる．しかし，s3 , s4 では s2ことなど，プログラム内での使われ方がグループ出している．また，s4 では，ユーザのマウスクリッごとに大きく異なることがわかる．

ク操作の結果，CalendarFrame オブジェクトからDateCell クラスのグループ s2 , s3 , s4 からそれぞれ代表オブジェクトを 1 つランダムに選び，シーもメソッドを呼び出されていることが確認できる．と異なり，CalendarDate オブジェクトを更に呼びこれは DateCell クラスが担っているセルの性質の-5-図 4: DateCell クラスのグループ s3 に属するオブジェクトの振る舞い．DateCellRenderer からの要求に対して，CalendarDate に予定データの有無を

図 5: DateCell クラスのグループ s4 に属する問い合わせている．

オブジェクトの振る舞い．ユーザのマウス操作に関するメソッド table mouseClicked(MouseEvent)

表 2:

Gc (DateCell)={s1 , s2 , s3 , s4 } とが呼び出されている．

Gc (CalendarDate) = {t1 , t2 , t3 } の関連
t1 (637)
t2 (90)t3 (3)
s1 (882)
s2 (33)s3 (90)90 組 (1 対 1)
s4 (3)
3 組 (1 対 1)

おり，s3 と t2 の間に 90 組，s4 と t3 の間に 3 組，いずれも 1 対 1 の呼び出し関係となっていた．
これらのグループ間の呼び出し関係グラフを，図6 に示す．CalenderFrame オブジェクトと相互作用する DateCell クラスのグループ s4 は，予定を違いからくる振舞いの差を示していると考えられ，追加するダイアログの役割を担う RegistorDialog

実際により詳しく解析を行ったところ，s1 はカレオブジェクトと相互作用する CalendarDate クランダーとして画面に 1 度も表示されなかったセル，スのグループ t3 とのみ関連していることがわか

s2 は図 1 において灰色で表示されている日付の無る．実際にこの組み合わせで呼び出し関係のある

いセル，s3 は日付と対応しているセル，s4 は日

オブジェクトのペアをランダムに 1 つ選び振舞い付に対応していて，かつ予定が追加されたセルでをシーケンス図に可視化したところ，図 7 に示すあった．関連するクラスに基づくグループ化の目ように，ユーザ操作により予定データを追加する

的は，オブジェクトの性質の違いからくる振舞い振舞いが確認できた．の差を識別することであり，この例では目的を達5.3成できていると考えられる．

5.2

関連メソッドに基づくグループ化

続いて，CalendarDate クラスから呼び出されるクラス間の相互作用例の抽出

ScheduleList クラスを分析した．このクラスは予

次に，DateCell クラスのグループ {s1 , s2 , s3 , s4 }定データをリスト構造で保持するクラスであるが，と，CalendarDate クラスを関連するクラスに基づ

この関連するクラスに基づくグループ化では分類いて分類したグループ {t1 , t2 , t3 } との間の呼び出できず，単一のグループとなった．しかし，関連し関係を分析した結果を表 2 に示す．表 2 で，グするメソッドに基づくグループ化では表 3 に示す

ループ ID 横の 内の数値はそのグループに含まれように，Gm (ScheduleList) = {u1 , u2 , u3 } というるオブジェクト数を表していて，さらにその横の結果が得られた．

括弧内は関係性を表している．両クラス間には，2それぞれの代表オブジェクトをシーケンス図に通りの組み合わせの呼び出し関係だけが存在して可視化すると，特に u3 は振舞いが他のグループと-6-

S1[882]

S3[90]
S3[90]->T2[90](1:1)

scheduler.gui.MonthTableModelscheduler.gui.DateCellRendererscheduler.domain.CalendarMonthT2[90]

S2[33]

T1[637]scheduler.domain.Scheduler

T3[3]scheduler.domain.FixedScheduleS4[3]scheduler.gui.CalendarFrame

S4[3]->T3[3](1:1)

scheduler.domain.ScheduleList

scheduler.gui.RegisterDialog

図 6: Gc (DateCell) = {s1 , s2 , s3 , s4 } と Gc (CalendarDate) = {t1 , t2 , t3 } 間の呼び出し関係グラフ

Group IDu1u2u3

表 3: グループ Gm (ScheduleList) = {u1 , u2 , u3 }#Instances M ethods(o), Called(o)(o ∈ uk )90{⟨init⟩(),iterator(),hasValids(Date)},{}
3{⟨init⟩(),iterator(),hasValids(Date),add(Schedule)},{}
7{⟨init⟩(),iterator(),hasValids(Date),clear()},{}

大きく異なっていた．この原因は，CarendarDate

スケーラビリティを確認したいと考えている．まクラスのグループ {t1 , t2 , t3 } との関連を解析する

た，より多くのケーススタディで，グループに含ことで明らかとなった．表 4 に示すように，u1 ,u2

まれるオブジェクトの振舞いを分析し，グループは 1 対 1 で，u3 は 1 対多で CalendarDate クラス化の妥当性を検証する必要がある．のオブジェクトと関係しており，関係性が異なる謝辞ことがわかる．実際にそれぞれの組み合わせの代本研究は，日本学術振興会科学研究費補助金若表ペアをシーケンス図に可視化したところ，u1 ,u2

手研究（スタートアップ）（課題番号:19800021）のは各日付ごとの予定データを管理し，u3 は曜日ご助成を得た．との予定データを管理していると判明した．この参考文献

ように，関連するメソッドに基づくグループ化は，[1] Ishio, T., Watanabe, Y. and Inoue, K.:
AMIDA: a Sequence Diagram Extraction

同じクラス群と相互作用しているオブジェクトの振舞いの違いを識別する場合に有効である．

6

Toolkit Supporting Automatic Phase Detection. Proceedings of the 30th International Conference on Software Engineering,

まとめと今後の課題
実行履歴の可視化により特定のクラスの機能を理解しようとするとき，そのクラスのすべてのオ

pp.969–970, 2008.

ブジェクトの振舞いを逐一確認することは現実的[2] Salah, M. and Spiros, M.:

ではない．本研究では，ある 1 つのクラスのオブ

A Hierarchy

みを可視化することで，クラスの代表的で具体的

of Dynamic Software Views: from ObjectInteractions to Feature Interacions. Proceedings of the 20th International Conference onな振舞いのみを確認する手法を提案した．

Software Maintenance, pp.72–81, 2004.

ジェクトを，関連する呼び出しの属性に基づいてグループ化し，各グループの代表オブジェクトの本研究ではグループの振舞いの可視化にあたっ[3] Salah, M. and Spiros, M.: Scenariographer:て，代表オブジェクトをグループ内からランダム

A Tool for Reverse Engineering Class Usage Scenarios from Method Invocation Sequences. Proceedings of the 21st Interna-に選択しているが，グループ内に含まれているオブジェクトがまったく同一の振舞いをしているとは限らない．適切な代表オブジェクトをグループ

tional Conference on Software Maintenance,
pp.155–164, 2005.

内から選択する手法は今後の課題である．その他にも，より大規模なシステムに適用し，提案手法の-7-図 7: DateCell クラスのグループ s4 と CalendarDate クラスのグループ t3 の相互作用例を可視化したシーケンス図．ユーザのマウス操作に関するメソッド呼び出し後，DateCell から CalendarFrame を経てRegisterDialog に CalendarDate が渡されたのち，RegisterDialog により予定データが追加されている．

表 4: Gc (CalendarDate) = {t1 , t2 , t3 } と Gm (ScheduleList) = {u1 , u2 , u3 } の関連
u1 (90)u2 (3)
u3 (7)
t1 (637)t2 (90)90 組 (1 対 1)
90 組 (多対 1)
t3 (3)
3 組 (1 対 1) 3 組 (多対 1)[4] Reiss, S.P., and Renieris, M.: Encoding program executions. Proceedings of the 23rd
International Conference on Software Engi-

Support Object-Oriented Programs. IEEE
Transactions on Software Engineering,
Vol.18, No.12, pp.1038–1044, 1992.

neering, pp.221–230, 2001.

[8] 谷口 考治, 石尾 隆, 神谷 年洋, 楠本 真二, 井上克郎: プログラム実行履歴からの簡潔なシー[5] Richner, T. and Ducasse, S.: Using Dy-ケンス図の生成手法. コンピュータソフトウェ

namic Information for the Iterative Recoveryof Collaborations and Roles. Proceedings ofthe 18th International Conference on Soft-ア, Vol.24, No.3, pp.153–169, 2007.

[9] 千 葉 滋:

ware Maintenance, pp.34–43, 2002.

Home

http://www.csg.is.titech.ac.jp/∼chiba/javassist/index.html.

[6] Valentin, D., Christian, L., Andrzej, W.
and Andreas, Z.: Mining Object Behavior
with ADABU. Proceedings of the 4th International Workshop on Dynamic Analysis,
pp.17–23, 2006.
[7] Wild, N. and Huitt, R.:

Javassist

Maintenance-8-Page,