SlideShare a Scribd company logo
Daniel Prager @agilejitsu agilejitsu.blogspot.com
Melbourne Functional User Group, September 6, 2013
There are two ways of constructing a software design: One way is to make it
so simple that there are obviously no deficiencies, and the other way is to
make it so complicated that there are no obvious deficiencies.
The first method is far more difficult. It demands the same skill, devotion,
insight, and even inspiration as the discovery of the simple physical laws
which underlie the complex phenomena of nature.
– Tony Hoare, in his 1980 Turing Award lecture
Introduction to Contracts and
Functional Contracts
A personal Preamble
● 1998: I discover Design by Contract and start using it
– Time spent debugging: ↓ 90%
– Joy ↑
● I've used variants ever since
– Technical pay-off: 
– Hit rate in persuading colleagues to join in: variable
● In this talk I
– Introduce the basics of Design by Contract
– Show how it can work in combination with functional programming
– Share some hard-won advice
– Ideally chat with you about where DbC sits today in relation to automated testing and static
type-checking
Overview
● The Problem of Software Quality
● Contracts: The basic idea
● Design By Contract (DbC)
● Questions and Concerns
● Functional Contracts
● Comparison with Tests and with Static Type-checking
● Some Hybrid Approaches
● Conclusion
The Problem of Software Quality
● Problem: How to design and program correct,
robust, maintainable, etc., etc. software?
● Assumption: BUGS happen!
● Prevention: Simplicity and clarity of design;
modularity; concision
● Treatment: Rapid isolation and diagnosis of
problems
Contracts: a metaphor
● Commercial Contract
– The client pays a supplier
to provide a good or service
– The contract
●
makes explicit the
expectations on both parties
● specifies who is to blame –
client or supplier – if
something goes wrong.
● Programming Contract
– The calling code (the client) calls a function
(the supplier)
– The contract
● defines explicit pre-conditions on
arguments passed by the calling code (and
on the initial state)
● defines explicit post-conditions on the
result of the function (and the final state)
● specifies which code is to blame – calling
code or function – if something goes wrong.
The standard example in Eiffel
square_root (x: REAL): REAL is
-- Returns the positive square root of x
require
-- Pre-condition section
positive_argument: x >= 0.0
do
-- Implementation section
...
ensure
-- Post-condition section
correct_root: abs(Result * Result – x) <= 0.000001
positive_root: Result >= 0
end
Same example in Racket
with hand-rolled contract
(define (square-root x)
(require (non-negative-real? x) "real, non-negative argument")
(let ([result ...])
(ensure (non-negative-real? result) "real, non-negative result")
(ensure (approx-equal? (* result result) x) "correct root")
result))
(define (require test [message “”])
(unless test (error 'pre-condition-violation message)))
(define (ensure test [message “”])
(unless test (error 'post-condition-violation message)))
(define (non-negative-real? x) (and (real? x) (>= x 0)))
(define (approx-equal? x y [tol 0.000001]) (<= (abs (- x y)) tol))
Quiz: Test your understanding
(define (square-root x)
(require (non-negative-real? x) "real, non-negative argument")
(let ([result (/ x 2)])
(ensure (non-negative-real? result) "real, non-negative result")
(ensure (approx-equal? (* result result) x) "correct root")
result))
● Which errors would the following calls induce?
– (square-root “five”)
– (square-root -8.0)
– (square-root 9)
Quiz answers
● Answers
– (square-root “five”) → pre-condition-violation: real, non-negative argument
– (square-root -8.0) → pre-condition-violation: real, non-negative argument
– (square-root 9) → post-condition-violation: correct root
Square root with hand-rolled
contract and static types
#lang typed/racket
(define: (square-root [x : Nonnegative-Real]) : Nonnegative-Real
(let ([result ...])
(ensure (approx-equal? (* result result) x) "correct root")
result))
(define: (require [test : Boolean] [message : String]) : Symbol
(if test 'ok (error 'pre-condition-violation message)))
(define: (ensure [test : Boolean] [message : String]) : Symbol
(if test 'ok (error 'post-condition-violation message)))
(define: (approx-equal? [x : Real] [y : Real]) : Boolean
(<= (abs (- x y)) 0.000001))
Design by Contract
● Design By Contract (DbC) is the discipline of writing out the contracts before
implementation.
– Steps of Design By Contract:
1)Declare a function and write-down its contract
2)Write an implementation
3)Manually test and fix any breakages
4)Refactor the contract and the code for concision and precision
5)Rinse, repeat.
– The mechanics are similar to Test-Driven Design/Development (TDD):
1)Write a failing test
2)Make it pass
3)Refactor to remove duplication, etc.
4)Rinse, repeat.
●
Let's DbC together!
● Scenario: Insert a string into another string
– Signature: (define (string-insert str other-str pos) …)
– Usage:
● (string-insert "stuff" "FOO" 0) → "FOOstuff"
● (string-insert "stuff" "FOO" 3) → "stuFOOff"
● (string-insert "stuff" "FOO" 5) → “stuffFOO”
● Challenge:
– Write down as many pre-conditions as you can
– Write down some post-conditions [usually harder]
Design by Contract: a solution
(define (string-insert str other-str pos)
(require (string? str) "str is a string")
(require (string? other-str) "other-str is a string")
(require (integer? pos) "pos is an integer")
(require (<= 0 pos (string-length str)) "0 <= pos <= length(str)")
(let ([result ...]
[other-len (string-length other-str)])
(ensure (string? result))
(ensure (= (string-length result) (+ (string-length str) other-len))
"len(result) = len(str) + len(other-str)")
(ensure (string=? (substring result pos (+ pos other-len)) other-str)
"other-str is spliced into the correct spot")
result))
DbC: a solution with static types
#lang typed/racket
(define: (string-insert [str : String] [other-str : String] [pos : Natural]) : String
(require (<= pos (string-length str)) "pos <= length(str)")
(let ([result ...]
[other-len (string-length other-str)])
(ensure (= (string-length result) (+ (string-length str) other-len))
“len(result) = len(str) + len(other-str)")
(ensure (string=? (substring result pos (+ pos other-len)) other-str)
"other-str is spliced into the correct spot")
result))
How are we doing so far?
● Questions and Concerns?
How are we doing so far?
● Questions and Concerns
– What if I make a mistake in specifying the contract?
– Do contracts slow down execution speed?
– Do I need to fully specify every contract?
– Can I use contracts with language X?
– Do contracts replace documentation?
– What about state?
– What about object-oriented programming?
– What about functional programming?
Questions and Concerns
● What if I make a mistake in specifying the contract?
● This happens, occasionally.
● Running the program with contracts in place checks
consistency between contracts and code, not absolute
correctness.
● Usually the contracts are simpler than the code, so most of the
time the problem is in the client or supplier code.
● Advice:
– Try to keep your contracts clear and concise
– If the problem is unclear, review the contract
Questions and Concerns
● Do contracts slow down execution speed?
– Yes, but …
● Pre-conditions are usually very cheap to test
● Complex post-conditions (and especially invariants) can be expensive
● Advice:
– Make the level of checking configurable.
– Turn everything on in testing; turn painfully slow checks off selectively
– Leave pre-condition checking on in production, augmented by recovery strategies
● Do I need to fully specify every contract?
– No, but …
● High contract coverage helps with design, defect-detection, and overall effectiveness
● Advice:
– Specify pre-conditions fully
– Keep post-conditions simple initially; jot down complex ones as comments and implement as needed
Questions and Concerns
● Can I use contracts with language X?
– Almost certainly, Yes
– You can usually roll your own support using asserts,
exceptions, or even pop-ups.
– Many languages have built-in support or libraries:
● Eiffel, Racket, Clojure, D, .NET languages (via Code
Contracts add-on), etc.
Questions and Concerns
● Do contracts replace documentation?
– Partly. Contracts can help reduce the documentation
burden and help keep technical documentation up-to-
dated.
– Ideally, language support should include a tool for
summarizing source code, by
● omitting implementation details
● retaining signatures, doc-strings and contracts
● formatting the output appropriately, and adding hyperlinks
Questions and Concerns
● What about state?
– State adds a bit of complexity, but Contracts can cope.
– Pre-conditions can check initial state (as well as arguments):
● E.g. A pre-condition on a routine that reads a token from a file should
check that the file is open and that the end hasn't been reached.
– Post-conditions can check final state (as well as the result)
● E.g. A setter can check that the desired effect has occurred.
– Advice:
● Favour pure functions over ones with side-effects
● Favour immutable data structures
Questions and Concerns
● What about object-oriented programming?
– OO design and programming with contracts is a major
focus of the Eiffel language, but not the focus of this talk.
– Besides object state, OO-progamming with contracts
involves invariant checking, and support for inheritance
when methods are redefined in sub-types.
– Advice:
● Read up on it elsewhere, e.g.
– Bertrand Meyer's Object-oriented Software Construction, 2nd ed.
Questions and Concerns
● What about functional programming?
– That's the focus of the next part of this presentation!
– The material so far applied equally to both the imperative
and functional paradigms.
– Now we switch to some more functional aspects
● Out-of-the-box support in Racket for contracts
● Higher-order functions and contracts
● Checking contracts at module boundaries
Square root reprised, using
Racket's contract combinators
; The simple (-> domain range) contract combinator is concise,
; but limited:
;
(define/contract (real-sqrt-1 x)
(-> non-negative-real? non-negative-real?)
...)
; The “indy” (->i ...) contract combinator gives names to the
; argument(s) and to the result: greater richness, less concision
;
(define/contract (real-sqrt x)
(->i ([x non-negative-real?])
(r non-negative-real?)
#:post (r x) (approx-equal? (* r r) x))
...)
Contract combinators provide richer
error messages
● Hand-rolled:
– (square-root 'foo)
● Combinator:
– (real-sqrt 'foo)
pre-condition-violation: real,
non-negative argument
real-sqrt: contract violation
expected: non-negative-real?
given: 'foo
in: the x argument of
(->i
((x non-negative-real?))
(r non-negative-real?)
#:post
(r x)
...)
contract from: .../contracts.rkt
Blaming: .../contracts.rkt
At: .../contracts.rkt: [line/col of the contract]
Higher-order functions and
Contracts
● Higher-order functions can't be checked
immediately for conformance to a predicate. E.g.
(define/contract (make-indenter n)
(->i ([n natural-number/c])
[r (n) (->i ([s string?])
[result string?]
#:post (s result) (= (string-length result)
(+ n (string-length s))))])
(λ (s) (string-append (make-string n #space) s)))
Usage: ((make-indenter 4) “foo”) → “ foo”
Higher order functions and Contracts
● Racket wraps the higher-order functions in a guard and
checks what's passed in and returned at the time of
function application.
● Failures are deciphered in the error message. E.g.
((make-indenter 4) 'foo) → make-indenter: contract violation
expected: string?
given: 'foo
in: the s argument of
the r result of
(->i ((n natural-number/c)) (r (n) ...))
Attaching contracts at module
boundaries
● Traditionally, contracts are enforced at function
boundaries, but other choices are possible.
● In Racket, contracts are commonly wrapped around
existing functions (and data) when they are
exported from modules.
● Contract checking only occurs across module
boundaries, useful e.g. in highly recursive
scenarios.
Example of adding contracts at the
module level
(module parity racket
(provide (contract-out
[odd? (-> integer? boolean?)]
[even? (-> integer? boolean?)]))
(define (odd? n)
(cond [(zero? n) #f]
[(negative? n) (odd? (- n))]
[else (even? (sub1 n))]))
(define (even? n)
(if (zero? n)
#t
(odd? (sub1 n)))))
Additional facilities in Racket
● Racket includes many more features for working
with contracts, including:
– Support for variable-arity and keyword arguments
– Contracts on structures
– Additional contract combinators
● See the Racket docs for details
Interlude: What do you do now?
● Questions for fans of automated tests:
– TDD? BDD? CI?
– What do you like about automated tests?
– Pains?
● Questions for fans of static typing:
– How sophisticated is your type-system?
– Is anyone using dependent types?
– Is anyone automatically generating tests from types?
– Likes? Pains?
● Any other approaches?
Automated Tests smackdown
● Positives of tests
– Popular
– Concrete and relatively
easy to understand
– Automated tests exercise
the code
– No performance impact on
production code
– TDD encourages good
design
● Negatives of tests:
– Requires discipline
– Tests don't apportion precise
blame (although TDD / rolling
back can help isolate issues)
– Not helpful in production
– A big test suite can be time-
consuming to run and take a
lot of work to maintain
Static Type-Checking smackdown
● Positives
– Type checks are at compile
time: early feedback
– Faster execution
– Simplifies contracts
– Enforces discipline
● Limitation
– You can't check everything
statically: Rice's theorem
● Negatives
– Demands discipline
– Can break programmer flow
– Can result in lots of boilerplate (Java,
C#, etc.)
– Large systems can be slow to compile
– Simpler type systems can be unduly
restrictive and inflexible
– Languages with superior type systems
are fairly challenging to learn (Haskell
is hard)
– Language / tool support is essential
Contracts smackdown
● Positives
– Assigns blame accurately
– Crushes debugging time
– Simplifies code and tests
– Can express elaborate checks
– Simplifies documentation
– Helps clarify design and
improve modularity
– Most of the benefit can be
achieved without out-of-the-
box language support
● Negatives
– Demands discipline
– Demands skill
– Not widely known or used
– Can slow down
performance, e.g. by
inflating algorithmic
complexity if you're not
careful
Hybrid Approach #1
● Contracts + Static Type-Checking
– Maximum concision
– This was the original mix designed into Eiffel
– Challenges?
● High-ish discipline factor
● No out-of-the-box contracts yet in Typed Racket
● For functional programming, rolling your own
higher-order contract support is non-trivial.
Hybrid Approach #2
● Tests + Contracts:
– Option 1:
● use explicit pre-conditions
● don't use explicit post-conditions; use tests instead
– Option 2 (my favourite):
● use scenario tests to exercise code and drive Continuous Integration
● Use pre-conditions and post-conditions instead of unit tests
– Option 3:
● automatically generate random unit tests from contracts
●
Hybrid Approach #3
● Tests + Contracts + Types:
● Worthwhile once you're comfortable with all three, especially
for large and complex software
● Challenges
– High discipline approach
– Difficult to get everyone in a team on board
Conclusion
● If you consistently write automated tests, you have the
necessary self-discipline to try contracts.
● If you are a fan of static type-checking, you can approach
contracts as a logical, dynamic extension.
● Using contracts consistently should
– greatly reduce the time you spend debugging
– make your code, tests, and documentation more concise and
readable
– clarify and simplify your design choices
– change the way you think!
Acknowledgements: Thanks to Matthias Felleisen, Greg Hendershott, Robby
Findler and Russell Sim, respectively for helpful critique and suggestions,
encouragement, a just-in-time correction, and for suggesting I give a talk.

More Related Content

What's hot

WUD 2019 — UX Maturity Levels and You (Darren Hood)
WUD 2019 — UX Maturity Levels and You (Darren Hood)WUD 2019 — UX Maturity Levels and You (Darren Hood)
WUD 2019 — UX Maturity Levels and You (Darren Hood)
Darren Hood, MSUXD
 
Figma Prototype A to Z.pdf
Figma Prototype A to Z.pdfFigma Prototype A to Z.pdf
Figma Prototype A to Z.pdf
Atiqur Rahaman
 
The Scrum Model
The Scrum ModelThe Scrum Model
The Scrum Model
Damian T. Gordon
 
Incremental model
Incremental model Incremental model
Incremental model
Radadiya Nayan
 
Agile software process
Agile software processAgile software process
Agile software process
Jennifer Polack
 
Kanban Basics
Kanban BasicsKanban Basics
Kanban Basics
Pawel Brodzinski
 
Vertical Story Slicing Takes the Cake!
Vertical Story Slicing Takes the Cake!Vertical Story Slicing Takes the Cake!
Vertical Story Slicing Takes the Cake!
kporemski
 
XP Explained
XP ExplainedXP Explained
XP Explained
vineet
 
Automation for JIRA - The Simplest Way to Automate Your Team and Project
Automation for JIRA - The Simplest Way to Automate Your Team and ProjectAutomation for JIRA - The Simplest Way to Automate Your Team and Project
Automation for JIRA - The Simplest Way to Automate Your Team and Project
Bosnia Agile
 
Prototyping tools
Prototyping toolsPrototyping tools
Prototyping tools
Joël Plas
 
Heuristics — The Holy Grail of UX
Heuristics — The Holy Grail of UXHeuristics — The Holy Grail of UX
Heuristics — The Holy Grail of UX
Darren Hood, MSUXD
 
Agile Methodology ppt
Agile Methodology pptAgile Methodology ppt
Scrum and Agile SDLC 101
Scrum and Agile SDLC 101Scrum and Agile SDLC 101
Scrum and Agile SDLC 101
Aniruddha Ray (Ani)
 
Agile & SCRUM basics
Agile & SCRUM basicsAgile & SCRUM basics
Agile & SCRUM basics
Arun R
 
Prototyping
PrototypingPrototyping
Prototyping
Matt Hurley
 
Waterfall vs Agile : A Beginner's Guide in Project Management
Waterfall vs Agile : A Beginner's Guide in Project ManagementWaterfall vs Agile : A Beginner's Guide in Project Management
Waterfall vs Agile : A Beginner's Guide in Project Management
Jonathan Donado
 
Figma design tool - an alternative for windows users
Figma design tool - an alternative for windows usersFigma design tool - an alternative for windows users
Figma design tool - an alternative for windows users
Augustina Reipšlėger
 
Ux design process
Ux design processUx design process
Ux design process
Junying Chang
 
Clean Code summary
Clean Code summaryClean Code summary
Clean Code summary
Jan de Vries
 

What's hot (20)

WUD 2019 — UX Maturity Levels and You (Darren Hood)
WUD 2019 — UX Maturity Levels and You (Darren Hood)WUD 2019 — UX Maturity Levels and You (Darren Hood)
WUD 2019 — UX Maturity Levels and You (Darren Hood)
 
Figma Prototype A to Z.pdf
Figma Prototype A to Z.pdfFigma Prototype A to Z.pdf
Figma Prototype A to Z.pdf
 
The Scrum Model
The Scrum ModelThe Scrum Model
The Scrum Model
 
Incremental model
Incremental model Incremental model
Incremental model
 
Agile software process
Agile software processAgile software process
Agile software process
 
Kanban Basics
Kanban BasicsKanban Basics
Kanban Basics
 
Vertical Story Slicing Takes the Cake!
Vertical Story Slicing Takes the Cake!Vertical Story Slicing Takes the Cake!
Vertical Story Slicing Takes the Cake!
 
XP Explained
XP ExplainedXP Explained
XP Explained
 
Automation for JIRA - The Simplest Way to Automate Your Team and Project
Automation for JIRA - The Simplest Way to Automate Your Team and ProjectAutomation for JIRA - The Simplest Way to Automate Your Team and Project
Automation for JIRA - The Simplest Way to Automate Your Team and Project
 
Prototyping tools
Prototyping toolsPrototyping tools
Prototyping tools
 
Heuristics — The Holy Grail of UX
Heuristics — The Holy Grail of UXHeuristics — The Holy Grail of UX
Heuristics — The Holy Grail of UX
 
Agile Methodology ppt
Agile Methodology pptAgile Methodology ppt
Agile Methodology ppt
 
Scrum and Agile SDLC 101
Scrum and Agile SDLC 101Scrum and Agile SDLC 101
Scrum and Agile SDLC 101
 
Prototyping model
Prototyping modelPrototyping model
Prototyping model
 
Agile & SCRUM basics
Agile & SCRUM basicsAgile & SCRUM basics
Agile & SCRUM basics
 
Prototyping
PrototypingPrototyping
Prototyping
 
Waterfall vs Agile : A Beginner's Guide in Project Management
Waterfall vs Agile : A Beginner's Guide in Project ManagementWaterfall vs Agile : A Beginner's Guide in Project Management
Waterfall vs Agile : A Beginner's Guide in Project Management
 
Figma design tool - an alternative for windows users
Figma design tool - an alternative for windows usersFigma design tool - an alternative for windows users
Figma design tool - an alternative for windows users
 
Ux design process
Ux design processUx design process
Ux design process
 
Clean Code summary
Clean Code summaryClean Code summary
Clean Code summary
 

Similar to Introduction to Contracts and Functional Contracts

Indy meetup#7 effective unit-testing-mule
Indy meetup#7 effective unit-testing-muleIndy meetup#7 effective unit-testing-mule
Indy meetup#7 effective unit-testing-mule
ikram_ahamed
 
Contracts in Ruby - Vladyslav Hesal
Contracts in Ruby - Vladyslav HesalContracts in Ruby - Vladyslav Hesal
Contracts in Ruby - Vladyslav Hesal
Ruby Meditation
 
From class to architecture
From class to architectureFrom class to architecture
From class to architecture
Marcin Hawraniak
 
Sorted
SortedSorted
Improving Code Quality Through Effective Review Process
Improving Code Quality Through Effective  Review ProcessImproving Code Quality Through Effective  Review Process
Improving Code Quality Through Effective Review Process
Dr. Syed Hassan Amin
 
Tdd in practice
Tdd in practiceTdd in practice
Tdd in practice
Andrew Meredith
 
When to Code / Config / Config + Code in Salesforce - Nikunj Doshi
When to Code / Config / Config + Code in Salesforce - Nikunj DoshiWhen to Code / Config / Config + Code in Salesforce - Nikunj Doshi
When to Code / Config / Config + Code in Salesforce - Nikunj Doshi
Sakthivel Madesh
 
The working architecture of node js applications open tech week javascript ...
The working architecture of node js applications   open tech week javascript ...The working architecture of node js applications   open tech week javascript ...
The working architecture of node js applications open tech week javascript ...
Viktor Turskyi
 
The working architecture of NodeJS applications, Виктор Турский
The working architecture of NodeJS applications, Виктор ТурскийThe working architecture of NodeJS applications, Виктор Турский
The working architecture of NodeJS applications, Виктор Турский
Sigma Software
 
Keeping code clean
Keeping code cleanKeeping code clean
Keeping code clean
Brett Child
 
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
Chris Laning
 
Software Craftmanship - Cours Polytech
Software Craftmanship - Cours PolytechSoftware Craftmanship - Cours Polytech
Software Craftmanship - Cours Polytech
yannick grenzinger
 
Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"
Fwdays
 
Domain driven design: a gentle introduction
Domain driven design:  a gentle introductionDomain driven design:  a gentle introduction
Domain driven design: a gentle introduction
Asher Sterkin
 
Acceptance tests
Acceptance testsAcceptance tests
Acceptance tests
Dragan Tomic
 
Technical debt management strategies
Technical debt management strategiesTechnical debt management strategies
Technical debt management strategies
Raquel Pau
 
Software Engineering Primer
Software Engineering PrimerSoftware Engineering Primer
Software Engineering Primer
Georg Buske
 
CHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docx
CHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docxCHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docx
CHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docx
walterl4
 
Agile Methodologies And Extreme Programming
Agile Methodologies And Extreme ProgrammingAgile Methodologies And Extreme Programming
Agile Methodologies And Extreme Programming
Utkarsh Khare
 
BDD presentation
BDD presentationBDD presentation
BDD presentation
temebele
 

Similar to Introduction to Contracts and Functional Contracts (20)

Indy meetup#7 effective unit-testing-mule
Indy meetup#7 effective unit-testing-muleIndy meetup#7 effective unit-testing-mule
Indy meetup#7 effective unit-testing-mule
 
Contracts in Ruby - Vladyslav Hesal
Contracts in Ruby - Vladyslav HesalContracts in Ruby - Vladyslav Hesal
Contracts in Ruby - Vladyslav Hesal
 
From class to architecture
From class to architectureFrom class to architecture
From class to architecture
 
Sorted
SortedSorted
Sorted
 
Improving Code Quality Through Effective Review Process
Improving Code Quality Through Effective  Review ProcessImproving Code Quality Through Effective  Review Process
Improving Code Quality Through Effective Review Process
 
Tdd in practice
Tdd in practiceTdd in practice
Tdd in practice
 
When to Code / Config / Config + Code in Salesforce - Nikunj Doshi
When to Code / Config / Config + Code in Salesforce - Nikunj DoshiWhen to Code / Config / Config + Code in Salesforce - Nikunj Doshi
When to Code / Config / Config + Code in Salesforce - Nikunj Doshi
 
The working architecture of node js applications open tech week javascript ...
The working architecture of node js applications   open tech week javascript ...The working architecture of node js applications   open tech week javascript ...
The working architecture of node js applications open tech week javascript ...
 
The working architecture of NodeJS applications, Виктор Турский
The working architecture of NodeJS applications, Виктор ТурскийThe working architecture of NodeJS applications, Виктор Турский
The working architecture of NodeJS applications, Виктор Турский
 
Keeping code clean
Keeping code cleanKeeping code clean
Keeping code clean
 
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
 
Software Craftmanship - Cours Polytech
Software Craftmanship - Cours PolytechSoftware Craftmanship - Cours Polytech
Software Craftmanship - Cours Polytech
 
Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"
 
Domain driven design: a gentle introduction
Domain driven design:  a gentle introductionDomain driven design:  a gentle introduction
Domain driven design: a gentle introduction
 
Acceptance tests
Acceptance testsAcceptance tests
Acceptance tests
 
Technical debt management strategies
Technical debt management strategiesTechnical debt management strategies
Technical debt management strategies
 
Software Engineering Primer
Software Engineering PrimerSoftware Engineering Primer
Software Engineering Primer
 
CHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docx
CHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docxCHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docx
CHAPTER 1 Creating a ProgramOBJECTIVES· Analyze some of the i.docx
 
Agile Methodologies And Extreme Programming
Agile Methodologies And Extreme ProgrammingAgile Methodologies And Extreme Programming
Agile Methodologies And Extreme Programming
 
BDD presentation
BDD presentationBDD presentation
BDD presentation
 

Recently uploaded

Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Zilliz
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 

Recently uploaded (20)

Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 

Introduction to Contracts and Functional Contracts

  • 1. Daniel Prager @agilejitsu agilejitsu.blogspot.com Melbourne Functional User Group, September 6, 2013 There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult. It demands the same skill, devotion, insight, and even inspiration as the discovery of the simple physical laws which underlie the complex phenomena of nature. – Tony Hoare, in his 1980 Turing Award lecture Introduction to Contracts and Functional Contracts
  • 2. A personal Preamble ● 1998: I discover Design by Contract and start using it – Time spent debugging: ↓ 90% – Joy ↑ ● I've used variants ever since – Technical pay-off:  – Hit rate in persuading colleagues to join in: variable ● In this talk I – Introduce the basics of Design by Contract – Show how it can work in combination with functional programming – Share some hard-won advice – Ideally chat with you about where DbC sits today in relation to automated testing and static type-checking
  • 3. Overview ● The Problem of Software Quality ● Contracts: The basic idea ● Design By Contract (DbC) ● Questions and Concerns ● Functional Contracts ● Comparison with Tests and with Static Type-checking ● Some Hybrid Approaches ● Conclusion
  • 4. The Problem of Software Quality ● Problem: How to design and program correct, robust, maintainable, etc., etc. software? ● Assumption: BUGS happen! ● Prevention: Simplicity and clarity of design; modularity; concision ● Treatment: Rapid isolation and diagnosis of problems
  • 5. Contracts: a metaphor ● Commercial Contract – The client pays a supplier to provide a good or service – The contract ● makes explicit the expectations on both parties ● specifies who is to blame – client or supplier – if something goes wrong. ● Programming Contract – The calling code (the client) calls a function (the supplier) – The contract ● defines explicit pre-conditions on arguments passed by the calling code (and on the initial state) ● defines explicit post-conditions on the result of the function (and the final state) ● specifies which code is to blame – calling code or function – if something goes wrong.
  • 6. The standard example in Eiffel square_root (x: REAL): REAL is -- Returns the positive square root of x require -- Pre-condition section positive_argument: x >= 0.0 do -- Implementation section ... ensure -- Post-condition section correct_root: abs(Result * Result – x) <= 0.000001 positive_root: Result >= 0 end
  • 7. Same example in Racket with hand-rolled contract (define (square-root x) (require (non-negative-real? x) "real, non-negative argument") (let ([result ...]) (ensure (non-negative-real? result) "real, non-negative result") (ensure (approx-equal? (* result result) x) "correct root") result)) (define (require test [message “”]) (unless test (error 'pre-condition-violation message))) (define (ensure test [message “”]) (unless test (error 'post-condition-violation message))) (define (non-negative-real? x) (and (real? x) (>= x 0))) (define (approx-equal? x y [tol 0.000001]) (<= (abs (- x y)) tol))
  • 8. Quiz: Test your understanding (define (square-root x) (require (non-negative-real? x) "real, non-negative argument") (let ([result (/ x 2)]) (ensure (non-negative-real? result) "real, non-negative result") (ensure (approx-equal? (* result result) x) "correct root") result)) ● Which errors would the following calls induce? – (square-root “five”) – (square-root -8.0) – (square-root 9)
  • 9. Quiz answers ● Answers – (square-root “five”) → pre-condition-violation: real, non-negative argument – (square-root -8.0) → pre-condition-violation: real, non-negative argument – (square-root 9) → post-condition-violation: correct root
  • 10. Square root with hand-rolled contract and static types #lang typed/racket (define: (square-root [x : Nonnegative-Real]) : Nonnegative-Real (let ([result ...]) (ensure (approx-equal? (* result result) x) "correct root") result)) (define: (require [test : Boolean] [message : String]) : Symbol (if test 'ok (error 'pre-condition-violation message))) (define: (ensure [test : Boolean] [message : String]) : Symbol (if test 'ok (error 'post-condition-violation message))) (define: (approx-equal? [x : Real] [y : Real]) : Boolean (<= (abs (- x y)) 0.000001))
  • 11. Design by Contract ● Design By Contract (DbC) is the discipline of writing out the contracts before implementation. – Steps of Design By Contract: 1)Declare a function and write-down its contract 2)Write an implementation 3)Manually test and fix any breakages 4)Refactor the contract and the code for concision and precision 5)Rinse, repeat. – The mechanics are similar to Test-Driven Design/Development (TDD): 1)Write a failing test 2)Make it pass 3)Refactor to remove duplication, etc. 4)Rinse, repeat. ●
  • 12. Let's DbC together! ● Scenario: Insert a string into another string – Signature: (define (string-insert str other-str pos) …) – Usage: ● (string-insert "stuff" "FOO" 0) → "FOOstuff" ● (string-insert "stuff" "FOO" 3) → "stuFOOff" ● (string-insert "stuff" "FOO" 5) → “stuffFOO” ● Challenge: – Write down as many pre-conditions as you can – Write down some post-conditions [usually harder]
  • 13. Design by Contract: a solution (define (string-insert str other-str pos) (require (string? str) "str is a string") (require (string? other-str) "other-str is a string") (require (integer? pos) "pos is an integer") (require (<= 0 pos (string-length str)) "0 <= pos <= length(str)") (let ([result ...] [other-len (string-length other-str)]) (ensure (string? result)) (ensure (= (string-length result) (+ (string-length str) other-len)) "len(result) = len(str) + len(other-str)") (ensure (string=? (substring result pos (+ pos other-len)) other-str) "other-str is spliced into the correct spot") result))
  • 14. DbC: a solution with static types #lang typed/racket (define: (string-insert [str : String] [other-str : String] [pos : Natural]) : String (require (<= pos (string-length str)) "pos <= length(str)") (let ([result ...] [other-len (string-length other-str)]) (ensure (= (string-length result) (+ (string-length str) other-len)) “len(result) = len(str) + len(other-str)") (ensure (string=? (substring result pos (+ pos other-len)) other-str) "other-str is spliced into the correct spot") result))
  • 15. How are we doing so far? ● Questions and Concerns?
  • 16. How are we doing so far? ● Questions and Concerns – What if I make a mistake in specifying the contract? – Do contracts slow down execution speed? – Do I need to fully specify every contract? – Can I use contracts with language X? – Do contracts replace documentation? – What about state? – What about object-oriented programming? – What about functional programming?
  • 17. Questions and Concerns ● What if I make a mistake in specifying the contract? ● This happens, occasionally. ● Running the program with contracts in place checks consistency between contracts and code, not absolute correctness. ● Usually the contracts are simpler than the code, so most of the time the problem is in the client or supplier code. ● Advice: – Try to keep your contracts clear and concise – If the problem is unclear, review the contract
  • 18. Questions and Concerns ● Do contracts slow down execution speed? – Yes, but … ● Pre-conditions are usually very cheap to test ● Complex post-conditions (and especially invariants) can be expensive ● Advice: – Make the level of checking configurable. – Turn everything on in testing; turn painfully slow checks off selectively – Leave pre-condition checking on in production, augmented by recovery strategies ● Do I need to fully specify every contract? – No, but … ● High contract coverage helps with design, defect-detection, and overall effectiveness ● Advice: – Specify pre-conditions fully – Keep post-conditions simple initially; jot down complex ones as comments and implement as needed
  • 19. Questions and Concerns ● Can I use contracts with language X? – Almost certainly, Yes – You can usually roll your own support using asserts, exceptions, or even pop-ups. – Many languages have built-in support or libraries: ● Eiffel, Racket, Clojure, D, .NET languages (via Code Contracts add-on), etc.
  • 20. Questions and Concerns ● Do contracts replace documentation? – Partly. Contracts can help reduce the documentation burden and help keep technical documentation up-to- dated. – Ideally, language support should include a tool for summarizing source code, by ● omitting implementation details ● retaining signatures, doc-strings and contracts ● formatting the output appropriately, and adding hyperlinks
  • 21. Questions and Concerns ● What about state? – State adds a bit of complexity, but Contracts can cope. – Pre-conditions can check initial state (as well as arguments): ● E.g. A pre-condition on a routine that reads a token from a file should check that the file is open and that the end hasn't been reached. – Post-conditions can check final state (as well as the result) ● E.g. A setter can check that the desired effect has occurred. – Advice: ● Favour pure functions over ones with side-effects ● Favour immutable data structures
  • 22. Questions and Concerns ● What about object-oriented programming? – OO design and programming with contracts is a major focus of the Eiffel language, but not the focus of this talk. – Besides object state, OO-progamming with contracts involves invariant checking, and support for inheritance when methods are redefined in sub-types. – Advice: ● Read up on it elsewhere, e.g. – Bertrand Meyer's Object-oriented Software Construction, 2nd ed.
  • 23. Questions and Concerns ● What about functional programming? – That's the focus of the next part of this presentation! – The material so far applied equally to both the imperative and functional paradigms. – Now we switch to some more functional aspects ● Out-of-the-box support in Racket for contracts ● Higher-order functions and contracts ● Checking contracts at module boundaries
  • 24. Square root reprised, using Racket's contract combinators ; The simple (-> domain range) contract combinator is concise, ; but limited: ; (define/contract (real-sqrt-1 x) (-> non-negative-real? non-negative-real?) ...) ; The “indy” (->i ...) contract combinator gives names to the ; argument(s) and to the result: greater richness, less concision ; (define/contract (real-sqrt x) (->i ([x non-negative-real?]) (r non-negative-real?) #:post (r x) (approx-equal? (* r r) x)) ...)
  • 25. Contract combinators provide richer error messages ● Hand-rolled: – (square-root 'foo) ● Combinator: – (real-sqrt 'foo) pre-condition-violation: real, non-negative argument real-sqrt: contract violation expected: non-negative-real? given: 'foo in: the x argument of (->i ((x non-negative-real?)) (r non-negative-real?) #:post (r x) ...) contract from: .../contracts.rkt Blaming: .../contracts.rkt At: .../contracts.rkt: [line/col of the contract]
  • 26. Higher-order functions and Contracts ● Higher-order functions can't be checked immediately for conformance to a predicate. E.g. (define/contract (make-indenter n) (->i ([n natural-number/c]) [r (n) (->i ([s string?]) [result string?] #:post (s result) (= (string-length result) (+ n (string-length s))))]) (λ (s) (string-append (make-string n #space) s))) Usage: ((make-indenter 4) “foo”) → “ foo”
  • 27. Higher order functions and Contracts ● Racket wraps the higher-order functions in a guard and checks what's passed in and returned at the time of function application. ● Failures are deciphered in the error message. E.g. ((make-indenter 4) 'foo) → make-indenter: contract violation expected: string? given: 'foo in: the s argument of the r result of (->i ((n natural-number/c)) (r (n) ...))
  • 28. Attaching contracts at module boundaries ● Traditionally, contracts are enforced at function boundaries, but other choices are possible. ● In Racket, contracts are commonly wrapped around existing functions (and data) when they are exported from modules. ● Contract checking only occurs across module boundaries, useful e.g. in highly recursive scenarios.
  • 29. Example of adding contracts at the module level (module parity racket (provide (contract-out [odd? (-> integer? boolean?)] [even? (-> integer? boolean?)])) (define (odd? n) (cond [(zero? n) #f] [(negative? n) (odd? (- n))] [else (even? (sub1 n))])) (define (even? n) (if (zero? n) #t (odd? (sub1 n)))))
  • 30. Additional facilities in Racket ● Racket includes many more features for working with contracts, including: – Support for variable-arity and keyword arguments – Contracts on structures – Additional contract combinators ● See the Racket docs for details
  • 31. Interlude: What do you do now? ● Questions for fans of automated tests: – TDD? BDD? CI? – What do you like about automated tests? – Pains? ● Questions for fans of static typing: – How sophisticated is your type-system? – Is anyone using dependent types? – Is anyone automatically generating tests from types? – Likes? Pains? ● Any other approaches?
  • 32. Automated Tests smackdown ● Positives of tests – Popular – Concrete and relatively easy to understand – Automated tests exercise the code – No performance impact on production code – TDD encourages good design ● Negatives of tests: – Requires discipline – Tests don't apportion precise blame (although TDD / rolling back can help isolate issues) – Not helpful in production – A big test suite can be time- consuming to run and take a lot of work to maintain
  • 33. Static Type-Checking smackdown ● Positives – Type checks are at compile time: early feedback – Faster execution – Simplifies contracts – Enforces discipline ● Limitation – You can't check everything statically: Rice's theorem ● Negatives – Demands discipline – Can break programmer flow – Can result in lots of boilerplate (Java, C#, etc.) – Large systems can be slow to compile – Simpler type systems can be unduly restrictive and inflexible – Languages with superior type systems are fairly challenging to learn (Haskell is hard) – Language / tool support is essential
  • 34. Contracts smackdown ● Positives – Assigns blame accurately – Crushes debugging time – Simplifies code and tests – Can express elaborate checks – Simplifies documentation – Helps clarify design and improve modularity – Most of the benefit can be achieved without out-of-the- box language support ● Negatives – Demands discipline – Demands skill – Not widely known or used – Can slow down performance, e.g. by inflating algorithmic complexity if you're not careful
  • 35. Hybrid Approach #1 ● Contracts + Static Type-Checking – Maximum concision – This was the original mix designed into Eiffel – Challenges? ● High-ish discipline factor ● No out-of-the-box contracts yet in Typed Racket ● For functional programming, rolling your own higher-order contract support is non-trivial.
  • 36. Hybrid Approach #2 ● Tests + Contracts: – Option 1: ● use explicit pre-conditions ● don't use explicit post-conditions; use tests instead – Option 2 (my favourite): ● use scenario tests to exercise code and drive Continuous Integration ● Use pre-conditions and post-conditions instead of unit tests – Option 3: ● automatically generate random unit tests from contracts ●
  • 37. Hybrid Approach #3 ● Tests + Contracts + Types: ● Worthwhile once you're comfortable with all three, especially for large and complex software ● Challenges – High discipline approach – Difficult to get everyone in a team on board
  • 38. Conclusion ● If you consistently write automated tests, you have the necessary self-discipline to try contracts. ● If you are a fan of static type-checking, you can approach contracts as a logical, dynamic extension. ● Using contracts consistently should – greatly reduce the time you spend debugging – make your code, tests, and documentation more concise and readable – clarify and simplify your design choices – change the way you think! Acknowledgements: Thanks to Matthias Felleisen, Greg Hendershott, Robby Findler and Russell Sim, respectively for helpful critique and suggestions, encouragement, a just-in-time correction, and for suggesting I give a talk.

Editor's Notes

  1. I first learned about Design by Contract in 1998 and started using it on a major commercial project that I was designing and implementing in Visual Basic 6 (ugh!). To my joy, the time I spent debugging dropped by 90%. Since then I&apos;ve experimented with several variants of programming with Contracts in a wide variety of domains and using diverse languages: Eiffel, VB.NET, C#, Python, ActionScript, and – most recently – Racket. The technical pay-off has always been very good, but my ability to persuade colleagues to try this approach has varied from point-blank refusal to reasonable uptake. Since then, the only thing that has had a comparable impact on my approach to software design and quality has been learning and then applying functional programming concepts (starting with SICP). To my mind, both Design by Contract and functional programming have an almost mathematical cleanliness, and indeed the two can be applied together in some interesting ways. With this talk I&apos;d like to introduce you to the basics , share some of what I&apos;ve learned, and perhaps discuss with you where Design by Contract sits nowadays as a pragmatic approach to Quality in a landscape also populated by TDD and increasingly advanced type systems.
  2. In the first two cases, the blame lies with the client – the calling code Notice that the reasons are intermingled; separate require statements could fix this, but it&apos;s a trade-off between concision and precision In the last case the blame lies with the supplier – the implementation code In all cases the stack trace helps locate the problem We could improve the error messages, by including dynamic information about the nature of the violation, and refining the wording, or make use of out-of-the-box or 3 rd party facilities.
  3. Checking types, then numerical relationships, then data is a common pattern You do not have to fully check the result in the post-condition E.g. The final ensure clause in the above example. Some sort of consistency check is often enough
  4. Checking types, then numerical relationships, then data is a common pattern You do not have to fully check the result in the post-condition E.g. The final ensure clause in the above example. Some sort of consistency check is often enough