• Post Reply Bookmark Topic Watch Topic
  • New Topic

difference between changing the String after putting in Set or changing Set in Object  RSS feed

 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
example-

if you see its output, you will not see str changes.


but if you do this way, you can see the changes in set values but not in String value. well one reason that comes into my mind is String is immutable whereas Set is mutable. So in my production changes also i followed the below steps.

Is it a kind of risky thing to do or pretty safe to do this ?



 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Amandeep Singh wrote:example-
Is it a kind of risky thing to do or pretty safe to do this ?

It is risky, but it is acceptable in some cases. It is risky because the ContData doesn't have full control of its internal state, hence won't be able to ensure that its operations are consistent. So in the perfect world, such problem should not exist, however, sometime it is too expensive to implement otherwise, you just have to deal with it, just need to be aware of the problem.

Anyway, after some refactoring your ContData can be something like


So that if you want to initialise an instance of ContData, it should be something like
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
well if you look this code-



it is no different than your's except ContData.

I think as long as you see the results good in output. the possibility of riskiness should be ruled out. And my this code is in Production, it is working without the issues.
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It will only be a problem if you have to debug mysterious issue later on i.e.
you change the set and the internal state of contData change without its notice.



Ah by the way, this
So that if you want to initialise an instance of ContData, it should be something like

Should read
If you change the set outside contData, it doesn't change the internal state of contData

 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Duc Vo wrote:
So that if you want to initialise an instance of ContData, it should be something like

Should read
If you change the set outside contData, it doesn't change the internal state of contData



i don't agree with this point. if we change the internal state it is definitely reflected. could you somehow can give me a scenario where it doesn't works..
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Amandeep Singh wrote:
i don't agree with this point. if we change the internal state it is definitely reflected. could you somehow can give me a scenario where it doesn't works..

Didn't you try my example above?

With your version of ContData, if I add another item to the set after initialising contData object, then the item is added into internal set of contData without its notice. And it doesn't happen to my version of ContData.

In the above example, your output at line 5 will be [hello] and after changing the set at line 8, the output at line 11 is now [hello, world]. Which means the internal state of object contData has been changed without using its own operation, it actually violates the Encapsulation principle of OOD.

In my example in the second post, the output at line 7 is [hello] and even if I changed the set at line 9 the output at line 12 is still [hello].
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

In the above example, your output at line 5 will be [hello] and after changing the set at line 8, the output at line 11 is now [hello, world]. Which means the internal state of object contData has been changed without using its own operation, it actually violates the Encapsulation principle of OOD.


this is what i actually want. I am asking is this thing guaranteed to work always ? Let me know as it is an urgent issue. what is working in above quote is what i need always to work.
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think if you only run them in the same JVM, it should always work.

But it's not a good practice, and potentially will create more problems later on say a year from now and/or when other developers inherit the project.
Should you let the contData object handle the change instead?
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
even if ContData want to handle the situation. it will be eventually end up in same situation.

the only way issue resolve is-



can be changed to




do you think the above code changes does it really makes difference?
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No that change doesn't make any difference. The problem isn't with the client code, the problem is with the implementation of ContData. If later on in the code the set variable is used for different purpose, the contData object will not have control of its state. The ContData should have method to add an item or collection of items, it should also provide a way to iterate through the items if the client code is required, also it should not return a reference to the set (its internal state). Recheck my implementation of the ContData in the second post.
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
oh i understand your point, you want to make the Set localized to ContData. So nobody can change it without the intent of ContData.
but the way i did is just made the Set outside the ContData. So that it can be shared outside also.

do you think there can be issues in my code, if yes which scenario ?

I just treated ContData as a placeholder of set.
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Amandeep,

I did mention that there may be side effect problem and I did give example in previous posts.
Normally it should work, but if you have mysterious issue like getSet() method of ContData returns inconsistent data time to time, be aware that any one who got a hold on the set reference of ContData can change the set. If it only happen on few places in your project, then it should be managable. If it happens almost to all your objects, you should consider refactor your code base.

Hope it help,

 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
well, i change the set only at one place as same as in my examples. but to get the set value, i do it at various places.
Does any one agree to this, for this particular scenario i mentioned it can give rise to problems. So far my tests are working great.
does that mean still i haven't discovered the issue.

Experts Help is appreciated!
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Duc Vo wrote:Normally it should work, but if you have mysterious issue like getSet() method of ContData returns inconsistent data time to time, be aware that any one who got a hold on the set reference of ContData can change the set.

That's where the unmodifiable wrapper methods in java.util.Collections come in:
Note how my iterator() method uses the unmodifiable set returned by getSet(). That's because Iterator has a nasty method called remove() - which allows foreign code to remove elements from your set if you return set.iterator() directly!
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In my case, there is no method which is going to remove from the Set.
but with the situation i am fighting is -


but the way i did is just made the Set outside the ContData. So that it can be shared outside also. So the code outside the ContData can change the value of Set.

but the way Duc is saying- make Set localized to ContData. So nobody can change it without the intent of ContData.

Even i agree with Duc approach. but is my approach wrong. I tested my code, it works well. if you want complete posting of the code let me know. above code are just snapshots. As my code will go into production, please advise if it needs immediate intention.



Expert advice would be appreciated as per my problem...
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your code is only as flawed as the code that uses it. If in your application, there is no code at all that modifies the set - no problem. But if anybody (perhaps you in the future) decides to use that class in another project, and doesn't know the contents are shared (or willingly (ab)uses this fact), your code may not work as that person expected.
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks Rob. can you suggest some changes in my code ASAP.
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well in real world i do have, more than 1 set types like this-



and the code use to above code is-


but i am unable to achieve the desired results. Still without the intent of ContData1, the user can changes the value of set.
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you don't want the sets edited outside your class, you will have to follow the combined techniques Duc Vo and I have shown you: copy the set in the constructor, and return an unmodifiable set wrapper:
Note that I also changed the Javadoc of the get method to inform users that they can't add anything to the returned set.

 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob has said it all. Just one minor point, if you create those empty HashSet just to create Cont1Data object, you may want to let Cont1Data to create them as well. So the clients of Cont1Data don't need to know how Cont1Data store the data.
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So my final code is -




this looks good, before further to promote my changes into Production. Is there any other discrepancy ?
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
All your setSet methods should rename to addAllSet methods, since they don't adhere to the standard of Java bean contract, hence they will mislead other developers and even you after sometime. If you insist to have the setSet methods, then you should have both methods and they should look like below



Then your client code should use the second method if required to append to the existing set.
If you want to replace the existing set with a new set then the first method should be used.


 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
when i need to add Strings to existing Set, then instead of making a String and make into Set then adding, i prefered this way of doing-


 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perfect, now you got the hang of it
 
Amandeep Singh
Ranch Hand
Posts: 853
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thank you for your help..
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!