1

I have been developing my skills at creating large object orientated programs (30+ classes). I am trying to make my code as clean as possible after reading a fantastic book called clean code. One problem I am having is to do with calling a method on an object from "across the program"

Say I have 5 classes. `ClassA ClassB ClassC ClassD ClassE`

an instance of ClassA contains an instance of ClassB, which in turn contains an instance of classC, so

`ClassA > ClassB > ClassC`

I'm not saying that this is the inheritance chain, rather that in the constructor of classA an instance of ClassB is created and so on.

Now, say that ClassD > ClassE in a similar way. ClassD is instansiated with an instance variable containing an instance of ClassE.

This is all well and good, and the classes are small and only handle one job, and it all seems nice and clean.

However, say that at some point in the program I need the instance of classC to call a method on the instance of ClassE. The two objects are on 'opposite sides of the program' so to speak. Yet the method call is necessary.

I am left with three options as I see it

  1. make the instance of classE a global variable, so that classD AND classC can access it (as well as anything else in the program). I feel like this is bad form as global variables are generally considered bad news
  2. Create the instance of ClassE at the top level, then pass it in as an argument to the constructors of ClassA, ClassB, and ClassC. The trouble with this is that I would end up with really long constructor argument lists if this is happening more than once, and it seems like lots of work to pass ojects down chains of constructors like this
  3. Move the object of ClassE to be instantiated by ClassC. The trouble with that is that its more strongly coupled with ClassD and only needs to be called once in the entire running of the program by ClassC.

So what do I do in situations such as these? And are there any resources I can read about this. I know that I could use the observer pattern for situations similar to this, but when its just for one method call it seems excessive, as I would be making things observable all over the program. I want my code as clean as possible!

Thanks in advance :)

Community
  • 1
  • 1
Circuit 8
  • 479
  • 6
  • 20

2 Answers2

2

Three words: Single Responsibility Principle. If you worry that your class has too many constructor arguments it's probably because this class needs to deal with too many different things. If you keep classes focused, they will be small.

You correctly indicate the coupling problem in the third solution you've described. The coupling problem is also present in the first solution (depending on a global variable is even harder to find/diagnose later). So the second option seems to be the best - as long as you refactor the code to keep your classes simple.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
1

You could read up on Law of Demeter (Short explanation on wikipedia: http://en.wikipedia.org/wiki/Law_of_Demeter or a longer but very well written example http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf)

  • Depending on the context / content of your example you could for instance: Build your Class D as a wrapper to your class E (or similar facade / adapter). Meaning if your class c sometimes needs to talk to an E instance it does so via it's class D instance.
  • Another way to go would be to provide a reference to a class E instance to those objects that need one.
  • If all your objects are talking to the same instance of E you could also think about the singleton pattern where there is only one instance of a class. But this instance is more or less globally available.

Give a bit more context info and we can develop this further.

EDIT: btw. a funny explanation of lad of demeter can be found here: http://www.daedtech.com/visualization-mnemonics-for-software-principles


EDIT Nr.2 (your comment): ad. 1.) Maybe you can implement your class D in a way that reliefs your other classes of ever talking directly to an E object. Instead they ask their D instance to do something (not knowing that D delegates the call to E). Depending on what you are trying to do this might be an option for you.
ad. Singleton.) Yes and No. The Singleton main use is that it guarantees (if implemented correctly) that only one instance of the singleton object exists. If you are talking about config settings this might not be a requirement. You are right however that basically the thing is kind of a global variable with all it's downsides. Your object D sounds as if it's immutable in a sense that it does not change it's state while your program is running so maybe the problem is not that you create a complex dynamic behaviour but that you create too many dependencies.
Just another link/principle to get you thinking: What is Inversion of Control?

Community
  • 1
  • 1
markus
  • 1,631
  • 2
  • 17
  • 31
  • Thanks for the reply. What do you mean by build class D as a wrapper to class E? Is that where by it has methods which call the methods in class E? The singleton pattern looks like it fits the bill perfectly, although isnt this pattern just a dressed up way of having global variables? Class D is a graphics settings class and class E deals with a certain part of the graphics. Many classes need to use class D and E. Thanks for the funny explanations, they actually illustrate the concepts very clearly! – Circuit 8 Dec 01 '14 at 16:01
  • Ok thanks that all makes sense. The class D gets itself up and running but once the program is going doesnt really do anything other than serve its information to everyone. Inversion of control looks like it could help but I'll need to read more about it. Thanks for the link and your help – Circuit 8 Dec 01 '14 at 16:53