I started using TDD to improve my quality and the design of my code but I usually encounter a problem. I'll try to explain it through a simple example: I try to implement a simple application using passive view design. This means that I try to make the view as dumb as possible. Let's consider an application, where the GUI has a button and a label. If the user presses the button, a file get created with one random line in it. Then the label displays whether the creation was successful or not. The code might look like this:
Instantiation looks like this:
As you can clearly see, there's a circular dependency in the design. I usually try to avoid using events, I don't like testing with them and I think this type of design is more self explanatory as it clearly states what are the relation of the classes. I'v heard of IoC design style but I'm not really familiar with it.
What are my "sticking point" in TDD regarding this issue? I always end up running into this problem and I want to learn a proper pattern or principle to avoid it in the future.
Avoiding circular dependencies by refactoring Circular dependencies create tight couplings between the classes or modules involved, which means both classes or modules have to be recompiled every time either of them is changed.
To resolve circular dependencies: Then there are three strategies you can use: Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.
A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can't always do so.
In software engineering, a circular dependency is a relation between two or more modules which either directly or indirectly depend on each other to function properly. Such modules are also known as mutually recursive.
- GUIController class: UpdateLabel method which gets called from the FileSaver class's SaveFile
...
- FileSaver's ctor: FileSaver(GUIController controller)
Here's the flaw in your design. The FileSaver should be agnostic of who calls it (read: shouldn't hold a reference to the layer underneath it), it should just do its job i.e. save a file and inform the world how the operation went - typically through a return value.
This not really related to TDD, except maybe TDD would have forced you to think in terms of the most basic behavior that is expected from a FileSaver and realize it is not its responsibility to update a label (see Single Responsibility Principle).
As for the other parts of your system, like Roy said they'll most often be difficult to test in TDD except for the Controller.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With