Passing object references is useless through an intermediary

It often seems to me that I need a reference to an object that is in multiple objects, or as it seems. The parameters I see are passing the link through an intermediary or just making something statically available. I understand the danger of a global scale, but passing the reference through an object that does nothing with it seems ridiculous. I guess I'm okay, get around a little. I suspect there will be a line of some kind.

Does anyone have any idea where to draw this line?

Or is it a good way to deal with the problem of propagating references between dependent objects?

+2


source to share


5 answers


Use the Law of Demeter (with moderation and good taste, not dogmatically). If you are coding a.b.c.d.e

something is wrong - you are forever imposing on the implementation a

on b

which has c

which ... EEP! -) One or no more than two points is the maximum you should use. But the alternative is NOT to push everything onto globals (and provide unsafe, unsafe, bad, hard-to-maintain code!) So that each object "covers" the characteristics that it is intended to support as part of the interface clients go forward, rather than just allowing poor clients go through such irregular chains of nested links!



+3


source


It smells like an abstraction that might need some improvement. You seem to be breaking the Law of Demeter.



+1


source


In some cases, the global is not so bad.

Note that you are probably programming against an operating system API. Full globals, you can probably access file or registry, write to console. Look at the window handle. You can do a lot of things to access state that is global across the entire computer or even over the Internet ... and you don't need to pass a separate reference to your class to access it. All of these materials are global if you refer to the OS API.

So, when you consider the amount of global things that often exist, the global in your own program is probably not as bad as many people are trying to figure out and shout about.

However, if you want to have very good OO code that is fully verifiable, I suppose you should write wrapper classes around any access to global variables, whether they come from the OS or are self-declared to encapsulate them. This means that a class that uses this global state can get references to wrappers and they can be replaced with fakes.

Hmm, anyway. I'm not really sure what advice I'm trying to give here, other than to say structuring code is balance! And how to do it for your specific problem depends on your preference, the preference of the people who will be using the code, how you feel on an academic day on a pragmatic scale, how big the code base is, how important is the security of the system, and how far from the deadline. ...

+1


source


I believe your question is showing something about your classes. Maybe the responsibilities can be improved? Perhaps some code can solve the problems?


Tell me, don't ask.

Here's how they explained it to me. There is a natural tendency to call classes to get some data. Taken too far, asking too much usually leads to heavy "getter sequences". But there is another way. I have to admit that this is not easy to find, but it gradually improves in specific code and in the habits of the coder.

Class A wants to do the calculation and asks B's data. Sometimes, it is appropriate that A tells B to do the job, perhaps passing some parameters. This could replace B "getName ()" used by A to validate a name with the isValid () method to B. "Asking" has been replaced by "tell" (a call to the method that performs the computation).

For me, this is the question I ask myself when I find too many getter calls . Gradually, the methods collide with their place in the correct object, and everything becomes a little easier, I have fewer getters and less their names. I have less code and it provides more semantics, aligns better with the functional requirement.


Move data around

There are other cases where I move some data. For example, if a field moves two objects up, the length of the "getter chain" is reduced by two.

I believe that at first no one can find the correct model. I think about it first (using handwritten diagrams quickly and with a lot of help), then code it and then think about the real thing again ... Then I code the rest and any smells I smell in the code I think again. ..


Split and combine objects

If method A needs data from C and B needs an average person, I can try if A and C have a common. Maybe A or part A could become C (possible splitting of A, merging of A and C) ...


However, there are cases where I keep getters of course. But it is less likely that a long chain will be created. A long chain will likely be broken by one of the methods above .

+1


source


I have three templates for this:

  • Pass in the required reference to the object's constructor - the master can then be stored as an object data item and does not need to be passed again; this means that the factory object has the required reference. For example, when I create a DOM, I pass in the name of the DOM node when I create a DOM node.

  • Let everyone remember their parent and get property references through their parent; this means that the parent or ancestor has the required property. For example, when I create the DOM, there are various things that are stored as properties of the top level ancestor of the DomDocument, and its child nodes can access these properties through a reference that everyone has for their parent.

  • Put all the different things that are passed as references into one class, and then only pass one instance of the class as the only one that passed. For example, there are many properties needed to render the DOM (like GDI graphics descriptor, viewport coordinates, callback events, etc.) ... I put all of these things in one instance "Context" which is passed as a parameter for methods of the generated DOM nodes, and each method can get any properties it needs from this context parameter.

0


source







All Articles