Best way to reference the plugin object in an external class?

Discussion in 'Plugin Development' started by Pitazzo, Jul 9, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    mazentheamazin

    *read :p
     
  2. mazentheamazin Pfft, don't know what you're on about.

    *corrects post*
     
    mazentheamazin likes this.
  3. Offline

    FerusGrim

    I read sticky posts. D=
     
    AdamQpzm and _LB like this.
  4. Offline

    DannyDog

    Who doesn't?
     
    _LB likes this.
  5. Offline

    1Rogue

    (Coming in late)

    I think I'd argue this:

    Code:java
    1. public class A {
    2.  
    3. private final B bee;
    4.  
    5. public A() {
    6. this.bee = new B(this);
    7. }
    8.  
    9. }

    Code:java
    1. public class B {
    2.  
    3. private final A ayy;
    4.  
    5. public B(A ayy) {
    6. this.ayy = ayy;
    7. }
    8.  
    9. }


    Of course that leaves you with the A class as the initializing dependency, but no need for counter maneuvering around using constructors. (There is also the whole passing of "this" before the 'bee' var can be set, but it already has the reference to itself, so in a more complex design it would be set much later in a constructor).

    Also re: The constructor argument bloat, while possibly outside the scope of the question would be the Builder pattern
     
  6. Offline

    garbagemule

    You have to be extremely cautious when using this kind of approach!

    First of all, as you said, class A now has the responsibility of instantiating a reference to the object of B that it needs (something that could be a sign of code smell in some cases), which only solves the problem if a reference to that specific object isn't needed anywhere else. Otherwise, you now need a getter in A to solve the circular dependency problem and still maintain the flexibility of external instantiators (something that is required in Builder). In fact, if the reference the B object inside of A is not needed elsewhere, you don't necessarily have to consider B an entity of its own, since it just constitutes part of A's state and has no "life" of its own. Besides, if you aren't careful, you'll quickly end up with stack overflows if you let both classes instantiate their own dependencies.

    Secondly, this kind of approach quickly opens up a can of inconsistency worms. When you pass this in a constructor, you are passing an incomplete object to the constructor or method of another class. The purpose of a constructor is to instantiate an object so that after instantiation, it is a complete and valid object of the given class. This is not the case when you pass this inside the constructor, and it leaves your object in an inconsistent state that may lead to unexpected behavior. Consider this extended example:
    Code:java
    1. public class A {
    2. private final B b;
    3. private final String x;
    4.  
    5. public A(String x) {
    6. this.b = new B(this);
    7. this.x = x;
    8. }
    9.  
    10. public String getX() {
    11. return x;
    12. }
    13. }
    14.  
    15. public class B {
    16. private final A a;
    17. private final String y;
    18.  
    19. public B(A a) {
    20. this.a = a;
    21. this.y = a.getX();
    22. }
    23. }

    What is the value of B.y when A has been constructed? Indeed, the guarantees of the final keyword completely disappear (very bad if you're trying to write an immutable class) unless the sequence of statements in A's constructor are ordered carefully with respect to B - something that may not actually be viable. The trouble doesn't stop here, though. Here's a pretty good write-up that covers some potential issues (check out the Don't pass the "this" reference during construction section).

    While Builder is a very nice pattern, especially for constructing Composite pattern objects (think tree structures like the ones found in e.g. XML and YAML files), its intent is not to solve the circular dependency problem, and indeed may not be able to "on its own". Builder is essentially just a way to loosen the construction process for a single object via multiple setters or adders, so in the case of the circular dependency problem, it's just an overcomplicated way to implement setter injection. Another way to deal with constructor bloat is Abstract Factory, but it also doesn't solve the circular dependency problem.
     
    AdamQpzm likes this.
Thread Status:
Not open for further replies.

Share This Page