Is it a bad practice to have a class that requires a reference to an instance of an object?

I saw this in code for someone and thought it was an elegant way to solve this particular problem, but it probably violates the good OO principles in an epic way.

In the constructor for a set of classes, all of which are derived from a common base class, it requires a reference to the instancing class that must be passed. For example, photos Foo Foo_i = new (this);

Then, later, Foo will call methods in the instancing class to get information about itself and other objects contained in the instancing class.

On the one hand, this simplifies TON code, which models a 5-layer tree structure in equipment (agents connect to ports on several switches, etc.). On the other hand, these objects are pretty closely related to each other in a way that seems pretty wrong, but I don't know enough about OOA & D to lay my finger on it.

So, is everything all right? Or is it the OO equivalent for the goto statement?

+4
source share
5 answers

I try to avoid this if I can only in terms of hiding information. The less information a class has, the easier it is to check and verify it. However, in some cases this leads to more elegant solutions, so if you do not do this, it is terribly confusing, which is associated with a huge number of parameters passed, and, in any case, for this.

Java, for example, uses this a lot with inner classes:

public class Outer { private class Inner { public Inner() { // has access to the members of Outer for the instance that instantiated it } } } 
+2
source

You try to avoid reciprocal links (especially when holding back containment), but often they cannot be avoided. That is, parenting with children - children often need to know the parent and notify about it if some events occur. If you really need to do this, select the interfaces (or abstract classes in the case of C ++). Thus, you implement the class in order to implement some interface, and the instanciated class needs to know it only as an interface - this will significantly reduce coupling. In some respects, this approach is similar to the nested class of the listener, since it provides only part of the class, but it is easier to maintain. Here is a C # example:

 interface IParent { //some methods here } class Child { // child will know parent (instancing class) as interface only private readonly IParent parent_; public Child(IParent parent) { parent_ = parent; } } class Parent : IParent { // IParent implementation and other methods here } 
+5
source

This seems to violate the Law of Demeter , depending on how much Foo you need to know to fish in the instancing class. Objects should preferably be loosely coupled. You would not want one class to know much about the structure of another class. One example that I have heard several times is that you did not transfer your wallet to the store clerk and did not allow him to fish inside. Your wallet is your business, and you will find what you need to give the clerk and pass it on to yourself. You can reorganize your wallet and nobody will become wiser. Looser connection makes testing easy. Ideally, Foo should be tested without having to maintain a complex context.

+2
source

In Java, I remember how to avoid this once by subclassing some Listeners and Adapters in my controller and adding these listeners and adapters to my subclasses.

In other words, my controller was

 class p { private member x private methods private class q { // methods referencing p private members and methods } x.setListener(new q()); } 

I think this is more loosely coupled, but I also need some confirmation.

+1
source

This design pattern can make a lot of sense in some situations. For example, iterators are always associated with a particular collection, so it makes sense for the iterator constructor to require collection.

You have not provided a concrete example, but if the class reminds you of goto , this is probably a bad idea.

You said that the new object should request an instance of the object for information. Perhaps the class makes too many assumptions about its environment? If these assumptions complicate unit testing, debugging, or (not hypothetical) code reuse, you should consider refactoring.

But if the design saves development time in general, and you do not expect that it will not reach maturity within two years, the practice will be completely acceptable from a practical point of view.

+1
source

All Articles