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?
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 veriļ¬cation 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);
}
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