fake it outside-in tdd xp days i… · 2014 justin searls "the failures of 'intro to...

Post on 30-Sep-2020

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

FAKE IT OUTSIDE-IN TDDDavid Völkel 05.10.2017 @ XP Days Germany

@DAVIDVOELKEL@codecentric

@softwerkskammer

#TDD

INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache

"Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'"

COMBINATION 2015 Dimitry Polivaev Outside-In with faked Data 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement

INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache

"Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'"

COMBINATION 2015 Dimitry Polivaev Outside-In with faked Data 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement

INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design

COMBINATION FAKE IT OUTSIDE-IN TDD

FAKE IT OUTSIDE-IN TDD

INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache

"Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" 2017 Llewelyn Falco „Extreme: Fake it Till you Make It“

FAKE IT OUTSIDE-IN TDD

WHY? Outside-In => YAGNI free design

WHY? Outside-In => YAGNI free design

Avoid mocking drawbacks - Readability - Refactorability

AGENDA Theory

Building Blocks Fake It Outside-In

Questions

AGENDA Theory

Building Blocks Fake It Outside-In

Questions

OPEN SPACE Practice

Mob Programming Session Reflect

Retro Trade-Offs

BUILDING BLOCKS

INTEGRATION OPERATION SEGREGATION PRINCIPLE

public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service";

mailService.sendMail(email, content); }

OPERATION

public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service";

mailService.sendMail(email, content); }

INTEGRATION OPERATION SEGREGATION PRINCIPLE

INTEGRATION

INTEGRATION

OPERATION

public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service";

mailService.sendMail(email, content); }

INTEGRATION OPERATION SEGREGATION PRINCIPLE

INTEGRATION

INTEGRATION

OPERATION

public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service";

mailService.sendMail(email, content); }

INTEGRATION OPERATION SEGREGATION PRINCIPLE

OPERATION

INTEGRATIONpublic void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

String content = renderMessage(customer, customer.account());

mailService.sendMail(email, content); }

private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service"; }

INTEGRATION OPERATION SEGREGATION PRINCIPLE

public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

String content = renderMessage(customer, customer.account());

mailService.sendMail(email, content); }

private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service"; }

TESTS?

OPERATION

public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

String content = renderMessage(customer, customer.account());

mailService.sendMail(email, content); }

private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service"; }

TESTS?

N UNITTESTS

INTEGRATION

OPERATION

public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email);

String content = renderMessage(customer, customer.account());

mailService.sendMail(email, content); }

private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",\n\n" + "This week you get " + discount + " discount " + "on all our products.\n\n" + "Best Regards,\n" + "ACME Customer Service"; }

TESTS?1 INTEGRATION TEST

N UNITTESTS

GREEN BAR PATTERNS*

Obvious Implementation

Fake it (until you make it)

Triangulation

* Kent Beck in "TDD by Example"

GREEN BAR PATTERNS

Obvious Implementation

Fake it

Triangulation

Trade-Off

Complexity

SWEET SPOT

Trivial

GREEN BAR PATTERNS

Obvious Implementation

Fake it

Triangulation

SWEET SPOT

Trivial

Structure

GREEN BAR PATTERNS

Obvious Implementation

Fake it

Triangulation

SWEET SPOT

Trivial

Structure

Logic

GREEN BAR PATTERNS

Obvious Implementation

Fake it

Triangulation

PREPARATORY REFACTORINGS*

*"An example of preparatory refactoring", Martin Fowler

PREPARATORY REFACTORINGS*

*"An example of preparatory refactoring", Martin Fowler

"GREEN" PHASE TRIANGULATION

Implementation Run Test

"Green Phase"

LIMIT YOUR TIME IN RED

"Green Phase"

Implementation Run Test

LIMIT YOUR TIME IN RED

"Green Phase"

Implementation Run Test

Implementation Run TestPreparatory Refactoring

Acceptance Test

UI

Persistence

OUTSIDE-IN

Acceptance Test

UI

Persistence

OUTSIDE-IN & MOCKS

Unit test Mock

OUTSIDE-IN & MOCKS

Unit Test

OUTSIDE-IN & MOCKS

Acceptance Test

UI

Persistence

OUTSIDE-IN & MOCKS

Non trivial

Acceptance Test

OUTSIDE-IN & FAKE IT

Comprehensive

Acceptance Test

Faked Result

OUTSIDE-IN & FAKE IT

Acceptance Test

Fake

Fake

OUTSIDE-IN & FAKE IT

Acceptance Test Drive Structure

through Refactoring

OUTSIDE-IN & FAKE IT

OUTSIDE-IN & FAKE IT

Acceptance Test

Unit Test

Fill logic with

triangulation

OUTSIDE-IN & FAKE IT

Acceptance Test Unit Test

OUTSIDE-IN & FAKE IT INTEGRATION

Fake It

TriangulationOPERATION

Start with

• comprehensive Acceptance Test

• faked result

Drive structure by refactoring

Drive logic by unit tests

OUTSIDE-IN & FAKE IT INTEGRATION

Fake It

TriangulationOPERATION

Start with

• comprehensive Acceptance Test

• faked result

Drive structure by refactoring

Drive logic by unit tests

DIAMOND KATA

WHY? Outside-In

=> YAGNI free design Without mocking drawbacks

WHY? Outside-In

=> YAGNI free design Without mocking drawbacks

Vs Triangulation More time in GREEN Better Design Guidance

DISCUSSION

IMAGES Most are Public Domain except theses

Creative Commons with attributions:

"Unstruttalbrücke" by Störfix

From State Library of Queensland

FAKE IT OUTSIDE-IN TDD MOB PROGRAMMING SESSION

AGENDA 05 min. Intro & Kata 40 min. Mob Programming 15 min. Retro & Tradeoffs

OUTSIDE-IN & FAKE IT INTEGRATION

Fake It

TriangulationOPERATION

Start with

• comprehensive Acceptance Test

• faked result

Drive structure by refactoring

Drive logic by unit tests

OUTSIDE-IN & FAKE IT INTEGRATION

Fake It

TriangulationOPERATION

Start with

• comprehensive Acceptance Test

• faked result

Drive structure by refactoring

Drive logic by unit tests

DIAMOND KATA

KATA Continue Diamond Kata

https://github.com/davidvoelkel/diamond-kata

CODING SESSION

RETROSPECTIVE Observations?

RETROSPECTIVE Observations?

Strenghts / Weaknesses?

TRADE-OFFS FAKE IT VS

OUTSIDE-IN & MOCKS TRIANGULATION

CONDITIONAL INTERACTIONS

Mocking when IOSP not possible

public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); return "Welcome " + username; } else { return "Username ' " + username + "' " + "already taken, please choose another"; } }

COUPLING OUTSIDE-IN

Mocking Fake It

Decoupling Refactorability

DATA GUIDES STRUCTURE

Triangulation Fake It

Structure Cumbersome Data guides well

# BRANCHES

Triangulation Fake It

# N 1

More confidence More effort

# BRANCHES

Triangulation Fake It

# N 1

Fake data easy to forget

Omitting cases is tempting

TIME IN GREEN

Triangulation

Prep Refactoring Triangulation

Fake It

DISCUSSION

top related