Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a Circular dependency?

is this code a example of circular dependency?

package expr;
import sheet.Sheet
public class AdressExpr implements Expr
{
    private Address address; 
    private Sheet sheet; 
    public double value(Sheet sheet)
    {
        return sheet.value(address);
    }
}
public interface Expr
{
    public double value(Sheet sheet);
}
public class Adress
{
    // omissions
}

package sheet; 
import expr.Address; 
import expr.Expr;

public class Sheet implements SuperSheet
{
    private Map <Address, Expr> map; 
    public double value(Address address)
    {
    return map.get(Address).value(this);
    }
}
public interface SuperSheet
{
    public double value(Address address);
}

I know the example is bad programming but doesn't the interface prohibit the circular dependency, due to the value method?

like image 979
qwert Avatar asked Feb 14 '11 13:02

qwert


3 Answers

I think it is easier to see in the class diagram. As you can see, there is indeed a circular dependency between Sheet concrete class and Expr interface. I wouldn't say it is VERY bad because I consider circular dependency between 2 concrete classes to be the worst... that said, it is certainly not advisable to do so, if possible.

Your Code

enter image description here

So, perhaps one of the ways you might consider refactoring is to have your AddressExpr to depend on SuperSheet instead of Sheet and Expr to depend on SuperSheet instead of Sheet:-

public class AdressExpr implements Expr {
    private Address address;
    private SuperSheet  sheet;

    public double value(SuperSheet sheet) {
        return sheet.value(address);
    }
}

public interface Expr {
    public double value(SuperSheet sheet);
}

...
...

... and this will remove any unwanted circular dependencies.

Possible Refactored Code

enter image description here

NOTE: I'm not implying this is the solution. I'm just saying you can certainly look at ways to refactor your code to minimize or remove circular dependencies, because circular dependencies make your code difficult to unit test. Coding against interfaces always help to remove unwanted circular dependencies. It also make your code easier to unit test because you can easily mock objects.

like image 67
limc Avatar answered Nov 11 '22 15:11

limc


This is a really funky example. I'm going to be pretty verbose about my thought process here because I suspect there's some silly naming going on.

Packages: sheet expr

Contents of sheet:

  • Sheet
  • SuperSheet

Contents of expr:

  • AddressExpr
  • Expr
  • Address

Usages in each:

  • AddressExpr - Expr, Address, Sheet
  • Sheet - SuperSheet, Address

We see that AddressExpr depends on Sheet, which is in the sheet package. One dependency down.

We also see that Sheet depends on Address, in the expr package.

Therefore, you have circular dependency between the sheet and expr packages. (Note: Tools can show this. I did it by hand because your problem was pretty abstract. Look into JDepend)

In addition, I'm not even sure that I've ever heard of a value method. If the compiler can make sense of two-way interface use, it'll work. It has the sense to untangle the mess.

like image 34
Mike Avatar answered Nov 11 '22 17:11

Mike


At least on package level. Package sheet depends on package expr and vice versa. Based on own experience - I'd refactor this.

like image 37
Andreas Dolk Avatar answered Nov 11 '22 15:11

Andreas Dolk