2 Replies - 1141 Views - Last Post: 01 April 2019 - 05:11 PM Rate Topic: -----

#1 NantucketSleighride   User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 119
  • Joined: 13-February 11

Passing parameters several layers deep?

Posted 31 March 2019 - 05:28 PM

I have another question! I didn't think it appropriate to put these both in the same post because they're too different and it would be muddled. This way it's more useful is someone else is looking for the same thing!

The idea of encapsulation frustrates me... I've read a lot of stuff saying it's unnecessary and that careful coding is all you need. But I still try to stick with properties and private variables because the other half says to. Who knows which way is better. I sure as heck don't.

I'm curious, though, how do you deal with passing parameters when methods may go several layers deep, or if those previous methods don't need that data?

For instance - let's say I have a player object. He's in my main Game object... Now I call some sort of method that maybe calls another method, and then that calls a last method... And that last one maybe affects the player somehow, whereas the others don't. Do I just pass all of those other methods the player object because it may lead to one of the chains needing one? It feels wrong to me, and makes me think there is something that I just don't know yet about how to handle data properly. I feel like that last method should somehow have its own way of accessing that player object without the other methods all having to pass it along when it may be completely unnecessary in the end for them to ever have it.

I don't have a specific example of code here - it's more of an organization/theoretical question, I suppose.

Is This A Good Question/Topic? 0
  • +

Replies To: Passing parameters several layers deep?

#2 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 6913
  • View blog
  • Posts: 23,505
  • Joined: 05-May 12

Re: Passing parameters several layers deep?

Posted 31 March 2019 - 05:40 PM

First, it sounds like you are asking the right questions and now is the right time to read on the Law of Demeter as explained by David Bock: The Paperboy, the Wallet, and the Law of Demeter

Second, on a practical level, as tempting as it will be to implement the Service Locator pattern to avoid having to pass all that information around all the time, or to implement the Singleton pattern for various types of objects, take a step back. Both the Service Locator and Single patterns have been shown to be anti-patterns that actually make your code harder to understand, test, and debug.

In your specific example, about your main Game object needing to all a method, and that method needs to call another, and than eventually gets to a method that needs a Player, my code smell sensor is telling me that your main Game class is too "wide" and knows to much, or is holding too many methods. You'll likely need to break up the class into smaller classes. When you construct instances of those smaller classes, you use dependency injection to pass in the things that will be needed by methods in those smaller classes.
Was This Post Helpful? 4
  • +
  • -

#3 Martyr2   User is online

  • Programming Theoretician
  • member icon

Reputation: 5413
  • View blog
  • Posts: 14,320
  • Joined: 18-April 07

Re: Passing parameters several layers deep?

Posted 01 April 2019 - 05:11 PM

Steve McConnell in his book Code Complete 2nd Edition calls the passing down of data like that "tramp data" and specifically addresses it at the bottom of page 338 onto page 339.

What I will say is that sometimes tramp data is necessary but should be limited if not eliminated where possible. Ideally I find tramp data as a clear sign that perhaps your methods are doing too much. They are doing one task and then giving that data to another task that is perhaps related but not necessarily part of the first task. Maybe you are are running a procedure to update a user account. You want to pass in a logger to log that the update is complete. The update of the user account is one action that makes no use of the logger other than to pass it to another method. What you can do is take the logger and call that other method after the update user account has completed and returned.

main {
  Logger logger = new Logger();
  updateUser(id, logger);  <-- passing logger to be used to log update of user
}

updateUser(id, logger) {
   // Updates stuff
   logSomething("Update user hurray!", logger); <--- passing logger on to logSomething
}


// One possible solution...
main {
  Logger logger = new Logger();

  updateUser(id);
  logSomething("Update user hurray!", logger);
}



Now of course this may add some temporal dependency, but it it would be one way. Plus now you can create the logger and use it closer to where it is created which helps with readability and allows the programmer to see the correlation. It is not the job of updateUser to do the logging, it updates. LogSomething is its own task that can be possibly called from other method and you don't want to be hurling through that logger object as tramp data in all your methods. It may also confuse programmers because what does a logger have to do with updating a user? They won't know until they go see updateUser's implementation.

But anyways, just one idea. Steve covers a few others in his book. :)
Was This Post Helpful? 2
  • +
  • -

Page 1 of 1