SlideShare uma empresa Scribd logo
1 de 27
Ted’s Tool Time
Ted Vinke
First8
Specifications Pattern
August 2016
“Separate the statement of how to
match a candidate, from the candidate
object that it is matched against”
-- Martin Fowler
http://martinfowler.com/apsupp/spec.pdf
Using specifications to describe the selection criteria for portfolios in contracts.
Using specifications to describe the selection criteria for portfolios in contracts.
Using specifications to constrain which containers can be used for transporting a cargo
Using a specification as an input to a route selector. This decouples the route selector from the
shipment.
Advantages
Treating the specification as a separate object has a number of advantages
Lets you decouple the design of requirements, fulfillment, and validation
Allows you to make your systemdefinitions more clear and declarative
3 simple requirements
1. Animal should be
female
2. Animal should not have
been tested before
(Herdbook API)
3. No existing genomic
tests (Breeding API)
Is a genomic test allowed?
version 1
(Warning: Groovy ahead!)
Render only animals for which genomic test is
allowed
Need:
HousingService housingService
Iterate and check:
Collection<Animal> animals = housingService.retrieveAnimals()
animals.each { animal ->
boolean matches = isGenomicTestAllowed(animal)
Animal should be female
Need:
class Animal {
AnimalId id
String name
String gender
}
Check:
gender.toLowerCase() == ‘female’
Animal should not have been tested before
Need:
HerdbookRepository herdbookRepository
Check:
AnimalHeredityResource heredity =
herdbookRepository.retrieveHeredity(animal.id)
heredity != null
No existing genomic tests
Need:
BreedingRepository breedingRepository
Check:
Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests()
GenomicTestResource existingTest = testResources.find { test ->
test.animalId == animal.id
}
Putting them
together
HousingService housingService
HerdbookBackendRepository herdbookBackendRepository
BreedingRepository breedingRepository
boolean isGenomicTestAllowed(Animal animal) {
boolean genderMatch = gender.toLowerCase() == ‘female’
AnimalHeredityResource heredity = herdbookRepository.retrieveHeredity(animal.id)
boolean heredityMatch = heredity != null
Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests()
boolean existingTestMatch = testResources.find { test ->
test.animalId == animal.id
}
return genderMatch && heredityMatch && existingTestMatch
}
}
Is a genomic test allowed?
version 2
(Warning: Groovy ahead!)
GenomicTestedBeforeCondition
class GenomicTestedBeforeCondition {
HerdbookRepository herdbookRepository
boolean isSatisfiedBy(Animal animal) {
final AnimalHeredityResource heredity = herdbookRepository.retrieveHeredity(animal.id)
return heredity?.heredity
}
}
GenomicTestRequestExistsCondition
class GenomicTestRequestExistsCondition {
BreedingRepository breedingRepository
boolean isSatisfiedBy(Animal animal) {
Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests()
return testResources.find { test ->
test.animalId == animal.id
}
}
Animal
class Animal {
AnimalId id
String name
String gender
boolean isFemale() {
gender.toLowerCase() == 'female'
}
}
Putting them together
GenomicTestRequestAllowedCondition (1)
class GenomicTestRequestAllowedCondition {
GenomicTestedBeforeCondition genomicTestedBeforeCondition
GenomicTestRequestExistsCondition genomicTestRequestExistsCondition
...
GenomicTestRequestAllowedCondition (2)
class GenomicTestRequestAllowedCondition {
GenomicTestedBeforeCondition genomicTestedBeforeCondition
GenomicTestRequestExistsCondition genomicTestRequestExistsCondition
private Closure isFemale = { Animal animal -> animal.female }
private Closure notTestedBefore = { Animal animal -> !genomicTestedBeforeCondition.isSatisfiedBy(animal) }
private Closure noExistingGenomicTests = { Animal animal -> !genomicTestRequestExistsCondition.isSatisfiedBy(animal) }
GenomicTestRequestAllowedCondition (3)
class GenomicTestRequestAllowedCondition {
GenomicTestedBeforeCondition genomicTestedBeforeCondition
GenomicTestRequestExistsCondition genomicTestRequestExistsCondition
private Closure isFemale = { Animal animal -> animal.female }
private Closure notTestedBefore = { Animal animal -> !genomicTestedBeforeCondition.isSatisfiedBy(animal) }
private Closure noExistingGenomicTests = { Animal animal -> !genomicTestRequestExistsCondition.isSatisfiedBy(animal) }
boolean isSatisfiedBy(Animal a) {
isFemale(a) && notTestedBefore(a) && noExistingGenomicTests(a)
}
}
Testing easier
Individual specification
class GenomicTestedBeforeConditionSpec extends Specification {
void "test condition should check that animal is tested before"() {
given:
GenomicTestedBeforeCondition condition = new GenomicTestedBeforeCondition()
when: "there are heredity characteristics"
condition.herdbookRepository = Mock(HerdbookRepository) {
1 * retrieveHeredity(_) >> new AnimalHeredityResource()
}
then: "animal must have been tested before"
condition.isSatisfiedBy(SOME_ANIMAL)
}
}
Combination of specifications
class GenomicTestRequestAllowedConditionSpec extends Specification {
GenomicTestRequestAllowedCondition condition = new GenomicTestRequestAllowedCondition()
void "test condition should be satisfied if all subconditions are met"() {
when: "all subconditions are met"
condition.isFemale = { true }
condition.notTestedBefore = { true }
condition.noExistingGenomicTests = { true }
then: "the condition is satisified"
condition.isSatisfiedBy(new Animal())
when: "one of the subconditions is not met"
condition.notTestedBefore = { false }
……...
Remember these closures? :-)
private Closure isFemale = { Animal animal -> animal.female }
private Closure notTestedBefore = { Animal animal -> !genomicTestedBeforeCondition.isSatisfiedBy(animal) }
private Closure noExistingGenomicTests = { Animal animal -> !genomicTestRequestExistsCondition.isSatisfiedBy(animal) }
That's it!
Thank you

Mais conteúdo relacionado

Semelhante a Specifications pattern - Ted's Tool Time

Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)Oliver Klee
 
Test-driven Development for TYPO3
Test-driven Development for TYPO3Test-driven Development for TYPO3
Test-driven Development for TYPO3Oliver Klee
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJohn Ferguson Smart Limited
 
Recommending Method Invocation Context Changes
Recommending Method Invocation Context ChangesRecommending Method Invocation Context Changes
Recommending Method Invocation Context ChangesBeat Fluri
 
Be smart when testing your Akka code
Be smart when testing your Akka codeBe smart when testing your Akka code
Be smart when testing your Akka codeMykhailo Kotsur
 
Test-Driven Development for TYPO3
Test-Driven Development for TYPO3Test-Driven Development for TYPO3
Test-Driven Development for TYPO3Oliver Klee
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava SchmidtJavaDayUA
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2Yi-Huan Chan
 
Mining Plant Pathogen Genomes for Effectors
Mining Plant Pathogen Genomes for EffectorsMining Plant Pathogen Genomes for Effectors
Mining Plant Pathogen Genomes for EffectorsLeighton Pritchard
 
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...GeeksLab Odessa
 
Test in action week 4
Test in action   week 4Test in action   week 4
Test in action week 4Yi-Huan Chan
 

Semelhante a Specifications pattern - Ted's Tool Time (15)

JUnit Pioneer
JUnit PioneerJUnit Pioneer
JUnit Pioneer
 
Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)
 
Test-driven Development for TYPO3
Test-driven Development for TYPO3Test-driven Development for TYPO3
Test-driven Development for TYPO3
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit Tests
 
Recommending Method Invocation Context Changes
Recommending Method Invocation Context ChangesRecommending Method Invocation Context Changes
Recommending Method Invocation Context Changes
 
Generic
GenericGeneric
Generic
 
Be smart when testing your Akka code
Be smart when testing your Akka codeBe smart when testing your Akka code
Be smart when testing your Akka code
 
Test-Driven Development for TYPO3
Test-Driven Development for TYPO3Test-Driven Development for TYPO3
Test-Driven Development for TYPO3
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava Schmidt
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
 
Testing untestable code - DPC10
Testing untestable code - DPC10Testing untestable code - DPC10
Testing untestable code - DPC10
 
Mining Plant Pathogen Genomes for Effectors
Mining Plant Pathogen Genomes for EffectorsMining Plant Pathogen Genomes for Effectors
Mining Plant Pathogen Genomes for Effectors
 
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
 
Test in action week 4
Test in action   week 4Test in action   week 4
Test in action week 4
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
 

Mais de Ted Vinke

Spock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeSpock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeTed Vinke
 
Upcoming Events 2017 for a Java Software Developer - Ted's Tool Time
Upcoming Events 2017 for a Java Software Developer - Ted's Tool TimeUpcoming Events 2017 for a Java Software Developer - Ted's Tool Time
Upcoming Events 2017 for a Java Software Developer - Ted's Tool TimeTed Vinke
 
Gmail Email Markup - Ted's Tool Time
Gmail Email Markup - Ted's Tool TimeGmail Email Markup - Ted's Tool Time
Gmail Email Markup - Ted's Tool TimeTed Vinke
 
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool TimeCode Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool TimeTed Vinke
 
JUnit 5 - The Next Generation of JUnit - Ted's Tool Time
JUnit 5 - The Next Generation of JUnit - Ted's Tool TimeJUnit 5 - The Next Generation of JUnit - Ted's Tool Time
JUnit 5 - The Next Generation of JUnit - Ted's Tool TimeTed Vinke
 
JEP 286 Local-Variable Type Inference - Ted's Tool Time
JEP 286 Local-Variable Type Inference - Ted's Tool TimeJEP 286 Local-Variable Type Inference - Ted's Tool Time
JEP 286 Local-Variable Type Inference - Ted's Tool TimeTed Vinke
 
Devoxx 2015 - Web Application Development using Grails and Docker
Devoxx 2015 - Web Application Development using Grails and DockerDevoxx 2015 - Web Application Development using Grails and Docker
Devoxx 2015 - Web Application Development using Grails and DockerTed Vinke
 
Working with Groovy Collections
Working with Groovy CollectionsWorking with Groovy Collections
Working with Groovy CollectionsTed Vinke
 
The Apache Software Foundation - Ted's Tool Time - Sep 2015
The Apache Software Foundation - Ted's Tool Time - Sep 2015The Apache Software Foundation - Ted's Tool Time - Sep 2015
The Apache Software Foundation - Ted's Tool Time - Sep 2015Ted Vinke
 
Devoxx 2014 Report
Devoxx 2014 ReportDevoxx 2014 Report
Devoxx 2014 ReportTed Vinke
 

Mais de Ted Vinke (10)

Spock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeSpock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted Vinke
 
Upcoming Events 2017 for a Java Software Developer - Ted's Tool Time
Upcoming Events 2017 for a Java Software Developer - Ted's Tool TimeUpcoming Events 2017 for a Java Software Developer - Ted's Tool Time
Upcoming Events 2017 for a Java Software Developer - Ted's Tool Time
 
Gmail Email Markup - Ted's Tool Time
Gmail Email Markup - Ted's Tool TimeGmail Email Markup - Ted's Tool Time
Gmail Email Markup - Ted's Tool Time
 
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool TimeCode Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
 
JUnit 5 - The Next Generation of JUnit - Ted's Tool Time
JUnit 5 - The Next Generation of JUnit - Ted's Tool TimeJUnit 5 - The Next Generation of JUnit - Ted's Tool Time
JUnit 5 - The Next Generation of JUnit - Ted's Tool Time
 
JEP 286 Local-Variable Type Inference - Ted's Tool Time
JEP 286 Local-Variable Type Inference - Ted's Tool TimeJEP 286 Local-Variable Type Inference - Ted's Tool Time
JEP 286 Local-Variable Type Inference - Ted's Tool Time
 
Devoxx 2015 - Web Application Development using Grails and Docker
Devoxx 2015 - Web Application Development using Grails and DockerDevoxx 2015 - Web Application Development using Grails and Docker
Devoxx 2015 - Web Application Development using Grails and Docker
 
Working with Groovy Collections
Working with Groovy CollectionsWorking with Groovy Collections
Working with Groovy Collections
 
The Apache Software Foundation - Ted's Tool Time - Sep 2015
The Apache Software Foundation - Ted's Tool Time - Sep 2015The Apache Software Foundation - Ted's Tool Time - Sep 2015
The Apache Software Foundation - Ted's Tool Time - Sep 2015
 
Devoxx 2014 Report
Devoxx 2014 ReportDevoxx 2014 Report
Devoxx 2014 Report
 

Último

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 

Último (20)

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 

Specifications pattern - Ted's Tool Time

