C. Keith Ray

C. Keith Ray writes about and develops software in multiple platforms and languages, including iOS® and Macintosh®.
Keith's Résumé (pdf)

Monday, April 18, 2011

Coupling. Or... what you don't want your objects doing too much of.

Dependencies by one class on another class can cause problems when refactoring and writing microtests. In microtests, you want awkward collaborators to be faked, mocked, or stubbed out, and some kinds of dependencies make that more difficult than others.

Here are some dependencies from best (least-coupled) to worst (most tightly-coupled).

1. Class A depends on Class B, where class B is an interface ("pure" abstract base class).

We can test instances of A by creating our own test-specific subclasses of B to pass into A.

2. Class A depends on Class B, where class B is a concrete class but the functions are declared virtual.

We can test instances of A by creating our own test-specific subclases of B, but at a price: we have to deal with B's constructors and destructor, possibly doing stuff we don't want.

3. Class A depend on Class B, where class B is concrete class with no virtual functions.

We're going to need to refactor B and/or A for testability. Either making B's functions virtual, or putting an testable Adapter between A and B.

4. Class A depends on Class B, and class B grants class A "friend" access.

Class A not only depends on the public interface of B, but also the private parts of B as well. Not recommended. Don't do this unless you are Bjarne Stroustrup. If a test needs to access private parts of B, make those parts 'protected' and use a test-specific subclass to change selected parts of B to have 'public' access.

5. Class A depends on Class B, and class B is a class declared INSIDE class A.

This can lead to mutual complete visibility between A and B, plus the scoping makes it hard to test A without B, or vice versa. Not recommended. Don't do this unless you are Alexander Stepanov.

Also affecting how class A depends on class B is the WAY the dependency is manifest. It turns out that "visible" dependencies are often better than "hidden" dependencies, which is opposite of the usual idea of "information hiding", the predecessor idea of "encapsulation".

No comments:

Post a Comment