The document provides guidance on software design principles such as encapsulation, abstraction, and testing. It emphasizes designing software to be flexible and adaptable to change over time, managing dependencies, and releasing working code incrementally rather than following a "waterfall" model where everything is finished at the end. Key priorities include error handling, logging, measurements, internationalization, documentation, and avoiding over-engineering for hypothetical scenarios. The document stresses designing interfaces and abstractions to reduce complexity and control what other code can access.
6. The “Perfect” API
• Nearly an art form
• Very Important, but “not always”
• Are you really writing an important API?
• “Better” APIs tend to be intuitive, clear, concise
• Focus on what is visible to consumers
• API might be more than methods in classes
• Packaging solution may allow high levels of
“forgiveness” for “bad” design
6
7. “What If” and “Can’t Happen”
• Ask as many “what ifs” as you can
• Handle all answerable outcomes
• e.g. what if a service call fails?
• Don’t waste too much time on “Can’t Happen”
issues but be sure to handle them gracefully
• e.g.. Database will “NEVER” return null for a
value, which is true until the day it happens
7
8. The World’s Problems are
Not Yours
• Task: Displaying a graph of well-defined values
• Solve that first
• Then prioritize any unrelated issues or
improvements uncovered during
development
• Avoid the temptation to “dig more holes”
• Manage “Scope Creep”
8
9. The Day After Tomorrow
• Don’t over-engineer based on guesses
• Design to be flexible and adaptable
• Release equals Support
• Half implemented solutions just make
everything confusing
9
10. Clarity FTW
• A nice, clean solution is way easier to hand off
to the “next class”
• Bugs stick out in clear code
• Passing around an array of multi-dimensional
arrays of makes you cool, but with the wrong
crowd
• Complex interactions make everything more
difficult
• You’re the only one who can support it
10
11. Change is Constant
• Cliche but true
• Requirements change all the time. Don’t
live in a fantasy world
• Get ready to throw away that glorious API
you spent 4 weeks “perfecting”
• Expect change when designing software
11
14. Abstraction & Encapsulation
“The single most important factor that
distinguishes a well-designed module from a
poorly designed one is the degree to which
the module hides its internal data and other
implementation details from other modules.”
-Joshua Bloch
14
17. Abstraction
• Reducing visible chaos
• Creating your own API to consolidate or simplify
access to another system/service
• Generally is tailored to your specific needs, rather
than directly consuming something more generic
• Can be satisfied by any number of potential
implementors
• If you’re just duplicating an existing API, be sure that’s
the right approach
• Everything isn’t worthy of the effort - don’t overdo it
17
19. 12 well-defined inputs
Not possible to tell the system “Z” was pressed
http://en.wikipedia.org/wiki/File:Snes_control.jpg
19
20. Encapsulation
• Enforce the rules of your design/contract
and control what is exposed
• Manage (hide) complexity
• Can help you avoid tough decisions about
exposing API that isn’t ready for prime time
• Don’t rely on documentation to prevent
use - disallow use with scoping/exporting
20
21. What scares you?
• Things you can’t control
• External systems
• Buggy code
• Unclear APIs
• Things that you know will change soon
• Subsystems that you didn’t have time to
properly design
21
22. Everything is a “service”
• View external APIs / systems like they are
just another service
• Stay decoupled
• Create an abstraction layer to encapsulate
calls as you would any service
• Define your contract and create an
implementation that uses the external API /
service to fulfill
22
23. Are you too good for your home?
• “Risky” code can be given its own “home”
• Don’t be afraid to create new projects in
order to encapsulate things you don’t trust
• ...but use your best judgement to avoid
10,000 jars in your assembly
23
25. Testing
• White-box, check.
• Black-box, check.
• Expected exception from a service
implementation that I can’t ever re-create?
• Bad data that can “never” be returned?
• Mock implementations FTW.
• Design the proper abstractions up front
25
26. Know Your Dependencies
• What do you depend on and why?
• What versions cause joy/pain?
• Which pieces are tightly coupled and which
can be abstracted?
• Don’t get surprised by a new version
• Test against upgraded dependencies early
26
27. Releasing / Deploying
• More jars = more “fun”
• Release when ready vs “at the end”
• more difficult than it sounds
• temptation is to wait “in case”
• Always diff your end states
• You should be intimately aware of what is
changing (versions, additions, removals)
27
28. Installing / Upgrading
• Will any given change/feature cause any
difficulty in installation?
• is it worth it?
• can we design around it?
• What does the client need to do to use the
new version?
• Automate as much as possible
• May need additional functionality to support
28