您是否经常在API文档(例如"公共函数的javadoc"中)中看到"值限制"的描述以及经典文档?
注意:我不是在谈论代码中的注释
"价值限制",我的意思是:
样品:
我经常看到的(无法访问源代码)是:
/**
* Get all readers name for this current Report. <br />
* <b>Warning</b>The Report must have been published first.
* @param aReaderNameRegexp filter in order to return only reader matching the regexp
* @return array of reader names
*/
String[] getReaderNames(final String aReaderNameRegexp);
Run Code Online (Sandbox Code Playgroud)
我希望看到的是:
/**
* Get all readers name for this current Report. <br />
* <b>Warning</b>The Report must have been published first.
* @param aReaderNameRegexp filter …Run Code Online (Sandbox Code Playgroud) 我正在研究几个C项目,我想使用自动定理证明来验证代码.理想情况下,我只想使用ATP来验证函数契约.C/gcc或外部软件/软件包/等中是否有任何功能可以实现按合同样式编码?
如果没有那么那只是激励我自己开始.
我对此的引用类似于Spec#或来自MSR的Sing#,但我是一个开源人员,我正在寻找开源解决方案.
我很好奇在埃菲尔社区之外的实践中使用了多少合同设计.是否有任何使用按合同设计的活跃开源项目?
或者,将问题重新整合为一个具有单一答案的问题:什么是使用最广泛的(非埃菲尔)开源项目?
以下是实现此目标的典型方法:
public void myContractualMethod(final String x, final Set<String> y) {
if ((x == null) || (x.isEmpty())) {
throw new IllegalArgumentException("x cannot be null or empty");
}
if (y == null) {
throw new IllegalArgumentException("y cannot be null");
}
// Now I can actually start writing purposeful
// code to accomplish the goal of this method
Run Code Online (Sandbox Code Playgroud)
我认为这个解决方案很难看.您的方法很快就会填充样板代码来检查有效的输入参数契约,从而模糊了方法的核心.
这是我想要的:
public void myContractualMethod(@NotNull @NotEmpty final String x, @NotNull final Set<String> y) {
// Now I have a clean method body that isn't obscured …Run Code Online (Sandbox Code Playgroud) 我有一些代码与以下逻辑:
//pseudo-code
foreach (element in elementList) {
if (element is whatever)
return element;
}
}
Run Code Online (Sandbox Code Playgroud)
理论上,总有一个元素是什么,所以这个方法应该没有问题.在任何情况下,我都在方法的最后确定了一个断言,以确保:
//pseudo-code
foreach (element in elementList) {
if (element is whatever)
return element;
}
}
Contract.Assert(false, "Invalid state!");
Run Code Online (Sandbox Code Playgroud)
问题是因为这个方法必须返回一些东西,并且编译器不理解断言会破坏程序执行.在使用Contracts之前,在这种情况下,我曾经抛出一个Exception,它解决了这个问题.你会如何处理Contract.Assert()?在Contract.Assert()调用之后返回null或default(element_type),知道它永远不会被调用并关闭编译器吗?或者还有其他更优雅的方式吗?
谢谢
我知道这个问题与以前发布的其他问题非常相似,但我想以适当的方式讨论这个话题.
你认为"明显的"例外应该进行单元测试吗?
明显的异常我的意思是例如由于空参数或空字符串或负数而导致的异常,在我们单元的业务逻辑使我们明白这些异常将始终在我们的方法的开头被抛出之前操作.
换句话说,我说的是违反类合同最简单部分后应该抛出的异常.
谢谢您的意见.
下面是一个非常简单的例子.当我打开静态分析警告时,我仍然得到 警告CodeContracts:确保未经证实:Contract.Result()!= string.Empty
在线上
return string.Format("{0},{1}",movie.Title,movie.Description);
请看下面的代码
namespace CodeContractsSamples
{
public class MovieRepo
{
public string GetMovieInfo(Movie movie)
{
Contract.Requires(movie != null);
Contract.Ensures(Contract.Result<string>() != string.Empty);
return string.Format("{0}, {1}", movie.Title, movie.Description);
}
}
public class Movie
{
public string Title { get; set; }
public string Description { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
是否有一个框架或库,可以帮助我在我的应用程序中按合同实现设计?
在最好的情况下,它会在注释中使用类似注释的javadoc.
我想知道好的合同在哪里结束,偏执狂开始了.真的,我只是不知道开发人员应该关心什么,他应该忘记什么:)
假设我有一个包含值的类,比如java.lang.Integer.它的实例由其他对象(MappedObjects)(一对多或多对多)聚合,并且经常在MappedObjects的方法中使用.出于性能原因,我还在TreeMap中跟踪这些关系(guava MultiMap,无所谓),以便能够快速迭代绑定到某些Integer键范围的MappedObjects.因此,为了使系统保持一致状态,我应该修改MappedObject.bind(整数整数)方法来更新我的Map,如:
class MappedObject {
public void bind (Integer integer) {
MegaMap.getInstance().remove(fInteger, this);
fInteger = integer;
MegaMap.getInstance().add(fInteger, this);
}
...
private Integer fInteger;
}
Run Code Online (Sandbox Code Playgroud)
我可以使用这个最终方法制作抽象的MappedObject类,强制其他人继承它,但它很粗鲁.如果我将MappedObject定义为具有方法bind()的接口并提供骨架实现 - 其他开发人员可能稍后忘记将其包含在对象中并自己实现方法而不进行Map更新.
我一直试图找出编写测试友好代码的最佳实践,但更具体地说是与对象构造相关的实践.在蓝皮书中,我们发现在创建对象时应该强制执行不变量,以避免我们的实体,值对象等的损坏,考虑到这一点,Design By Contract似乎是避免我们的对象损坏的解决方案,但是当我们遵循这个,我们最终可能会编写如下代码:
class Car
{
//Constructor
public Car(Door door, Engine engine, Wheel wheel)
{
Contract.Requires(door).IsNotNull("Door is required");
Contract.Requires(engine).IsNotNull("Engine is required");
Contract.Requires(wheel).IsNotNull("Wheel is required");
....
}
...
public void StartEngine()
{
this.engine.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
嗯,这看起来很好看吗?看来我们正在构建一个安全类,暴露了所需的契约,因此每次Car创建对象时我们都可以确定该对象是"有效的".
现在让我们从测试驱动的角度来看这个例子.
我想构建测试友好的代码,但为了能够隔离测试我的Car对象我需要为每个依赖创建一个模拟存根或一个虚拟对象来创建我的对象,即使我可能只是想测试一种方法,只使用这些依赖项之一,如StartEngine方法.遵循Misko Hevery的测试理念我想编写我的测试,明确指出我不关心Door或Wheel对象只是将null引用传递给构造函数,但是因为我正在检查null,所以我不能这样做
这只是一小段代码,但是当您面对真正的应用程序时,编写测试变得越来越难,因为您必须解决主题的依赖关系
Misko建议我们不要滥用代码中的空值检查(这与设计合同相矛盾)因为这样做,编写测试会变得很痛苦,作为替代方案,他认为编写更多的测试比"只有这样的测试"更好.我们的代码是安全的,因为我们到处都有空检查"
你对此有何看法?你会怎么做?什么应该是最好的做法?
unit-testing design-by-contract dependency-injection constructor-injection
c# ×2
java ×2
unit-testing ×2
.net-4.0 ×1
annotations ×1
c ×1
comments ×1
contract ×1
exception ×1
php ×1
validation ×1