More Related Content
Similar to GContractsの基礎 (20)
GContractsの基礎
- 1. GContracts
の
基礎
Groovy基礎勉強会
2013/03/09
13年3月11日月曜日
- 6. お前誰よ
• 名前:杉浦孝博
• twitter:@touchez_du_bois
• 自称アニメエヴァンジェリスト
• 最近はVB6とVB.NETがお友達
13年3月11日月曜日
- 8. 今回の内容
•契約による設計
• GContractsとは
• GContractsの実際
13年3月11日月曜日
- 10. 契約による設計
• プログラムコードの中にプ
ログラムが満たすべき仕様に
ついての記述を盛り込む事で
設計の安全性を高める技法
(Wikipediaより)。
13年3月11日月曜日
- 11. 契約による設計
• Bertrand Meyer氏の提唱
• 詳細はこんな本で
13年3月11日月曜日
- 12. 契約による設計
• コードの利用者と実装者の
間の契約
• 利用者側が守るべきこと
• 実装者が約束すること
13年3月11日月曜日
- 13. 契約による設計
• 主ロジックとは別に、コー
ドとして契約内容を定義
• コード利用の責任範囲を明
確化
13年3月11日月曜日
- 14. 契約による設計
• 契約の条件
• 事前条件(Precondtion)
• 事後条件(Postcondition)
• 不変条件(Invariant)
13年3月11日月曜日
- 15. 契約による設計
• 事前条件
• サブルーチンの開始時に満
たされるべき条件
• 呼び出し側が守ること
13年3月11日月曜日
- 16. 契約による設計
• 事後条件
• サブルーチンの終了時に保
証されるべき条件
• 実装側が守ること
13年3月11日月曜日
- 17. 契約による設計
• 不変条件
• 公開している操作の実行後
に常に保証されるべき条件
• 実装側が守ること
13年3月11日月曜日
- 18. 詳しくは
• 原本で
13年3月11日月曜日
- 19. 詳しくは
••
@t_wadaさんの
http://www.slideshare.net/t_wada/exception-
design-by-contract#btnPrevious
13年3月11日月曜日
- 21. 言語標準な言語
• Eiffel
• Bertrand Meyer氏考案
• D言語
13年3月11日月曜日
- 22. Java
• 標準
• assert文
• ライブラリ
• Contract4J, cofoja
13年3月11日月曜日
- 23. Groovy
• 標準
• assert文(PowerAssert)
• ライブラリ
• GContracts
13年3月11日月曜日
- 24. GContracts
• Andre Steingress氏による
契約プログラミング用のラ
イブラリ
• https://github.com/
andresteingress/
13年3月11日月曜日
- 25. GContracts
• アノテーションにより満た
すべき条件をコード中に記述
• 条件のコード内容は
GroovyDocに出力可能
13年3月11日月曜日
- 26. GContracts
• 事前条件 -> @Requires
• メソッドに指定
• 事後条件 -> @Ensures
• メソッドに指定
• 不変条件 -> @Invariants
• クラスに指定
13年3月11日月曜日
- 27. GContracts
• 各条件をクロージャで記述
• 契約に違反した場合、
PowerAssertでエラー出力
13年3月11日月曜日
- 28. GContracts
• @Ensuresのクロージャ内
では、次の値を参照できる
• old : メソッド実行前の状
態。Map
•
13年3月11日月曜日
result : 実行結果
- 29. GContracts
• 各条件を継承
• 各条件をクラスだけでなく
インタフェースにも指定可
13年3月11日月曜日
- 30. GContracts
import org.gcontracts.annotations.*
@Invariant({ speed() >= 0 })
class Rocket {
int speed = 0
@Requires({ isStarted() })
@Ensures({ old.speed < speed })
void accelerate() { ++speed }
boolean isStarted() { true }
int speed() { speed }
}
13年3月11日月曜日
- 32. やってること
• 3行で言うと...
13年3月11日月曜日
- 33. やってること
• 3行で言うと...
• AST変換で
13年3月11日月曜日
- 34. やってること
• 3行で言うと...
• AST変換で
• 条件用のコードを
13年3月11日月曜日
- 35. やってること
• 3行で言うと...
• AST変換で、
• 条件用のコードを、
• コンストラクタとメソッド
に埋め込み
13年3月11日月曜日
- 36. やってること
• 3行で言うと...
• AST変換で、
• 条件用のコードを生成、
• コンストラクタとメソッド
に埋め込み、
• 実行する。
13年3月11日月曜日
- 37. AST変換
• Abstract Syntax Tree変換
• 抽象構文木をこねくりまわ
す
13年3月11日月曜日
- 38. AST変換
• サービスプロバイダ機能を使って、次の
ASTTransformationの実装クラスを指
定。
• org.gcontracts.ast.ClosureExpressionE
valuationASTTransformation
• org.gcontracts.ast.GContractsASTTran
sformation
13年3月11日月曜日
- 40. import org.gcontracts.annotations.*
@org.gcontracts.annotations.Invariant(value = Rocket$_gc_closure1)
@org.gcontracts.annotations.Contracted
public class Rocket extends java.lang.Object {
private int speed
final static boolean $GCONTRACTS_ENABLED
@org.gcontracts.annotations.Requires(value = Rocket
$_gc_closure2)
@org.gcontracts.annotations.Ensures(value = Rocket
$_gc_closure3)
public void accelerate() {
++( speed )
}
public boolean isStarted() {
true
}
public int speed() {
speed
}
}
13年3月11日月曜日
- 41. final public class Rocket$_gc_closure1 extends
groovy.lang.Closure<V extends java.lang.Object> {
// (省略)
public java.lang.Boolean doCall() {
java.lang.Boolean $_gc_closure_result = false
try {
assert this.speed() >= 0 : null
$_gc_closure_result = true
}
catch
(org.codehaus.groovy.runtime.powerassert.PowerAssertionError error)
{
org.gcontracts.ClassInvariantViolation newError = new
org.gcontracts.ClassInvariantViolation('<org.gcontracts.annotations
.Invariant> Rocket nn' + error.getMessage())
newError.setStackTrace(error.getStackTrace())
}
finally {
}
return $_gc_closure_result
}
// (省略)
}
13年3月11日月曜日
- 42. final public class Rocket$_gc_closure2 extends
groovy.lang.Closure<V extends java.lang.Object> {
// (省略)
public java.lang.Boolean doCall() {
java.lang.Boolean $_gc_closure_result = false
try {
assert this.isStarted() : null
$_gc_closure_result = true
}
catch
(org.codehaus.groovy.runtime.powerassert.PowerAssertionError error) {
org.gcontracts.PreconditionViolation newError = new
org.gcontracts.PreconditionViolation('<org.gcontracts.annotations.Req
uires> Rocket.void accelerate() nn' + error.getMessage())
newError.setStackTrace(error.getStackTrace())
}
finally {
}
return $_gc_closure_result
}
// (省略)
}
13年3月11日月曜日
- 43. final public class Rocket$_gc_closure3
extends groovy.lang.Closure<V extends java.lang.Object> {
// (省略)
public java.lang.Boolean doCall(java.util.Map old) {
java.lang.Boolean $_gc_closure_result = false
try {
assert old .speed < speed : null
$_gc_closure_result = true
}
catch
(org.codehaus.groovy.runtime.powerassert.PowerAssertionError error) {
org.gcontracts.PostconditionViolation newError = new
org.gcontracts.PostconditionViolation('<org.gcontracts.annotations.En
sures> Rocket.void accelerate() nn' + error.getMessage())
newError.setStackTrace(error.getStackTrace())
}
finally {
}
return $_gc_closure_result
}
// (省略)
}
13年3月11日月曜日
- 47. if ( $GCONTRACTS_ENABLED ) {
try {
if
(org.gcontracts.generation.ContractExecutionTracker.track('Rocket', 'void
accelerate()', 'precondition', false)) {
java.lang.Boolean $_gc_result = false
org.gcontracts.ViolationTracker.init()
$_gc_result = new Rocket$_gc_closure2(this,
this).doCall()
if (!( $_gc_result ) &&
org.gcontracts.ViolationTracker.violationsOccured()) {
try {
org.gcontracts.ViolationTracker.rethrowFirst()
}
finally {
org.gcontracts.ViolationTracker.deinit()
}
}
}
}
finally {
org.gcontracts.generation.ContractExecutionTracker.clear('Rocket', 'void
accelerate()', 'precondition', false)
}
}
++( speed )
13年3月11日月曜日
- 48. // 事後条件
if ( $GCONTRACTS_ENABLED ) {
if (!( old .speed < speed )) {
try {
assert old .speed < speed : null
}
catch
(org.codehaus.groovy.runtime.powerassert.PowerAssertionError error) {
org.gcontracts.PostconditionViolation newError =
new
org.gcontracts.PostconditionViolation('<org.gcontracts.annotations.En
sures> Rocket.void accelerate() nn' + error.getMessage())
newError.setStackTrace(error.getStackTrace())
throw newError
}
finally {
}
}
}
// 不変条件
this.invariant_Rocket()
}
13年3月11日月曜日
- 49. public boolean isStarted() {
java.lang.Object $_gc_result = true
this.invariant_Rocket()
return $_gc_result
}
public int speed() {
java.lang.Object $_gc_result = speed
this.invariant_Rocket()
return $_gc_result
}
13年3月11日月曜日
- 51. protected void invariant_Rocket() {
if ( $GCONTRACTS_ENABLED ) {
try {
if
(org.gcontracts.generation.ContractExecutionTracker.track('Rocket',
'void invariant_Rocket()', 'invariant', false)) {
java.lang.Boolean $_gc_result = false
org.gcontracts.ViolationTracker.init()
$_gc_result = new Rocket$_gc_closure1(this,
this).doCall()
if (!( $_gc_result ) &&
org.gcontracts.ViolationTracker.violationsOccured()) {
try {
org.gcontracts.ViolationTracker.rethrowFirst()
}
finally {
org.gcontracts.ViolationTracker.deinit()
}
}
}
}
finally {
org.gcontracts.generation.ContractExecutionTracker.clear('Rocket',
13年3月11日月曜日
- 52. $GCONTRACTS_ENABLED
• メソッドの呼び出しごとに条
件が評価されるのは遅い
• $GCONTRACTS_ENABLED
で実行を制御する
• -ea,-daVMパラメータで指定
13年3月11日月曜日
- 53. 3 09, 2013 4:56:21 午後 org.codehaus.groovy.runtime.StackTraceUtils
sanitize
WARNING: Sanitizing stacktrace:
Assertion failed:
assert 1 == 2
|
false
! at
org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.
java:399)
! at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(Script
BytecodeAdapter.java:655)
! at A.process(ConsoleScript30:22)
13年3月11日月曜日
- 54. Exception thrown
3 09, 2013 4:50:36 午後 org.codehaus.groovy.runtime.StackTraceUtils
sanitize
WARNING: Sanitizing stacktrace:
org.gcontracts.PostconditionViolation:
<org.gcontracts.annotations.Ensures> Rocket.void accelerate()
old.speed < speed
| | | |
| 10 | 9
| false
[speed:10]
! at
org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.
java:399)
! at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(Script
BytecodeAdapter.java:655)
! at Rocket.accelerate(ConsoleScript29:8)
13年3月11日月曜日
- 55. 4.まとめ
Add-up
13年3月11日月曜日
- 56. まとめ
• 原本を読んでね。
• 使ってみてね。
13年3月11日月曜日