15. JakubPilimon
–Michael C. Feathers
“Code refactoring is the process of
restructuring existing computer code
—changing the factoring—
without changing its observable
behavior. (!!!)”
36. JakubPilimonJakubPilimon
Black-box testing of observable behaviors
Collect
Book
Collected
Books View
Command
API call
queue listener
db script
executed…
Query
API call
Excel sheet
DB query
Place
Book On
Hold
Collected
Books View
Collect
Book
Placed on
Hold Books
View
37. JakubPilimonJakubPilimon
Black-box testing of observable behaviors
@Test
public void patronCanHoldABook() {
//given
BookEntity book = fixtures.aCirculatingBookAvailableForLending();
//and
BookHolderEntity patron = fixtures.aRegularPatron();
//when
patronWantsToHoldBook(patron, book);
//then
assertThat(placedOnHoldsBooksBy(patron)).containsExactlyInAnyOrder(book);
}
Hold
Book
Books on
Hold View
Observable Behaviors!!!
39. JakubPilimonJakubPilimon
Reverse engineering from tests to business rules
@Test
public void patronCanHoldABook() {
//given
BookEntity book = bookFromDb(“Domain-Driven Design”);
//and
BookHolderEntity john = fromDb(“John”);
//and
BookHolderEntity amy = fromDb(“Amy”);
//when
assertThatExceptionIsThrown(()-> patronWantsToHoldBook(john, book)); //exception
patronWantsToHoldBook(amy, book); //success
//then
assertThat(placedOnHoldsBooksBy(amy)).containsExactlyInAnyOrder(book);
}
Heuristics about rules
5 holds
rule?
Researcher
can book
Restricted
books?
John has
overdue
books?
DDD
Book is
special?
Why
exception?
Why
success?
40. JakubPilimon
How to make the transition?
JakubPilimon
Option #1: Climbing step by step (💩 slowly becomes 🦄)
Option #2: Blue/Green refactoring (🦄 side by side with 💩)
41. JakubPilimonJakubPilimon
• 💩 slowly becomes 🦄
•Observable effects of 💩
kept
•Cannot easily rollback to
💩 from 🦄
•Need to dig in 💩
•Need to maintain one
model
Step by Step Refactoring
43. JakubPilimonJakubPilimon
• 💩 remains untouched
•Observable behavior of 💩
kept
•Easy to rollback to 💩 from
🦄
• 🦄 feels a bit like a green
field in 💩
•Need to maintain both 💩 🦄
•Need to somehow plugin 🦄
to the observable behaviors
Blue/Green Refactoring
59. JakubPilimon
Black-box testing of observable behaviors should
pass against two models!
@Test
public void patronCanHoldABook() {
//given
BookEntity book = fixtures.aCirculatingBookAvailableForLending();
//and
BookHolderEntity patron = fixtures.aRegularPatron();
//when
patronWantsToHoldBookInNewModel(patron, book);
//then
assertThat(newModelPlacedOnHoldsBooksBy(patron)).containsExactlyInAnyOrder(book);
}
@Rule
public TogglzRule togglzRule = TogglzRule.allDisabled(NewModelToggles.class);
List<UUID> newModelPlacedOnHoldsBooksBy(BookHolderEntity aRegularPatron) {
togglzRule.enable(NewModelToggles.RECONCILE_AND_USE_NEW_MODEL);
//..
}
60. JakubPilimon
Place
Book On
Hold
Collected
Books View
Collect
Book
Placed on
Hold Books
View
Automated verification of two models
@Test
public void researcherCanPlaceOpenEndedHolds() {
//given
BookHolderEntity aResearcherPatron = fixtures.aResearcherPatron();
//when
patronWantsToHoldBookForOpenEndedHold(aResearcherPatron, aCirculatingBook);
//and
List<UUID> oldModel = oldModelPlacedOnHoldsBooksBy(aResearcherPatron);
List<UUID> newModel = newModelPlacedOnHoldsBooksBy(aResearcherPatron);
//then
assertThat(oldModel).containsExactlyInAnyOrderElementsOf(newModel);
}
61. JakubPilimon
Place
Book On
Hold
Collected
Books View
Collect
Book
Placed on
Hold Books
View
Production copy/Staging
Amy John
JakubPilimon
Exploratory testing against present data set after data
migration from 💩 to 🦄
Place
Book On
Hold
Collected
Books View
Collect
Book
Placed on
Hold Books
View
Production copy/Staging
Amy John
66. JakubPilimon
Modular monolith
Is the system modular?
Isthesystemdistributed?
Big Ball Of Mud
Distributed
Big Ball Of Mud
Modular Monolith
Microservices
67. JakubPilimon
• Always, ALWAYS! Test if ACL works correctly (returning
correct models depending on the toggle settings)
• Always test if ACL does reconciliation correctly!
• Add test that checks that your feature toggle is disabled/
enabled by default
• Go to production and reconcile very quickly (after 1st
seam)
• Make sure new model failures do not affect old model
• With B/G Refactoring you are limited to programming
language and database of BBOM
JakubPilimon
Lessons Learned