首页 理论教育 接口时序关系建模:探索与成果

接口时序关系建模:探索与成果

时间:2023-11-17 理论教育 版权反馈
【摘要】:在本节中,将详细分析接口间的时序关系,并对它们进行形式化建模。图10接口间的三种基本时序关系这三种接口间的时序关系是接口间最基本的时序关系,一个软件系统中接口调用的时序关系都可以用这三种关系组合而成。为了更好地描述接口与接口之间的时序关系,本节对描述逻辑在时态领域进行了扩展。

接口时序关系建模:探索与成果

前两节中介绍的引发关系和条件限定关系,只描述了接口之间的调用关系,没有刻画接口与接口之间调用的时序关系,而在软件系统中接口有多种调用方式,包括顺序调用、并行调用等。在本节中,将详细分析接口间的时序关系,并对它们进行形式化建模。

假设接口ai(i=1,2,…,n)是概念接口API的实例。

(1)顺序调用(Sequence)

若接口a1,a2,…,an是顺序调用的接口序列,则在调用a1后,会依次顺序调用后续的各个接口,如图10(a)所示。接口ai+1的调用一定是在接口ai的调用之后。例如,在图6 的示例中,接口CheckMaterial(用来查看厨房是否还有足够的食材)一定是在接口ReduceInventory(用来减少厨房食材的持有量)之前被调用,它们之间有明确的先后顺序。

同样是在图6 的示例中,在通过接口CheckMaterial确认厨房还有足够的食材后,会引发的两个接口:接口ReduceInventory(用来减少厨房食材的持有量)和接口PrepareOrder(用来照订单准备所需菜品),它们之间没有依赖关系,并且在实现功能上没有交集,互不影响,因此它们可以是同时并行调用,也可以是一前一后调用,并且谁先谁后并不是强制的。因此就有了下面两种调用关系:

(2)不确定调用(Uncertain)

接口b 的调用引发了接口集合{a1,a2,…,an}被调用,但是接口集合中每个接口被调用的先后顺序是不确定的,如图10(b)所示。并且这种不确定的先后顺序并不会影响到系统的运行。通常这种不确定的调用发生在没有依赖关系且功能没有交集的接口之间。

(3)并行调用(Parallel)

若接口a1,a2,…,an是并行调用的接口序列,则在调用a1的同时,也会调用序列中的其他各个接口,如图10(c)所示。

图10 接口间的三种基本时序关系

这三种接口间的时序关系是接口间最基本的时序关系,一个软件系统中接口调用的时序关系都可以用这三种关系组合而成。

如前文所述,本体的逻辑基础是描述逻辑,而描述逻辑可以有效地描述静态知识,但是却难以处理具有时态关系的动态知识。为了更好地描述接口与接口之间的时序关系,本节对描述逻辑在时态领域进行了扩展。

描述逻辑的基本知识在文献[114]中有详细的介绍,在此就不再赘述了。本节根据应用需要,主要是在传统的描述逻辑上扩展4 个时序逻辑构造子:○(下一个时刻)、□(将来总是)、◇(将来的某一时刻)和∪(直到)。这4 个操作符在时序逻辑中都有定义,其中,○、□和◇是一目算子,∪是二目算子。在时序逻辑中,○称为next算子,○p 意味着,p 将在下一个时刻为真;□称为always算子,□p 意味着,p 将在所有的将来时刻(包括现在)为真;◇称为eventually算子,◇p 意味着,p 将在某个将来时刻(可能现在)为真;∪称为until算子,p∪q 意味着,存在一个将来时刻,q 将在该时刻为真,并且使得直到那个时刻之前p 都一直为真。

扩展后的描述逻辑有了可以描述时间的构造子,接下来就可以定义接口与接口之间的三种基本时序关系。

(1)顺序调用

接口a1,a2,…,an是顺序调用的接口序列,首先调用接口a1,然后依次调用序列中其他的接口。

(2)不确定调用

接口b 的调用引发了接口集合{a1,a2,…,an}被调用,接口集合中每个接口被调用的先后顺序是不确定的,但是执行过程中若选择了某一调用顺序后,接口的调用顺序就不能再改变了。

其中( 1 ≤i≤n)

接口ai是接口集合{a1,a2,…,an}中的某一个接口,接口ai被调用后,再调用的接口便是从接口集合{ a1,a2,…,ai-1,ai+1,…,an}中选择,这个集合不再包含接口ai

(3)并行调用

接口集合{a1,a2,…,an}中的每一个接口都同时被调用。

这样,在前一小节中介绍的,当所有api都运行结束后才能调用下一组接口,也能形式化表示出来。

例如:只有当接口集合{a1,a2,…,an}中所有的接口都执行结束后才能继续调用下一个接口b,这一过程便可以形式化表示为:a1 ∧a2 ∧...∧an→○◇b

在描述逻辑中,是通过构造子来构造出复杂的概念和关系,而在本体中,不能直接使用描述逻辑中的构造子,但是描述逻辑中通过构造子构造出复杂的概念和关系可以在本体中都有相应的表示。接下来就要定义本体中用来表示时间的谓词。(www.xing528.com)

