wildcatsの日記

赤羽在住でIT関係の会社の社長やってます。

はじめてのBarter - beyond design by contract

前に角田さんの「オレンジニュース」で紹介されていて触らなきゃと思って放置していたのですが
今日のartonさんの日記のエントリを読んで少し触ってみた。
メイヤー本にある継承におけるDbCの関係*1まではAspectの結合段階ではチェックしてくれないみたい。
# 実行時にはチェックしてくれるけど。
あと一クラスにpreまたはpostとinvariantを併用するとAspectの結合段階で


[ajc] C:\eclipse\workspace\Barter-Example\work\com\wikihouse\wildcats0201\barter\example\PersonBarterAspect.java:40
[error] can't determine precedence between two or more pieces of advice that apply to the same join point: method-execution(void com.wikihouse.wildcats0201.barter.example.Person.setName(java.lang.String))
[ajc] C:\eclipse\workspace\Barter-Example\work\com\wikihouse\wildcats0201\barter\example\PersonBarterAspect.java:24
[error] can't determine precedence between two or more pieces of advice that apply to the same join point: method-execution(void com.wikihouse.wildcats0201.barter.example.Person.setName(java.lang.String))
[ajc] C:\eclipse\workspace\Barter-Example\work\com\wikihouse\wildcats0201\barter\example\PersonBarterAspect.java:76
[error] can't determine precedence between two or more pieces of advice that apply to the same join point: method-execution(void com.wikihouse.wildcats0201.barter.example.Person.setName(java.lang.String))
てなエラーが出てアウト。これは仕組み的に厳しそうですね。無念だ....
一応、動作したサンプルのコードを置いておきます。(無保証)
動作環境
xdoclet-1.1.2
aspectj-1.2
barter-0.2.0

Person.java


package com.wikihouse.wildcats0201.barter.example;

/**
* @barter
*/
public class Person {

private String name;
private int age;
private int money;

/**
* @barter.pre aName!=null
*/
public void setName(String aName) {
this.name = aName;
}

/**
* @barter.post $this.getAge()>=0
*/
public void setAge(int age) {
this.age = age;
}

public String getName() {
return this.name;
}

public int getAge() {
return this.age;
}

/**
* @barter.post $this.getMoney()>=0
*/
public int payMoney() {
this.money = this.money - 100;
return this.money;
}

public int getMoney() {
return this.money;
}

public void setMoney(int money) {
this.money = money;
}
}

PersonTest.java


package test.com.wikihouse.wildcats0201.barter.example;

import junit.framework.TestCase;
import barter.runtime.impl.BarterAssertionFailed;

import com.wikihouse.wildcats0201.barter.example.Person;

public class PersonTest extends TestCase {

public static void main(String[] args) {
junit.textui.TestRunner.run(PersonTest.class);
}

public void testSetName() {
Person person = new Person();
person.setName("aaaa");
try {
person.setName(null);
fail();
} catch (BarterAssertionFailed e) {
assertNull(null);
}
}

public void testSetAge() {
Person person = new Person();
person.setAge(13);
try {
person.setAge(-1);
fail();
} catch (BarterAssertionFailed e) {
assertNull(null);
}
}

public void testMoney() {
Person person = new Person();
person.setMoney(400);
person.payMoney();
person.payMoney();
person.payMoney();
person.payMoney();
try {
person.payMoney();
fail();
} catch (BarterAssertionFailed e) {
assertNull(null);
}
}

}

*1:例えばサブクラスでオーバライドされたメソッドではスーパークラスのメソッドのpreより厳しくしなきゃいけなくてpostは緩めなきゃいけないとか