Jakub is a Java EE developer since 2005 and occasionally a project manager, working currently with Iterate AS. He's highly interested in developer productivity (and tools like Maven and AOP/AspectJ), web frameworks, Java portals, testing and performance and works a lot with IBM technologies. A native to Czech Republic, he lives now in Oslo, Norway. Jakub is a DZone MVB and is not an employee of DZone and has posted 154 posts at DZone. You can read more from them at their website. View Full User Profile

Book Review: Implementation Patterns

07.26.2012
| 4528 views |
  • submit to reddit

Summary: Should you read the book? It contains pearls of wisdom hidden in the mud of “I know that already, man.” I’d thus recommend skimming through the book and reading only the pieces matching your level and needs.

The book seems to be targeted a lot at Java beginners (especially the chapter on collections), going into otherwise unnecessary details, yet there are many valuable advises of which some can only be appreciated by somebody with multiple years of professional programming experience. It thus seems to me that the book isn’t a perfect match for anybody but everybody will find there many useful ideas. It would best be split in two.

An experienced developer will already know many of the patterns though it’s perhaps useful to see them named and described explicitly and listed next to each – it helps to be aware and clearer of what you do and why you do it.

I’d absolutely recommend everybody to read the chapter A Theory of Programming, explaining Kent’s style of programming and the underlying key values of communication, simplicity and flexibility as well as the more concrete principles (local consequence, minimize repetition, logic and data together, symmetry, declarative expression, co-locating data and logic having the same rate of change). Also in the rest of the book there are valuable ideas that it would be a pity to miss. I list below some of those that I found particularly interesting.

Selected Quotes etc.

  • On the cost of software, maintenance, big up-front designs, communication: “[..] the cost of software maintenance is much higher than the cost of initial development. [..] Maintenance is expensive because understanding existing code is time-consuming and error-prone.” p.19
    • “One strategy for reducing overall cost is to invest more in initial development in hope of reducing or eliminating the need for maintenance. Such efforts have generally failed to reduce overall costs. When code needs to change in unanticipated ways, no amount of forethought can perfectly prepare the code for change. The premature attempts to make the code general enough to meet future needs often interfere with the unanticipated changes that turn out to be necessary.” p.19 The future is uncertain and money we’ve now are generally more valuable than those we might save in the future.
    • “My strategy for reducing overall costs is to ask all programmers to address the cost of understanding code during the maintenance phase by focusing on communicating, programmer-to-programmer.” p.20
    • “[..] the implementation patterns are focused on ways to gain immediate benefit while setting up clean code for ease of future development.”
  • Flexibility (and simplicity): “Making workable decisions today and maintaining the flexibility to change your mind in the future is a key to good software development.” p.45
  • Aesthetics and programming: “Sometimes I feel silly introducing methods ‘just’ to satisfy an ‘aesthetic’ urge like symmetry. Aesthetics go deeper than that. [..] Once you have cultivated your sense of aesthetics of code, the aesthetic impression you receive of your code is valuable feedback about the quality of the code.” p.68
  • Why revealing intent and hiding implementation is important: “The distinction between intention and implementation [..] It is what allows you to understand a computation first in essence and later, if necessary, in detail.” p.69
    (=> the “explaining message” pattern: send first a message (call method) named after the problem you’re solving which in turn sends a message named after how it’s solved)
  • “Compose methods based on facts, not speculation. Get your code working, then decide how it should be structured.” p.78 – you learn only during the implementation what pieces you need and how the best fit them together
    • Similarly: “Try moving the logic and seeing if it reads more clearly. Sometimes these moves violate your preconception about which object is responsible for what part of a computation. Believing and acting on the evidence of your eyes generally improves the design.” p.94
  • Method naming: “Why was this method invoked and not some other? [..] The calling method should be telling a story. Name methods so they help tell the story.” p.79
  • Final methods (and classes): Use only when overriding the method would lead to serious consequences. “I don’t use final myself, and I have occasionally been frustrated when encountering final methods when I had legitimate reason to override a method.” p.81 (JH: Final might often prevent testing or complicate it unnecessarily.)
  • “Following the principle of putting logic and data together, the need for public- or package-visible getting methods is a clue that logic should be elsewhere.” (though there are some exceptions) p.95
  • Setters: The name should be written from the client code’s perspective, w.r.t. what it wants to achieve, not how => .centered() is better than setJustification(CENTERED).
  • About safe copies (return new List(instanceList)): Use only rarely, when really needed, not as a part of the core semantics. “Immutable objects and composed methods provide simpler, more communicative interfaces that are less prone to error.” p.98
  • “Learning how to use patterns needs to be followed by learning when to use them and when to leave them in the bag.” p.131

Other Highlights

  • Design: when to use an interface (-: can’t add methods) and when to use an abstract class (-: more coupled, single inheritance). Use “versioned interface” (f.ex. “interface MyServiceEnhanced extends MyService”) when you need to add a method to an interface but cannot force existing clients to update
  • Design patterns for expressing clearly what is similar and what is different
  • Guard Clause: Don’t mix exceptional flows with the main logic flow, i.e. have simple checks like “if (param1 == null) throw new IllegalArgumentExc.(..);” at the beginning instead of (nested?!) if-else. (JH: I even prefer to drop {..} here since guard statements are and always should be one-liners and are thus easier to spot and read.)
  • The chapter about evolving frameworks was also quite interesting
  • Simple Superclass Name (p.23): Important classes should have one-word names. Find rich metaphors to make even the short names expressive enough. Strike balance between brevity and expressiveness in class names.
Published at DZone with permission of Jakub Holý, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: