我想就合同部分实施设计的想法得到一些意见。 目标是在不需要外部库的情况下,为不提供简单版本的合同(不变量和后置条件)添加语言。
我的例子是用Java编写的,但我认为这个想法适用于很多OO语言。
我们有一个这样的课程:
class myClass{
type1 field1;
type2 field2;
public myClass(type1 param1){
//do something
}
public type3 method1(type1 param1, type3 param2){
if (paramsAreNotOk()){
throw new IllegalArgumentException();
}
// do a lot of things
return //do something
}
}
我们以这种方式扩展上面的代码:
class myClass{
type1 field1;
type2 field2;
public myClass(type1 param1){
//do something
assert invariant();
}
public type3 method1(final type1 param1, final type3 param2){
assert invariant();
myClass old;
assert ((old = this.clone()) != null)
if (paramsAreNotOk()){
throw new IllegalArgumentException();
}
//do a lot of things
type3 res = //do something
assert method1_post(old, param1, param2, res);
assert invariant();
return res;
}
protected boolean invariant(){
// states something about myClass and return a boolean
// OR
// uses some assertions on some helping methods
}
protected boolean method1_post(myClass old, type1 param1, type3 param2, type3 res){
// states something about res and about the modifications made on old
// OR
// uses some assertions on some helping methods
}
}
这种方法的局限性:
- 没有先决条件
- 合同不是继承的(但请注意,不变量和后置条件受到保护,可以由子类重复使用。)
- 没有检查不变量和后置条件不会修改对象的状态,因此存在副作用的风险。
- 合同不是我们文件中明确的一部分
- 我们需要为每个班级制作克隆。
现在,有些问题:
- 这种方法会以任何方式伤害表演吗?我的意思是,如果断言被禁用,甚至旧的和res局部变量也会被JIT编译器删除?
- 你认为这种做法有什么缺点吗?你为什么不在课堂上使用它?
- 你能建议任何改进吗?
感谢您的阅读和您的意见。
答案 0 :(得分:2)
如果你想要Java的“按合同设计”,你可能想看看(真的)大家伙是怎么做的!以下是Google最近对“Contracts for Java”主题的讨论:
http://google-opensource.blogspot.com/2011/02/contracts-for-java.html
现在回答你的两个问题:
- do you see any downside of this approach? Why wouldn't you use this in your classes?
因为一个缺点是它非常冗长:如此冗长以至于使代码几乎无法读取。
- can you suggest any improvement?
不要重新发明轮子......
答案 1 :(得分:2)
这并不可怕,实际上它是在你面前被别人写的。例如,请参阅Liskov / Guttag的Program Development in Java,它将您的方法用于不变检查,但将其称为repOK()而不是invariant()。
在有限的应用程序中,它有点有用。但是,合同规范不必担心实际代码所做的“谁在调用谁”这一事实,这就产生了许多问题。
我认为DbC很有意思,如果语言有它(或者更好,像Python的函数装饰器那样),或者你有Modern Jass这样的工具,那么就深入研究。但是这样做纯Java是不可行的。也就是说,我正在研究一个不变的检查tool,它会产生类似于你在这里的代码,减去调用链问题(它可以通过扩展类来接受一个知道什么时候适合的访问者来工作。做检查)。它需要Eclipse,并且有自己的问题(主要是私有和静态相关的坏词),但检查机制是纯Java。
答案 2 :(得分:0)
你知道这有什么缺点吗? 进场?你为什么不用这个呢? 你的课程?
我编写的大多数Java类都不可克隆,因为在Java中实现Clonable
并不容易。因此,当不是绝对必要时,我不会实施它。我不想只为你的方法做这件事。