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

Objects Dependancies Are Their Own Tax

This list of ways one class can depend on another is ordered from worst to best (for C++):

1. A depends on B because B is Singleton.

Avoid this. The dependency is 'invisible' and Singleton makes it worse than a global variable. Destruction is usually not possible unless a counting mechanism is used.

2. A depends on B because B is global variable.

Avoid this. The dependency is 'invisible'.

3. A depends on B because B is a file-local variable.

Avoid this. Not accessible to test.

4. A depends on B because B is a function-static variable.

Avoid this. Initialization is not multiple-thread safe. Not accessible to test. Destruction is difficult.

5. A depends on B because B is a class-static variable.

Avoid this. A class with static members and non-static members is doing two things. Separate the two responsibilities into separate classes, one of which can be a longer-lived than the other.

6. A depends on B because B is a member variable of A "by value".

Great for "value" objects, not so good for other kinds of objects. ("By Value" means by not by pointer nor by reference,)

7. A depends on B because B is a local variable of one of A's function.

Inaccessible to test. The dependency is 'invisible'.

8. A depends on B because B is a "by value" parameter in A's functions.

Not subject to faking or mocking, any data or behavior that are defined in a subclass of 'B' is "sliced-off" to be just a "B" inside the function.

9. A depends on B because B is a pointer/reference member of A, created in constructor.

Creation in the constructor is too soon for us to insert a fake.

10. A depends on B because B is a pointer/reference member of A, created in non-virtual function.

We can't override the creation inside the function.

11. A depends on B because B is a pointer/reference member of A, created in virtual function.

This allows us to override the function that creates B, using a fake, stub, or mock.

12. A depends on B because B is a pointer/reference member set by parameter in A's constructor.

We can create A with a fake, sub, or mock in testing. Dependency is visible.

13. A depends on B because B is a pointer/reference parameter in A's functions.

This makes the dependency visible in the interface. We can supply fake, stub, or mock in testing.

No comments:

Post a Comment