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