The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Program design question

I have a value originally calculated in main(), call it $profit.  $profit is used in c, which is called by b, which is called by a, which is called by main.  So basically:

main()
{
  $profit = 5;

  a($profit);
}

a($profit)
{
  b($profit);
}

b($profit)
{
  c($profit);
}

c($profit)
  print($profit);
}

Of course the above is contrived, but my situation is very similar to the above.  The problem with the above is it is very... ugly.  $profit isn't used in a or b at ALL, just to pass along.

So two questions:

1) Is there a name for this kind of variable or practice?

2) Are there any known techniques for avoiding it by design in the first place, or solving it now that it's cropped up?  Without global variables?

Thanks in advance.
Dan Hulton Send private email
Friday, January 21, 2005
 
 
Yes, it's called a data member ;-) $profit should be a data member of a class that has b, c, d, etc., as function methods.

Use the OOP facilities of your language.

Silly Me
Silly Me
Friday, January 21, 2005
 
 
Isn't this the problem that the Law of Demeter addresses?

http://c2.com/cgi/wiki?LawOfDemeter
Yet another anon
Friday, January 21, 2005
 
 
Maybe it should be a data member, or maybe it makes sense to pass the value between three different functions.  Nothing in the example indicates that it ought to be a data member, and in fact introducing state by member variable assignment actually makes the model of your program more complicated.  Is it possible to decouple the three functions?  Does it make sense to integrate the three functions into a single function?
Kalani Send private email
Friday, January 21, 2005
 
 
Probably not, Kalani.

Put more specific to my problem, it's a PHP script.

In the script itself, I call a routine to calculate the maximum number of pages in a query, for "Showing page 1 of 50" type functions.

I pass this number to view_list(), which includes a template file that uses this value.  But view_list never uses this value, it only passes it along.

(The templating I do is based off the article here: http://www.sitepoint.com/print/beyond-template-engine .  Very powerful and simple.)

I've cleaned up a little since I posted (removed an extraneous call), but it's still being passed through view_list without use.

Maybe I'm over-reacting, but it seems really inelegant.  And usually when something seems overtly inelegant, that's because there's an underlying design descision that is incorrect.  In this case, it may just be a situation of conflicting priorities (easy, simple, powerful templates vs. passing variables oddly).
Dan Hulton Send private email
Friday, January 21, 2005
 
 
If you have a several related variables, you can combine them into a object (if you're doing OOP) or some other structure (otherwise). That way, you can pass fewer variables around.

Going to extremes, you can define a context object, a structure that contains references to the data items you'll need throughout your code. Many of your functions then take the context object as an input argument. Context objects have their problems, described in http://c2.com/cgi/wiki?ContextObjectsAreEvil , but they're often the easiest way to deal with large numbers of variables in a large code base.
Julian
Saturday, January 22, 2005
 
 
I believe what you are doing is a form of dependency injection (otherwise known as inversion of control).  The alternative to this is a service locator, where you would reference "services" through a central repository and remove the coupling of your methods to objects.  Here is a good article that covers these concepts (Concepts are in Java, but can apply to PHP too):
http://www.martinfowler.com/articles/injection.html

Essentially, I think an alternative solution for you would be to have your templating object stored as a service somewhere in the system.  Any method/class can access it independently.  So, one method can apply the template variable values.  The other could just tell the template object to display itself.

Here is some pseudo php 4 code of its use:

class ServiceLocator() {
  function getTemplateObject() {
    static $tmplObj;
      if (!isset($tmplObj)) {
        $tmplObj = new YourTmplObj();
      }
      return $tmplObj;   
  }
}

Then, whenever you want to access the object you would say something like:

$tmplObj =& ServiceLocator::getTemplateObject();
 // add variables... or display it or whatever

---Tom
Tom Davies Send private email
Saturday, January 22, 2005
 
 
The DeMarco / Yourdon / Data Flow Diagram / Structure Chart answer to this would have several pieces.

1.  If module C really does have need of this, and module B really must be called in the middle, then yes, pass the parameter, even if the only use B makes of it is to pass it on.

2.  In 'normal' C, the variable would have been made a global.  This is NOT a good thing.  The same concern you have would exist, but it would be MUCH harder to determine it was happening from the code.

3.  It is possible to define a data structure, which has this value in it, along with other stuff that IS used by 'B'.  Then you're only passing one parameter.  This is a less desirable form of Coupling, but can prevent long strings of 'useless' parameters in your call to B.
AllanL5
Saturday, January 22, 2005
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz