Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Learning TDD, always running into circular dependency

Tags:

c#

oop

tdd

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:

  • IView interface: a single setter string property: Result
  • GUIEventListener class: OnUserButtonClick method which gets called from the GUI's button
  • FileSaver class: SaveFile method which gets called from the GUIEventListener
  • GUIController class: UpdateLabel method which gets called from the FileSaver class's SaveFile method with a parameter depending the success of the SaveFile method.

Instantiation looks like this:

  • View's ctor: View(GUIEventListener eventListener)
  • GUIEventListener's ctor: GUIEventListener(FileSaver fileSaver)
  • FileSaver's ctor: FileSaver(GUIController controller)
  • GUIController's ctor: GUIController(View view)

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.

like image 249
SLOBY Avatar asked Mar 09 '12 07:03

SLOBY


People also ask

How do I stop circular dependency?

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.

How do you fix a circular dependency problem?

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.

What causes circular dependency?

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.

What is circular dependency problem?

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.


1 Answers

  • 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.

like image 180
guillaume31 Avatar answered Oct 12 '22 08:10

guillaume31