• Post Reply Bookmark Topic Watch Topic
  • New Topic

Alternative to update passed arguments.  RSS feed

 
Brendon McCullum
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am writing a simple program in Java, where I call a method and pass some variables (namely, min and max) as arguments. This method is recursive, so the same arguments are again passed on in each recursive call.
I need to update these variables in recursive calls so that when the calling method uses them, it uses updated values. As it might sound confusing, here is sample code :



As you can see, min and max are updated after each recursive call returns, based on conditions. However, these changes aren't reflected in original min and max, which were used by func1 while calling func2. As far as
I know, this happens due to call by value mechanism being used by Java while passing arguments. If I declare min and max as instance variables in the class, my problem is solved. But, I want to know whether there's any other way to update these variables so that changes in original min and max are reflected. Yes, I can return them as an array of 2 elements each time while returning, but it didn't seem a good solution to me.
Any suggestions would be appreciated.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Brendon.

This is a really bad idea. Recursion can be hard enough as it is, without having to worry about the possibility of changing arguments. There's a good reason Java's developers chose not to allow passing values by reference.

you should strive to write functions without side effects. Instead, define a class that models the result of an intermediary recursive step. It could look something like this:
 
Brendon McCullum
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Stephen, thanks for your reply.

I have few doubts regarding this :
1. I don't think there is need for private constructor and setter and getter (as here, we are accessing only through outer class, so irrespective of access specifiers, it will have full access to inner class' members).
2. I don't understand the use for making class as static and final and also the need for making min and max as final. (As per the suggestion, I think what you're suggesting is to maintain a single instance of result class, and update it's min and max in calculate method, so making max and min as final would prevent updating them).

Finally, I have following piece of code (for vertical order traversal of a tree) :



I partially implemented your suggestions, but I have few doubts that I pointed above. Also, it would be really helpful if there's any more suggestions that could help improve the present code. Thanks.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can only answer your questions if I explain that you should favor immutable value types where possible. If you design classes so that they can't be changed, it becomes very easy to make correct assumptions about the data they contain, and thus easier to write correct code. If you design your Result class so that instances never change, you have a rock steady basis to build functions on top of. Wouldn't it be a hassle if a two could sometimes suddenly be a one?

Brendon McCullum wrote:1. I don't think there is need for private constructor and setter and getter (as here, we are accessing only through outer class, so irrespective of access specifiers, it will have full access to inner class' members).

The reason is that in your original question, you didn't specify where the data would be used. If you use the Result outside of your class, it doesn't make sense for the outside world to be able to create instances of Result. That's why the constructor is private. If the inner class is not used outside of the outer class, you can leave away the getter methods.

2. I don't understand the use for making class as static and final and also the need for making min and max as final.

The class is static, because it can live without the existence of the outer class. If you don't make inner classes static, instances 'belong' to the outer class. Now it's just like any other regular class, except that it lives within the namespace of the outer class. The class is final, because really... you don't need subclasses of it. It's a good habit to make your classes final, unless you specifically design them to have sub-classes (which is actually not very easy!). Also, don't make classes public just because it's a habit to write the public keyword. Most classes can be package private.

(As per the suggestion, I think what you're suggesting is to maintain a single instance of result class, and update it's min and max in calculate method, so making max and min as final would prevent updating them).

No. An instance of Result is a single immutable value that never changes. You build new Results using old Results, just like a function may return new numbers based on old numbers.

As for your code, I have the following suggestions:

- You do not have to explicitly null your left and right trees in the constructor. Use default values assigned to instance fields instead (false, null, 0).
- Your class VerticalLevelOrder is unnecessary. You can make the functions methods of a Tree. If you instead want a utility class that contains various operations on trees, call the class something like TreeOperations and give it a private constructor and make all the functions static.
- Use meaningful names. 'hd' is meaningless. Write out words rather than abbreviating them. 'map' is also meaningless. We can see it's a map. The name should reflect what it does.
- You are mixing code to determine the width and the height of a Tree. This is confusing and will most likely lead to bugs.
- Use results to create new results. Do it like this:


I hope it helps! I'm looking forward to see any changes.
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't think there is need for private constructor and setter and getter (as here, we are accessing only through outer class, so irrespective of access specifiers, it will have full access to inner class' members).