我们知道,一个接口的执行是一个时间段T,有开始时间(startTime),也有结束时间(endTime),如图11 所示。

图11 接口的执行时间段

定义11 (开始时间startTime)若接口a在时间t被调用,并开始执行,则记作startTime(a,t)。

同样,可以定义接口的结束时间endTime()。

定义12 (开始时间endTime)若接口a在时间t执行结束,则记作endTime(a,t)。

在时间轴上,两个时间点的关系只有两种,相遇[如图12(a)所示]和不相遇[如图12(b)所示]。

图12 时间点的两种关系

从图12 中可以看出,时间点在时间轴上相遇,意味着两个时间点相等;时间点在时间轴上不相遇,则两个时间点中必有一个在前,一个在后。

定义13 (前后关系before/after)接口a1在t1时刻被调用,接口a2在t2时刻被调用,若时间点t1先于时间点t2,则记作before(a1,a2),也可记作after(a2,a1),表示接口a2的调用晚于接口a1

定义14 (相遇关系meet)接口a1在t1时刻被调用,接口a2在t2时刻被调用,若时间点t1 与时间点t2 在时间轴上相遇,即处于同一时间点,则记作meet(a1,a2)。

仅仅定义前后关系(before/after)是不够的,因为它无法准确表示出下一时刻(Next)的含义。例如,在顺序调用序列{a1,a2,…,an}中,若接口a1先于接口a2被调用,则存在关系before(a1,a2);若接口a2要先于接口a3被调用,则存在关系before(a2,a3),显然关系before(a1,a3)也是成立的,即接口a1先于接口a3被调用,然而只有接口a2是在接口a1的下一时刻被调用的。因此要区分这之间的差别,还需要定义具有下一时刻(Next)含义的紧跟关系(dirBefore/dirAfter)。

定义15 (紧跟关系dirBefore/dirAfter)接口a1在t1时刻被调用,接口a2在t2时刻被调用,若时间点t1先于时间点t2,且在时间点t1与时间点t2之间的时间区间内,没有接口被调用。则称接口a2 在调用时间轴上紧跟接口a1 的调用。记为dirBefore(a1,a2),或dirAfter(a2,a1)。

显然,定义13 中的前后关系(before/after)与定义14 中的相遇关系(meet)都是具有传递性质的,而定义15 中的紧跟关系(dirBefore/dirAfter)则没有。因为若接口a2在调用时间轴上紧跟接口a1的调用,存在关系dirBefore(a1,a2),假设接口a3在调用时间轴上紧跟接口a2的调用,则存在关系dirBefore(a2,a3),显然接口a3在调用时间轴上不是接口a1 的下一个紧跟调用,因此不存在关系dirBefore(a1,a3),传递性质在紧跟关系(dirBefore/dirAfter)上是不成立的。

(1)顺序调用

若接口序列{a1,a2,a3}顺序调用,则接口a1 执行完后才会调用接口a2,而接口a3的调用在接口a2之后。

完成时间t1'的下一个时刻便是接口a2调用开始的时间t2,同样,接口a2执行完成时间t2'的下一个时刻便是接口a3调用开始的时间t3。即:

Sequence(a1,a2,a3) →before(a1,a2))∧before(a2,a3

(2)不确定调用

若接口序列{a1,a2,a3}调用顺序不确定,则有6 种调用顺序,但程序运行时只能选择其中之一,不论哪种调用顺序,接口的执行时间区间都是不相交的,因此接口a1的调用开始时间t1的下一时刻是接口a1的执行完成时间t1',对于接口a2、a3也是同样的。即:

Uncertain(b,{a1,a2,a3})→ before(b,a1)∧before(b,a2)∧before(b,a3)∧((before(a1,a2)∧(before(a2,a3))∨(before(a1,a3)∧(before(a3,a2)) ∨(before(a2,a1)∧(before(a1,a3))∨(before(a2,a3)∧(before(a3,a1))∨(before(a3,a1)∧(before(a1,a2))∨(before(a3,a2)∧(before(a2,a1)))

(3)并行调用

若接口序列{a1,a2,a3}并行调用,则有接口a1调用开始的时间t1与接口a2的调用开始时间t2,以及接口a3的调用开始时间t3,在时间轴上位于同一时刻。即:

Parallel(b,{a1,a2,a3})→before(b,a1)∧before(b,a2)∧before(b,a3)∧meet(a1,a2)∧meet(a2,a3

举例说明接口之间时序关系在接口定位中的应用,如在Windows API中,调用了函数FindFirstVolume来获取第一个驱动器的GUID,在这之后的某一个时间点必然需要调用函数FindVolumeClose来关闭函数FindFirstVolume返回的句柄,这两个函数之间存在明显的时序关系。因此它们之间的关系可以表示为:

before(FindFirstVolume,FindVolumeClose)

当在一段代码中定位到函数FindFirstVolume,那么在距离该函数不远处必然应该能定位到函数FindVolumeClose。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