  • 1. Ted’s Tool Time Ted Vinke First8 Specifications Pattern August 2016
  • 2. “Separate the statement of how to match a candidate, from the candidate object that it is matched against” -- Martin Fowler http://martinfowler.com/apsupp/spec.pdf
  • 3. Using specifications to describe the selection criteria for portfolios in contracts.
  • 4. Using specifications to describe the selection criteria for portfolios in contracts.
  • 5. Using specifications to constrain which containers can be used for transporting a cargo
  • 6. Using a specification as an input to a route selector. This decouples the route selector from the shipment.
  • 7. Advantages Treating the specification as a separate object has a number of advantages Lets you decouple the design of requirements, fulfillment, and validation Allows you to make your systemdefinitions more clear and declarative
  • 8.
  • 9. 3 simple requirements 1. Animal should be female 2. Animal should not have been tested before (Herdbook API) 3. No existing genomic tests (Breeding API)
  • 10. Is a genomic test allowed? version 1 (Warning: Groovy ahead!)
  • 11. Render only animals for which genomic test is allowed Need: HousingService housingService Iterate and check: Collection<Animal> animals = housingService.retrieveAnimals() animals.each { animal -> boolean matches = isGenomicTestAllowed(animal)
  • 12. Animal should be female Need: class Animal { AnimalId id String name String gender } Check: gender.toLowerCase() == ‘female’
  • 13. Animal should not have been tested before Need: HerdbookRepository herdbookRepository Check: AnimalHeredityResource heredity = herdbookRepository.retrieveHeredity(animal.id) heredity != null
  • 14. No existing genomic tests Need: BreedingRepository breedingRepository Check: Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests() GenomicTestResource existingTest = testResources.find { test -> test.animalId == animal.id }
  • 15. Putting them together HousingService housingService HerdbookBackendRepository herdbookBackendRepository BreedingRepository breedingRepository boolean isGenomicTestAllowed(Animal animal) { boolean genderMatch = gender.toLowerCase() == ‘female’ AnimalHeredityResource heredity = herdbookRepository.retrieveHeredity(animal.id) boolean heredityMatch = heredity != null Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests() boolean existingTestMatch = testResources.find { test -> test.animalId == animal.id } return genderMatch && heredityMatch && existingTestMatch } }
  • 16. Is a genomic test allowed? version 2 (Warning: Groovy ahead!)
  • 17. GenomicTestedBeforeCondition class GenomicTestedBeforeCondition { HerdbookRepository herdbookRepository boolean isSatisfiedBy(Animal animal) { final AnimalHeredityResource heredity = herdbookRepository.retrieveHeredity(animal.id) return heredity?.heredity } }
  • 18. GenomicTestRequestExistsCondition class GenomicTestRequestExistsCondition { BreedingRepository breedingRepository boolean isSatisfiedBy(Animal animal) { Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests() return testResources.find { test -> test.animalId == animal.id } }
  • 19. Animal class Animal { AnimalId id String name String gender boolean isFemale() { gender.toLowerCase() == 'female' } }
  • 21. GenomicTestRequestAllowedCondition (1) class GenomicTestRequestAllowedCondition { GenomicTestedBeforeCondition genomicTestedBeforeCondition GenomicTestRequestExistsCondition genomicTestRequestExistsCondition ...
  • 22. GenomicTestRequestAllowedCondition (2) class GenomicTestRequestAllowedCondition { GenomicTestedBeforeCondition genomicTestedBeforeCondition GenomicTestRequestExistsCondition genomicTestRequestExistsCondition private Closure isFemale = { Animal animal -> animal.female } private Closure notTestedBefore = { Animal animal -> !genomicTestedBeforeCondition.isSatisfiedBy(animal) } private Closure noExistingGenomicTests = { Animal animal -> !genomicTestRequestExistsCondition.isSatisfiedBy(animal) }
  • 23. GenomicTestRequestAllowedCondition (3) class GenomicTestRequestAllowedCondition { GenomicTestedBeforeCondition genomicTestedBeforeCondition GenomicTestRequestExistsCondition genomicTestRequestExistsCondition private Closure isFemale = { Animal animal -> animal.female } private Closure notTestedBefore = { Animal animal -> !genomicTestedBeforeCondition.isSatisfiedBy(animal) } private Closure noExistingGenomicTests = { Animal animal -> !genomicTestRequestExistsCondition.isSatisfiedBy(animal) } boolean isSatisfiedBy(Animal a) { isFemale(a) && notTestedBefore(a) && noExistingGenomicTests(a) } }
  • 25. Individual specification class GenomicTestedBeforeConditionSpec extends Specification { void "test condition should check that animal is tested before"() { given: GenomicTestedBeforeCondition condition = new GenomicTestedBeforeCondition() when: "there are heredity characteristics" condition.herdbookRepository = Mock(HerdbookRepository) { 1 * retrieveHeredity(_) >> new AnimalHeredityResource() } then: "animal must have been tested before" condition.isSatisfiedBy(SOME_ANIMAL) } }
  • 26. Combination of specifications class GenomicTestRequestAllowedConditionSpec extends Specification { GenomicTestRequestAllowedCondition condition = new GenomicTestRequestAllowedCondition() void "test condition should be satisfied if all subconditions are met"() { when: "all subconditions are met" condition.isFemale = { true } condition.notTestedBefore = { true } condition.noExistingGenomicTests = { true } then: "the condition is satisified" condition.isSatisfiedBy(new Animal()) when: "one of the subconditions is not met" condition.notTestedBefore = { false } ……... Remember these closures? :-) private Closure isFemale = { Animal animal -> animal.female } private Closure notTestedBefore = { Animal animal -> !genomicTestedBeforeCondition.isSatisfiedBy(animal) } private Closure noExistingGenomicTests = { Animal animal -> !genomicTestRequestExistsCondition.isSatisfiedBy(animal) }