My goals for the talk
• Show how what I have learned at coderetreats
have been taken into production use
• GOAL 1: Encourage us to practice the craft
• Show what I’ve done – Test Driving my design
• Show steps rather than finished ‘product’
• GOAL 2: initiate discussions on what I’ve done
• GOAL 3: reflect on my work and decisions and how
they actually seem now.
Tips for listeners
• There’s going to be a lot of code
• Rather than reading the code, try to smell it.
• How clean the code seems to be?
What I’ve done – what I believe in
• Is not either good or bad.
• It has bugs (I’ve seen those)
• It provides value to the customer every day
What is valuable (for someone)
• clients of the Client
• Myself & fellow ambientians
• How likely this code is going to change?
• How likely the change I make is going to introduce
bugs in future additions to this feature
Key process decisions
• TDD as design tool.
• Unit tests for changes
• Practice TDD in real environment. Try to get feedback
• Refactor often
• Keep tests clean
• ”if it is not important for the test, it is important not to
be in the test!”
• Note: Builder pattern
Key process decisions
• Use proper tools
• GIT, IntelliJ IDEA, VIM
• Hamcrest, mockito, various other open-source
4 elements of simple design
1. Passes its tests
2. Minimizes duplication
3. Maximizes clarity
4. Has fewer elements
• 1 day of coding
• Pair programming, 6 different pairing partner
• Learn through pairing
• Deliberate practice
Key takeaways from coderetreats
• Baby steps – commit to git often. Rebase to
keep git log clean
• Avoid conditionals, switches, try/catch
• Only 4 lines per method
• Avoid naked primitives
• Only one assert/behavior per test
• Sapir-Whorf hypothesis
• Tell – Don’t ask: no getters/setters for objects
1. One level of indentation per method
2. Don’t use the ELSE keyword
3. Wrap all primitives and Strings
4. First class collections
5. One dot per line
6. Don’t abbreviate
7. Keep all entities small
8. No classes with more than two instance
9. No getters / setters / properties
What I did was a brief study
• How the methods are used in the service?
• Grails-based service (200LOC) uses it
• Determine the current responsibilities
• Service builds valid parameters, DAO consumes it.
• Where the changes could be made?
• Both the service & DAO
• Is the method likely to change later?
• Factory to hide implementation details
• Sometimes Criteria handled Date, sometimes
• Make it first to work, refactor then.
• Create a ProductSearchCriteria per type –
think about the name of the object
• There were no tests before – try to make
minimal impact on code.
Test on localhost.
• The context is a bit more complex than I
• In one case, it was not enough to limit on
• Thus, the original factory-idea would turn into a
bit more complicated problem
• Fast to refactor
• Next time: start from integration test
• But one cannot integration test the whole – too many
• Minor changes somewhere in the controller code
caused it to fail on other places.
• Later, a colleague joined me. His first task was
to add a new concept to domain.
• Also for search
Decision to be made
• Where to start?
• The only (business) knowledge came from the
• I decided to tackle the switch-case structure
• It was spread 4 times throughout the code
• To ease the change from 20 to 5
• Similar concept with AttachmentFile and
• With one difference
• AttachmentFile is interface and has two concrete
classes PlainAttachmentFile and
• Use of Template-pattern (which changed a lot
• Factory to create an AttachmentFile
• Factory creates a AttachmentFileProcess –
process to move/copy/clone/delete the
• For specific AttachmentFileType, it does
• The execute method takes one argument,
AttachmentFileAction, which either is
And that led to
• New class: AttachmentFileName
• A domain logic for handling name of the Attachment
• I’m working with this. Now.
• Slow to refactor
• Test-Driven design can work even in brown-field
• Integration to old system required integration tests
• How valuable the changes were to the customer
• With my current understanding:
• Split the changes to two – deploy both separately.