49.

What We've Learned

In this chapter on the Fictitious Implementation bug pattern we've learned the following:

  • Specifying an interface for all the services that a client expects to use makes it possible to plug in various implementations of that interface as necessary.

  • The only parts of a specification that can be checked statically are method signatures.

  • When an implementation of an interface fails to satisfy some necessary invariants, we have an instance of the Fictitious Implementation bug pattern.

  • Fictitious Implementations may not be immediately apparent, but can lurk hidden until some uncommon execution path uncovers them. They may pass compilation without incident.

  • Because Java checks only the type signatures of interface implementations, it is possible to "implement" an interface without actually meeting its intended semantics.

  • A disadvantage: many invariants we would like to specify cannot be checked statically.

  • The addition of assertions—boolean checks for certain conditions at various stages in the execution of a program—is a potential method for preventing Fictitious Implementations. Because they can be compiled into the code, assertions are a fast and powerful diagnostic tool.

  • Assertions should be included in the agreement the implementation of an interface makes with outside clients.

  • The three kinds of assertions are: (1) a invariant that checks that some condition holds during the execution of a code block. (Invariants are rarely supported in the general form due to expense.)

  • In all but the most performance-critical sections of a program, the overhead of assertion checking will not be significant. Leaving assertions in makes it easier to diagnose bug reports from users.

  • Like types, assertions are not expressive enough by themselves to capture all of the rules we may want to specify on an interface. For this reason, they are best used in tandem with unit tests.

  • Unit tests provide limited specification of extra invariants as a means for an implementer to check that the extra invariants of an interface are satisfied.

  • Unlike type declarations, unit tests cannot check an implementation over all possible inputs.

  • Unit tests should be small, straightforward, and easy to read. Because they can be arbitrary Java code, they allow us to test complex behaviors of an implementation.

  • It is important that the maintainer of the interface document any invariants that may be assumed by a client programmer.

  • Client code that relies on undocumented invariants can quickly lose value since it may be incompatible with future releases of the interface implementation.

In Chapter 18, we'll look at instances of the Orphaned Thread, a bug pattern that can make using the marvelous ability of multithreading a bit of a headache.



Bug Patterns in Java
Bug Patterns In Java
ISBN: 1590590619
EAN: 2147483647
Year: N/A
Pages: 95
Authors: Eric Allen

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net