怎样解释 Design by contract by deed

怎样解释 Design by Contract_百度知道
怎样解释 Design by Contract
提问者采纳
esign by contract (DbC), which extend the ordinary definition of abstract data types with preconditions, also known as contract programming, in accordance with a conceptual metaphor with the conditions and obligations ocontracts&quot. These specifications are referred to as &quot. It prescribes that software designers should define formal, is an approach for designing software, postconditions and invariants, precise and verifiable interface specifications for software components. 契约式设计、 设计原则, programming by contract and design-by-
采纳率100%
其他类似问题
为您推荐:
作文的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁在上一篇文章中,我简单介绍了契约设计(Design by Contract)的现状,还有自己的想法。
这篇文章主要介绍我如何实现了这个设计。
阅读本文前,想再强调一下,本文介绍的是一种实践,而不是技巧,或者能够保证您代码绝对 0 bug的方法。但是在这种实践下,代码 0 bug 是可以达到的。
一个简单的契约设计,就是约束了某个方法调用的要求、以及返回的承诺。比如:
&&&&public&class&Log&&&&{&&&&&&&&public&void&Info(string&message)&&&&&&&&{&&&&&&&&&&&&//do&something&here&&&&&&&&}&&&&}
如果我要调用的方法,前提必须满足message非空。否则这个方法不能保证返回需要的结果。
那么根据经典的计算机原则:在正确的输入下,能够得到正确的输出。我只要保证了我所有调用方法的前提要求,我的代码就是 0 bug。这个就是契约设计。
以往我们会通过各种判断去检测输入,这种设计模式叫做:防范式设计(请看code complete 2,里面有详细介绍)。防范式设计的前提就是:我们会假设调用这个方法是恶意的,因此要对所有可能出错的输入进行检测。
在这种设计模式下,就会导致了各种与业务逻辑无关的代码充斥着我们的程序,维护困难,看起来也恶心。因此契约设计是非常反对的。
可是非常可惜,现在连微软也还走不出这个圈子,一堆的Policy Injection / AOP / attribute / SPec#等等,仍然无法成为主流。
现在我就尝试去走出这个圈子。
首先,我会对这个方法设置一个Contract.Constraint,如果用中文就是契约里面的约束(合同约束)。
&&&&public&class&Log&&&&{&&&&&&&&[Contract.Constraint("message不能空")]&&&&&&&&public&void&Info(string&message)&&&&&&&&{&&&&&&&&&&&&//do&something&here&&&&&&&&}&&&&}
很简单,我什么都没有做,仅仅好像输入了一个注释,内容是messge不能为空。
然后,我去尝试调用这个方法:
&&&&public&class&TestCase&&&&{
&&&&&&&&public&void&call001()&&&&&&&&{&&&&&&&&&&&&string&message&=&"hello&world";&&&&&&&&&&&&Log&log&=&new&Log();&&&&&&&&&&&&(message);&&&&&&&&}&&&&}
乍看一下,好像我还是什么都没有做啊???我是不是在愚弄大家啊???别急,咱们还没有进行契约的验证(合同验证)。
&&&&public&class&TestCase&&&&{&&&&&&&&public&void&test001()&&&&&&&&{&&&&&&&&&&&&MethodInfo&method&=&typeof(TestCase).GetMethod("call001");&&&&&&&&&&&&Console.WriteLine("check&the&call001&can&be&approved&by&contract.");&&&&&&&&&&&&Console.WriteLine("approval&result&=&:"&+&Contract.Approval(method));&&&&&&&&&&&&foreach&(IConstraint&cons&in&Contract.GetOpenConstraints(method))&&&&&&&&&&&&{&&&&&&&&&&&&&&&&Console.WriteLine("the&constraint&of&\""&+&cons.ConstraintName&+&"\"&is&not&committed.");&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public&void&call001()&&&&&&&&{&&&&&&&&&&&&string&message&=&"hello&world";&&&&&&&&&&&&Log&log&=&new&Log();&&&&&&&&&&&&(message);&&&&&&&&}&&&&}
在test001这个方法里面,我对契约进行了验证,因此得到了输出:
check&the&call001&can&be&approved&by&contract.approval&result&=&:Falsethe&constraint&of&"message不能空"&is&not&committed.
结果是:approval result = FAlse
意思就是,契约的约束没有被履行,方法call001是个无效的方法。大家这个时候应该清楚什么意思了吧。
简单说明下,有个契约的约束,要使用这个方法必须履行这个约束,可是我在call001这个方法里面没有履行这个约束,所以合同无效,也就不能保证代码是正确的。
如何保证呢?请看:
&&&&public&class&TestCase&&&&{&&&&&&&&public&void&test002()&&&&&&&&{&&&&&&&&&&&&MethodInfo&method&=&typeof(TestCase).GetMethod("call002");&&&&&&&&&&&&Console.WriteLine("check&the&call002&can&be&approved&by&contract.");&&&&&&&&&&&&Console.WriteLine("approval&result&=&:"&+&Contract.Approval(method));&&&&&&&&&&&&foreach&(IConstraint&cons&in&Contract.GetOpenConstraints(method))&&&&&&&&&&&&{&&&&&&&&&&&&&&&&Console.WriteLine("the&constraint&of&\""&+&cons.ConstraintName&+&"\"&is&not&committed.");&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&[mitment("input&of&log&is&not&null")]&&&&&&&&public&void&call002()&&&&&&&&{&&&&&&&&&&&&string&message&=&"hello&world";&&&&&&&&&&&&Log&log&=&new&Log();&&&&&&&&&&&&(message);&&&&&&&&}&&&&}
在这段代码里面,我的call002调用了。但是我在这个call002里面做了一个承诺[mitment],我保证了这个代码满足了的契约。所以,我得到的测试结果是:
check&the&call002&can&be&approved&by&contract.approval&result&=&:True
结果是:approval result = TRUE,再简单说下,因为我在call002里面使用了承诺,因此在这个承诺范围内,所有契约的约束我都会被满足。
这下子我的思路就清楚拉吧!!老实说,我真的很兴奋!!!因为我找到了通往 0 bug 的道路了!
核心技术介绍
其实思路比较简单的,就是查看当前方法体内 所有使用了的方法是否存在了契约的约束,如果存在了但是没有被履行,那么就认为契约无效。
当然,为了实现这个技巧,我使用了Reflection.Emit,直接操作了IL语言去获取方法体内的信息。
当一个问题无法解决的时候怎么办?采用最简单的方法。Design by contract是个绝对的精华,可惜大部分人总是再想怎么去用代码实现,怎么在编译解析、运行中去实现。
因此我尝试了退一步,海阔天空。就像TestDriven一样,难道我们会在代码里面放各种Assert吗?肯定不会。但是我们在coding的时候需要了。
契约设计也是一样,他是一种编码过程,而不是结果。只有这个思路清晰了,才能豁然开朗。
阅读(...) 评论() 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
Design by Contract Deontic Design Language for Multiagent Systems
下载积分:2000
内容提示:Design by Contract Deontic Design Language for Multiagent Systems
文档格式:PDF|
浏览次数:0|
上传日期: 12:27:13|
文档星级:
该用户还上传了这些文档
Design by Contract Deontic Design Language for Mul
官方公共微信&&raquo&&&raquo&
Bean Validation - Design By Contract
Bean Validation (aka JSR 303) contains an optional appendix dealing with method validation.
Some implementions of this JSR implement this appendix (Apache bval, Hibernate validator for example).
OpenEJB provides an interceptor which allows you to use this feature to do design by contract.
Design by contract
The goal is to be able to configure with a finer grain your contract. In the example you specify
the minimum centimeters a sport man should jump at pole vaulting:
public interface PoleVaultingManager {
int points(@Min(120) int centimeters);
TomEE and OpenEJB do not provide anymore BeanValidationAppendixInterceptor since
Bean Validation 1.1 does it (with a slighly different usage but the exact same feature).
So basically you don't need to configure anything to use it.
If a parameter is not validated an exception is thrown, it is an EJBException wrapping a ConstraintViolationException:
gamesManager.addSportMan("I lose", "EN");
fail("no space should be in names");
} catch (EJBException wrappingException) {
assertTrue(wrappingException.getCause() instanceof ConstraintViolationException);
ConstraintViolationException exception = ConstraintViolationException.class.cast(wrappingException.getCausedByException());
assertEquals(1, exception.getConstraintViolations().size());
OlympicGamesManager
package org.superbiz.
import javax.ejb.S
import javax.validation.constraints.NotN
import javax.validation.constraints.P
import javax.validation.constraints.S
@Stateless
public class OlympicGamesManager {
public String addSportMan(@Pattern(regexp = "^[A-Za-z]+$") String name, @Size(min = 2, max = 4) String country) {
if (country.equals("USA")) {
return new StringBuilder(name).append(" [").append(country).append("]").toString();
PoleVaultingManager
package org.superbiz.
import javax.ejb.L
import javax.validation.constraints.M
public interface PoleVaultingManager {
int points(@Min(120) int centimeters);
PoleVaultingManagerBean
package org.superbiz.
import javax.ejb.S
@Stateless
public class PoleVaultingManagerBean implements PoleVaultingManager {
public int points(int centimeters) {
return centimeters - 120;
OlympicGamesTest
public class OlympicGamesTest {
private static C
private OlympicGamesManager gamesM
private PoleVaultingManager poleVaultingM
@BeforeClass
public static void start() {
Properties properties = new Properties();
properties.setProperty(BeanContext.USER_INTERCEPTOR_KEY, BeanValidationAppendixInterceptor.class.getName());
context = EJBContainer.createEJBContainer(properties).getContext();
public void inject() throws Exception {
context.bind("inject", this);
@AfterClass
public static void stop() throws Exception {
if (context != null) {
context.close();
public void sportMenOk() throws Exception {
assertEquals("IWin [FR]", gamesManager.addSportMan("IWin", "FR"));
public void sportMenKoBecauseOfName() throws Exception {
gamesManager.addSportMan("I lose", "EN");
fail("no space should be in names");
} catch (EJBException wrappingException) {
assertTrue(wrappingException.getCause() instanceof ConstraintViolationException);
ConstraintViolationException exception = ConstraintViolationException.class.cast(wrappingException.getCausedByException());
assertEquals(1, exception.getConstraintViolations().size());
public void sportMenKoBecauseOfCountry() throws Exception {
gamesManager.addSportMan("ILoseTwo", "TOO-LONG");
fail("country should be between 2 and 4 characters");
} catch (EJBException wrappingException) {
assertTrue(wrappingException.getCause() instanceof ConstraintViolationException);
ConstraintViolationException exception = ConstraintViolationException.class.cast(wrappingException.getCausedByException());
assertEquals(1, exception.getConstraintViolations().size());
public void polVaulting() throws Exception {
assertEquals(100, poleVaultingManager.points(220));
public void tooShortPolVaulting() throws Exception {
poleVaultingManager.points(119);
fail("the jump is too short");
} catch (EJBException wrappingException) {
assertTrue(wrappingException.getCause() instanceof ConstraintViolationException);
ConstraintViolationException exception = ConstraintViolationException.class.cast(wrappingException.getCausedByException());
assertEquals(1, exception.getConstraintViolations().size());
-------------------------------------------------------
-------------------------------------------------------
Running OlympicGamesTest
Apache OpenEJB 4.0.0-beta-1
build: :06
http://tomee.apache.org/
INFO - openejb.home = /Users/dblevins/examples/bean-validation-design-by-contract
INFO - openejb.base = /Users/dblevins/examples/bean-validation-design-by-contract
INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Found EjbModule in classpath: /Users/dblevins/examples/bean-validation-design-by-contract/target/classes
INFO - Beginning load: /Users/dblevins/examples/bean-validation-design-by-contract/target/classes
INFO - Configuring enterprise application: /Users/dblevins/examples/bean-validation-design-by-contract
INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container)
INFO - Auto-creating a container for bean PoleVaultingManagerBean: Container(type=STATELESS, id=Default Stateless Container)
INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
INFO - Auto-creating a container for bean OlympicGamesTest: Container(type=MANAGED, id=Default Managed Container)
INFO - Enterprise application "/Users/dblevins/examples/bean-validation-design-by-contract" loaded.
INFO - Assembling app: /Users/dblevins/examples/bean-validation-design-by-contract
INFO - Jndi(name="java:global/bean-validation-design-by-contract/PoleVaultingManagerBean!org.superbiz.designbycontract.PoleVaultingManager")
INFO - Jndi(name="java:global/bean-validation-design-by-contract/PoleVaultingManagerBean")
INFO - Jndi(name="java:global/bean-validation-design-by-contract/OlympicGamesManager!org.superbiz.designbycontract.OlympicGamesManager")
INFO - Jndi(name="java:global/bean-validation-design-by-contract/OlympicGamesManager")
INFO - Jndi(name="java:global/EjbModule/OlympicGamesTest!OlympicGamesTest")
INFO - Jndi(name="java:global/EjbModule/OlympicGamesTest")
INFO - Created Ejb(deployment-id=OlympicGamesManager, ejb-name=OlympicGamesManager, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=PoleVaultingManagerBean, ejb-name=PoleVaultingManagerBean, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=OlympicGamesTest, ejb-name=OlympicGamesTest, container=Default Managed Container)
INFO - Started Ejb(deployment-id=OlympicGamesManager, ejb-name=OlympicGamesManager, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=PoleVaultingManagerBean, ejb-name=PoleVaultingManagerBean, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=OlympicGamesTest, ejb-name=OlympicGamesTest, container=Default Managed Container)
INFO - Deployed Application(path=/Users/dblevins/examples/bean-validation-design-by-contract)
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.245 sec
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
svn co http://svn.apache.org/repos/asf/tomee/tomee/trunk/examples/bean-validation-design-by-contract
cd bean-validation-design-by-contract
mvn clean install
Any help with the documentation is greatly appreciated.
All edits are reviewed before going live, so feel free to do much more than fix typos or links.
If you see a page that could benefit from an entire rewrite, we'd be thrilled to review it.
Don't be surprised if we like it so much we ask you for help with other pages :)
NOTICE: unless indicated otherwise on the pages in question, all editable content available from apache.org is presumed to be licensed under the Apache License (AL) version 2.0 and hence all submissions to apache.org treated as formal Contributions under the license terms.
Copyright &
The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
Apache TomEE, TomEE, Apache, the Apache feather logo, and the Apache TomEE project logo are trademarks of The Apache Software Foundation.
All other marks mentioned may be trademarks or registered trademarks of their respective owners.

我要回帖

更多关于 design by contract 的文章

 

随机推荐