Top Banner
Ted’s Tool Time Ted Vinke First8 Specifications Pattern August 2016
27

Specifications pattern - Teds Tool Time

Jan 22, 2018

Download

Technology

Ted Vinke
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Specifications pattern - Teds Tool Time

Ted’s Tool TimeTed VinkeFirst8

Specifications Pattern

August 2016

Page 2: Specifications pattern - Teds Tool Time

“Separate the statement of how to match a candidate, from the candidate object that it is matched against”

-- Martin Fowlerhttp://martinfowler.com/apsupp/spec.pdf

Page 3: Specifications pattern - Teds Tool Time

Using specifications to describe the selection criteria for portfolios in contracts.

Page 4: Specifications pattern - Teds Tool Time

Using specifications to describe the selection criteria for portfolios in contracts.

Page 5: Specifications pattern - Teds Tool Time

Using specifications to constrain which containers can be used for transporting a cargo

Page 6: Specifications pattern - Teds Tool Time

Using a specification as an input to a route selector. This decouples the route selector from the

shipment.

Page 7: Specifications pattern - Teds Tool Time

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

Page 8: Specifications pattern - Teds Tool Time
Page 9: Specifications pattern - Teds Tool Time

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)

Page 10: Specifications pattern - Teds Tool Time

Is a genomic test allowed?version 1

(Warning: Groovy ahead!)

Page 11: Specifications pattern - Teds Tool Time

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)

Page 12: Specifications pattern - Teds Tool Time

Animal should be female

Need:

class Animal {

AnimalId id

String name

String gender

}

Check:

gender.toLowerCase() == ‘female’

Page 13: Specifications pattern - Teds Tool Time

Animal should not have been tested before

Need:

HerdbookRepository herdbookRepository

Check:

AnimalHeredityResource heredity =

herdbookRepository.retrieveHeredity(animal.id)

heredity != null

Page 14: Specifications pattern - Teds Tool Time

No existing genomic tests

Need:

BreedingRepository breedingRepository

Check:

Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests()

GenomicTestResource existingTest = testResources.find { test ->

test.animalId == animal.id

}

Page 15: Specifications pattern - Teds Tool Time

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

}

}

Page 16: Specifications pattern - Teds Tool Time

Is a genomic test allowed?version 2

(Warning: Groovy ahead!)

Page 17: Specifications pattern - Teds Tool Time

GenomicTestedBeforeCondition

class GenomicTestedBeforeCondition {

HerdbookRepository herdbookRepository

boolean isSatisfiedBy(Animal animal) {

final AnimalHeredityResource heredity = herdbookRepository.retrieveHeredity(animal.id)

return heredity?.heredity

}

}

Page 18: Specifications pattern - Teds Tool Time

GenomicTestRequestExistsCondition

class GenomicTestRequestExistsCondition {

BreedingRepository breedingRepository

boolean isSatisfiedBy(Animal animal) {

Collection<GenomicTestResource> testResources = breedingRepository.retrieveTests()

return testResources.find { test ->

test.animalId == animal.id

}

}

Page 19: Specifications pattern - Teds Tool Time

Animal

class Animal {

AnimalId id

String name

String gender

boolean isFemale() {

gender.toLowerCase() == 'female'

}

}

Page 20: Specifications pattern - Teds Tool Time

Putting them together

Page 21: Specifications pattern - Teds Tool Time

GenomicTestRequestAllowedCondition (1)

class GenomicTestRequestAllowedCondition {

GenomicTestedBeforeCondition genomicTestedBeforeCondition

GenomicTestRequestExistsCondition genomicTestRequestExistsCondition

...

Page 22: Specifications pattern - Teds Tool Time

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) }

Page 23: Specifications pattern - Teds Tool Time

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)

}

}

Page 24: Specifications pattern - Teds Tool Time

Testing easier

Page 25: Specifications pattern - Teds Tool Time

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)

}

}

Page 26: Specifications pattern - Teds Tool Time

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) }

Page 27: Specifications pattern - Teds Tool Time

That's it!

Thank you