This is true, but its just general good practice to maintain abstraction between classes. If for example you wanted to refactor in the future and make Result a top-level class rather than a nested class then it would be easier to do if its members were suitably protected from outside interference. I will admit that I often forgo getters on nested classes an just access them directly though, when I'm confident that I will never want to refactor.

I don't understand the use for making class as static and final and also the need for making min and max as final. (As per the suggestion, I think what you're suggesting is to maintain a single instance of result class, and update it's min and max in calculate method, so making max and min as final would prevent updating them).


The code would certainly work without either the static or the final, but there are good reasons for them being there.

Neither making a nested class static nor final means that you can only have a single instance of that class. You can have as many instances as you want in either case. However there is a big difference between a static and a non-static nested class. If you don't make the nested class static then the actual class is a member of the outer class. Each instance of the outer class creates instances of the inner class that are specifically tied to it. The instances of the inner class have free access to the member variables of the outer class. However if the nested class is static then this is not the case. The instances of the nested class have no access to the member fields of instances of the outer class. If your nested class is not accessing member fields of the outer class then it should be marked static.

As for the final keyword, that is also good practice. Marking a class final prevents it being extended. Marking the fields of a class final means that they can only be written to once. The net effect of this is that your class is now immutable once instantiated, and this is a very good property for classes to have as it allows you to reason about the code more easily and helps prevents bugs. As a general rule you should make everything final unless you actively need it to be not final.
 
Brendon McCullum
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Stephen,

As per your suggestions, and what I understood , I have the following code:



I hope most parts have been corrected as per the suggestions. I'd appreciate any further inputs from your side. Thanks a lot.

@Mike, thanks for your insightful inputs.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good job Brendon!

I have a few more remarks:
- Properly document what your methods do. This is invaluable for the reader to understand why you're calling a method, and what they can expect to be returned.
- I used calculate() in my original skeleton, because I din't know what the point of the method was. You should probably give it a more descriptive name.
- Do not align inline comments. It's better to put them above whatever line you're annotating than next to them.
- I'm not exactly sure why your TreeOperations class contains a newTree() method, when you can directly call the constructor.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I gave this problem a crack myself, and this is what I would have written. The classes didn't necessarily have to be generic, but I like to exercise
Note especially the method headers. It should make it absolutely clear what is expected of a method, and the implementations should be self-documenting code.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Although I wouldn't emulate my way of constructing the binary tree in the main method. Your way is much more clear.
 
Brendon McCullum
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Stephen,

Thanks for your effort, and suggestions. I studied your code, and though it's quite clear and well documented, I have few remarks :

1. You're adjusting the indices and updating the maps on returning back from recursive calls, while as a beginner, I feel that it's easy to update the maps on the go if you pass on the map as an argument (I know it may cause bugs, as you suggested in your earlier post, but dealing with recursion gets a little simpler that way.) Maybe I'll learn the best way as I practice more.

2. Is there any programming book that you'd suggest for designing (Because the solution for this problem was same, but your approach is much more clear, mainly due to well documented code, and ensuring less bugs as you maintain separate copies of maps for each recursive calls and returning them back). It turns out there are hundreds of ways to design a solution that'd give the same complexity, but designing good, documented, bug free code separates them. Of course, experience matters, considering that I'm no Java expert, and that's why I seek help from you regarding this.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Brendon McCullum wrote:1. You're adjusting the indices and updating the maps on returning back from recursive calls, while as a beginner, I feel that it's easy to update the maps on the go if you pass on the map as an argument.

I think I usually do it like that because I design my class interface before I implement it. This also makes it easier for me to employ recursion, because I already know what my method is expected to do before I call it inside the method body. I think to myself, what do I want to return from a method that gives me the vertical lines of a tree? What do I need to provide to make that happen? If I don't need to pass anything to get the data I want, I generally don't design my methods that way.

2. Is there any programming book that you'd suggest for designing

I'm sorry, I have to admit I have read very few books on the topic of software design. The only book I ever recommend to people is Joshua Bloch's Effective Java, which I think is a must-read for any Java programmer, and maybe even everyone working with an Object Oriented language. Most of what I know is from endlessly browsing discussions and blogs on the internet.

It turns out there are hundreds of ways to design a solution that'd give the same complexity, but designing good, documented, bug free code separates them.

This is what I love about programming. If there was one true solution for every problem, programming would be very boring
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!