Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am familiar with immutability and can design immutable classes, but I have mostly academic knowledge and lacking hands on experience
Please refer to the linked image above (not allowed to embed yet)
Looking at it from the bottom up
Student needs a new address
Instead of really changing student, we create a new student which incorporates the new address
The mutator method returns this new object
Question: What do do with this new object, presuming the mutator call came from an immutable object?
The new student can't be saved in Lecture, because Lecture is immutable as well
So we need a new Lecture as well, which incorporates the new Student
But where to save the new Lecture?
In a new Semester, of course, but where does it end?
The chain can be broken at least, by using the component facade pattern, which handles the creation of all the new objects, without having to forward the call through the whole chain
Question: Where does this stop? Doesn't there have to be a mutable object somewhere to at least save the topmost instance?
This is the idea of functional programming. Everything is immutable, no function call is allowed to have side-effects. The only way to mutate complex objects, like in your example, is to re-create the parent objects.
Now the question is how to alter the program state. Therefore, we first think about the stack. It contains the values of all local variables as well as the value of all parameters to the called functions. We can create new values by calling new functions. We can discard values by returning from a function. Thus, we can mutate the program state by calling functions. However, it is not always possible to return from the function to discard its local variables, because we might want to only discard some of the local variables, but need to keep the value of others for further operations. In this case, we simply cannot return, but we need to call another function and pass only some of the local variables to it. Now, to prevent a stack overflow, functional languages have a feature which is called tail call optimization, which is able to remove unnecessary entries from the call stack. An entry of the call stack is unnecessary if the only thing that is left to do for the associated function is to return the value of the function that was called by itself. In this case, there is no point in keeping the call stack entry. By removing the unnecessary call stack entry, the values of the otherwise unused local variables is discarded. You might want to read about it here. Also, tail recursion is related to this.
Again, this is the idea of purely functional programming languages like Haskell. It is really nice that everything is immutable, however these languages have their only issues and their own ways to handle these. For example, Monads (and therefore higher kinded types) are available in these languages, but are rarely seen in imperative/object oriented programming languages.
I like to have immutable values at the leaves of my program memory. However, the code to compose these immutable values, which actually forms the application logic does contain mutable state. For me, this combines the advantages of both worlds. However, this seems to be a matter of preference.
With your existing structure this would be quite difficult, and this is probably what you are supposed to learn with this exercise.
I would remove all relationships between the objects from the objects and implement those relationships using Map and Set.
Something like this would be a good starting point.
// Make sure all objects can be uniquely identified.
interface Id {
public Long getId();
}
class HasId implements Id {
private final Long id;
// Normal constructor.
public HasId(Long id) {
this.id = id;
}
// Copy constructor.
public HasId(HasId copyFrom) {
this(copyFrom.id);
}
#Override
public Long getId() {
return id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HasId hasId = (HasId) o;
return Objects.equals(id, hasId.id);
}
#Override
public int hashCode() {
return Objects.hash(id);
}
}
class Semester extends HasId {
public Semester(Long id) {
super(id);
}
public Semester(Semester copyFrom) {
super(copyFrom);
// TODO: Copy all the other fields of Semester to mine.
}
// Do NOT hold a list of Lectures for this semester.
}
class Lecture extends HasId {
// ...
// Do NOT hold a list of Students for this lecture.
}
class Student extends HasId {
// ...
}
// Core structures.
Map<Id, List<Lecture>> semesters = new HashMap<>();
Map<Id, List<Student>> lectures = new HashMap<>();
Set<Id> students = new HashSet<>();
// Utility structures that need to be maintained.
Map<Id, Lecture> studentsInLecture = new HashMap<>();
Map<Id, Semester> lecturesInSemester = new HashMap<>();
In this way you can isolate the objects and keep them immutable but if you do need to change any student's details you can clone the original student and steal it's identity.
This is clearly not a complete solution yet but I hope the concept I am trying to suggest is clear.
Related
This question already has answers here:
How shall we write get method, so that private fields don't escape their intended scope? [duplicate]
(2 answers)
Closed 3 years ago.
In Java Concurrency in Practice chapter # 3 author has suggested not to share the mutable state. Further he has added that below code is not a good way to share the states.
class UnsafeStates {
private String[] states = new String[] {
"AK", "AL"
};
public String[] getStates() {
return states;
}
}
From the book:
Publishing states in this way is problematic because any caller can modify its contents. In this case, the states array has escaped its intended scope, because what was supposed to be private state has been effectively made public.
My question here is: we often use getter and setters to access the class level private mutable variables. if it is not the correct way, what is the correct way to share the state? what is the proper way to encapsulate states ?
For primitive types, int, float etc, using a simple getter like this does not allow the caller to set its value:
someObj.getSomeInt() = 10; // error!
However, with an array, you could change its contents from the outside, which might be undesirable depending on the situation:
someObj.getSomeArray()[0] = newValue; // perfectly fine
This could lead to problems where a field is unexpectedly changed by other parts of code, causing hard-to-track bugs.
What you can do instead, is to return a copy of the array:
public String[] getStates() {
return Arrays.copyOf(states, states.length);
}
This way, even the caller changes the contents of the returned array, the array held by the object won't be affected.
With what you have it is possible for someone to change the content of your private array just through the getter itself:
public static void main(String[] args) {
UnsafeStates us = new UnsafeStates();
us.getStates()[0] = "VT";
System.out.println(Arrays.toString(us.getStates());
}
Output:
[VT, AR]
If you want to encapsulate your States and make it so they cannot change then it might be better to make an enum:
public enum SafeStates {
AR,
AL
}
Creating an enum gives a couple advantages. It allows exact vales that people can use. They can't be modified, its easy to test against and can easily do a switch statement on it. The only downfall for going with an enum is that the values have to be known ahead of time. I.E you code for it. Cannot be created at run time.
This question seems to be asked with respect to concurrency in particular.
Firstly, of course, there is the possibility of modifying non-primitive objects obtained via simple-minded getters; as others have pointed out, this is a risk even with single-threaded programs. The way to avoid this is to return a copy of an array, or an unmodifiable instance of a collection: see for example Collections.unmodifiableList.
However, for programs using concurrency, there is risk of returning the actual object (i.e., not a copy) even if the caller of the getter does not attempt to modify the returned object. Because of concurrent execution, the object could change "while he is looking at it", and in general this lack of synchronization could cause the program to malfunction.
It's difficult to turn the original getStates example into a convincing illustration of my point, but imagine a getter that returns a Map instead. Inside the owning object, correct synchronization may be implemented. However, a getTheMap method that returns just a reference to the Map is an invitation for the caller to call Map methods (even if just map.get) without synchronization.
There are basically two options to avoid the problem: (1) return a deep copy; an unmodifiable wrapper will not suffice in this case, and it should be a deep copy otherwise we just have the same problem one layer down, or (2) do not return unmediated references; instead, extend the method repertoire to provide exactly what is supportable, with correct internal synchronization.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I want to see an example of reaching directly into the code from a class that uses publicly declared data members to see an example of poor encapsulation so I can understand the good examples of encapsulation in OOP by contrasting with a bad example.(Being told to use encapsulation without a bad example is like being told not to steal without understanding what stealing is to me.) Thanks.
Suppose you have a Counter class that:
Starts with value = 0
Lets you increase the value by one (increment)
Lets you see the current value
A poorly-encapsulated version would directly expose the inner counter value:
class Counter {
public int value;
public Counter() {
this.value = 0;
}
public int increment() {
return ++this.value;
}
}
The problem, of course, is that users of the class can do this:
Counter c = new Counter();
System.out.println(c.value); // 0
c.increment();
System.out.println(c.value); // 1
c.value = 42;
System.out.println(c.value); // 42
Proper encapsulation corrects that:
class Counter {
private int value; // *** Private
public Counter() {
this.value = 0;
}
public int increment() {
return ++this.value;
}
public int getValue() { // *** Accessor
return this.value;
}
}
Now, there's no way¹ for the user of the class to directly set value.
Counter c = new Counter();
System.out.println(c.getValue()); // 0
c.increment();
System.out.println(c.getValue()); // 1
// No equivalent to `c.value = 42` is possible here¹
¹ (without using reflection)
Your question is a useful one, since understanding the reasons that encapsulation is important will help you avoid overgeneralizing the principle as well as help you understand when you've done it adequately.
You can find an example of poor encapsulation here: https://github.com/dotnet/training-tutorials/blob/master/content/csharp/getting-started/encapsulation-oop.md When the class in the example is used by other code to do something mundane, it create problems because the class hasn't been encapsulated. (Other examples might illustrate the problems that are created by poor encapsulation rather than a lack of encapsulation, but I understand you to want an example of the basic idea.)
Many times the problem that is created by not encapsulating your code is that properties and/or objects are updated or deleted when it is a copy of the object that you actually wish to update or delete.
Here are some relevant portions of the linked example. The first quote describes the problem that is created when the class lacks encapsulation:
Notice that in this example, the technique used to print the orders is a while loop that throws away each record as it prints it. This is an implementation detail, and if the collection this loop was working with were properly encapsulated, it wouldn't cause any issues. Unfortunately, even though a locally scoped orders variable is used to represent the collection, the calls to RemoveAt are actually removing records from the underlying Customer object. At the end of the program, both customers have 0 orders. This is not the intended behavior.
The second quote notes that the problem can be "solved" with a different implementation, but avoided altogether with encapsulation:
There are a variety of ways this can be addressed, the simplest of which is to change the while loop to a foreach, but the underlying problem is that Customer isn't encapsulating its Orders property in any way. Even if it didn't allow other classes to set the property, the List type it exposes is itself breaking encapsulation, and allowing collaborators to arbitrarily Remove or even Clear the contents of the collection.
What this example illustrates well is that the need for encapsulation isn't absolute, but it's most certainly a best practice.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am learning design pattern from Head first book and I understood most of them. But when I try to apply in real world, it becomes more difficult. In every example, it has created lot of sub classes. But do we really create so much classes in real time projects?
E.g. Consider an example of Bank Account
Approach 1:
Account {
String name;
double balance;
operation1() {
}
}
SavingAccount extends Account {
// some extra fields and methods related to saving account
operation1() {
}
}
CurrentAccount extends Account {
// Some extra fields and methods related to current account.
operation1() {
}
}
When I map these classes with database, using Hibernate using one of the inheritance strategy, e.g. table per sub class, I will end up with three tables. Account, Saving_account and Current_account.
Advantage: I can call operation1() depending on the type of object using polymorphism.
Disadvantage: more tables and classes. If project is more complex and big, It will end up with thousands of classes.
Approach 2:
Account {
string name;
double balance;
string type;
operation1() {
}
}
I need only 1 table for this approach called Account. And "type" field will identify the type of the account.
Advantage: Only 1 table and class.
Disadvantage: I will lose Object oriented world and every place I have to put the condition as below.
if (type == saving) {
// do this;
} else if (type == current) {
// do that;
}
As per theory, approach 1 is correct and best. But currently in my project, approach 2 is used. My project is not banking. I took it as an example for the simplicity.
I know this is very basic question. But due to my current project implementation, I could not stop myself asking this question.
EDIT: maintainability of approach 1 is more better than approach 2.
Design patterns like inheritance are difficult to describe in terms of their importance, because it takes a very large project to realize the power of it. Usually examples end up with stuff like:
class A {
}
class B extends A {
}
class C extends B {
}
class D extends A {
}
And then you get a lot of not so real life questions like which method foo() really refers to when it's implemented four separate times.
The motivation for using inheritance is to group similar types of things together in a class. A basic example is if you want to have a bunch of different objects all in a list together. This isn't possible if they're all different types, but if they're in an inheritance hierarchy, you can group them all together.
For your example, you can put every Account object into a single list, no matter which subclass the objects are really in.
List<Account> list = new ArrayList<Account> ();
list.add(new Account());
list.add(new SavingsAccount());
list.add(new CurrentAccount());
Say you want to process every thing in that list. If you have one common method, you can use polymorphism to make each Account do its own specific action:
for(Account a : list) {
a.operation1();
}
Much simpler than having a separate list for each type of object, no? And then if you want to make more types of accounts, if you extend the base Account class, you don't have to add new lists and new loops to your code. Everything can remain as is.
Using inheritance also helps to use code that other people have written. If you want to add something to a class that someone else has written, you can include it in a package and then extend it with one of your own classes. That way you don't have to do a lot of copy and pasting and navigating through the other class's source code. You also can extend another class even if you only have its .class file, rather than the source code in a .java file.
So the power of inheritance depends on how you use it. In a small example, it doesn't really make sense. But the bigger the project, the more it makes sense.
Both approaches are valid as you just mentioned and the pros and cons you explained are also valid.
But for example you if you are Giving this Accounting package (compiled jar) as a library to be extended by other people, the approach 1 is ideal because;
You don't need to modify any source code of Account, just extend it and then implement your own version. Ex:- FixedDepositAccount
Won't break your Account code.
No need of Testing again for Account.operation1()
But if you are willing to share the source code and willing to do above mentioned steps then it is best to use method 2.
In Java we can have String type; (not string type;), but even better would be an Enum type (that way we could have add a Money Market Account or a Platinum Preferred Savings Account, possibly without re-implementing the caller code). Something like,
enum AccountType {
CHECKING(0.005), SAVINGS(0.01), MMA(0.02);
final double rate;
private AccountType(double rate) {
this.rate = rate;
}
public double getRate() {
return this.rate;
}
}
And with an AccountType you can safely use == for equality, while doing if (type == saving) { with a String is asking for trouble. That is
if (type == AccountType.CHECKING) {
} else if (type == AccountType.SAVINGS) {
will function as you would expect. Finally, it would be better to try and avoid the if chains and instead encapsulate whatever you plan to do with the account type into the enum itself when you can. For example,
Account acct = getAccount(accountNumber);
if (acct != null && acct.isValid()) {
acct.balance += acct.balance * type.getRate();
}
Recently I have read some articles saying that methods having side effects is not good. So I just want to ask if my implementation here can be categorized as having side effect.
Suppose I have a SecurityGuard which checks to see if he should allow a customer to go to the club or not.
The SecurityGuard either has only list of validNames or list of invalidNames, not both.
if the SecurityGuard has only validNames, he only allows customer whose name on the list.
if the SecurityGuard has only invalidNames, he only allows customer whose name NOT on the list.
if the SecurityGuard has no lists at all, he allows everyone.
So to enforce the logic, on setter of each list, I reset the other list if the new list has value.
class SecurityGaurd {
private List<String> validNames = new ArrayList<>();
private List<String> invalidNames = new ArrayList<>();
public void setValidNames(List<String> newValidNames) {
this.validNames = new ArrayList<>(newValidNames);
// empty the invalidNames if newValidNames has values
if (!this.validNames.isEmpty()) {
this.invalidNames = new ArrayList<>();
}
}
public void setInvalidNames(List<String> newInvalidNames) {
this.invalidNames = new ArrayList<>(newInvalidNames);
// empty the validNames if newInvalidNames has values
if (!this.invalidNames.isEmpty()) {
this.validNames = new ArrayList<>(); //empty the validNames
}
}
public boolean allowCustomerToPass(String customerName) {
if (!validNames.isEmpty()) {
return validNames.contains(customerName);
}
return !invalidNames.contains(customerName);
}
}
So here you can see the setter methods have an implicit action, it resets the other list.
The question is what I'm doing here could be considered having a side effect? Is it bad enough so that we have to change it? And if yes, how can I improve this?
Thanks in advance.
Well, setters themselves have side effects (A value in that instance is left modified after the function ends). So, no, I wouldn't consider it something bad that needs to be changed.
Imagine that the guard just had one SetAdmissionPolicy which accepted a reference to an AdmissionPolicy defined:
interface AdmissionPolicy {
boolean isAcceptable(String customerName) {
}
and set the guard's admissionPolicy field to the passed-in reference. The guard's own allowCustomerToPass method simply called admissionPolicy.isAcceptable(customerName);.
Given the above definitions, one can imagine three classes that implement AdmissionPolicy: one would accept a list in its constructor, and isAcceptable would return true for everyone on the list, another would also accept a list in its constructor, but its isAcceptable would return true only for people not on the list. A third would simply return true unconditionally. If the club needs to close occasionally, one might also have a fourth implementation that returned false unconditionally.
Viewed in such a way, setInvalidNames and setValidNames could both be implemented as:
public void setAdmissionPolicyAdmitOnly(List<String> newValidNames) {
admissionPolicy = new AdmitOnlyPolicy(newValidNames);
}
public void setAdmissionPolicyAdmitAllBut(List<String> newInvalidNames) {
admissionPolicy = new AdmitAllButPolicy(newInvalidNames);
}
With such an implementation, it would be clear that each method was only "setting" one thing; such an implementation is how I would expect a class such as yours to behave.
The behavior of your class as described, however, I would regard as dubious at best. The issue isn't so much that adding admitted items clears out the rejected items, but rather that the behavior when a passed-in list is empty depends upon the earlier state in a rather bizarre fashion. It's hardly intuitive that if everyone but Fred is allowed access, calling setValidNames to nothing should have no effect, but if it's set to only allow George access that same call should grant access to everyone. Further, while it would not be unexpected that setValidNames would remove from invalidNames anyone who was included in the valid-names list nor vice versa, given the way the functions are named, the fact that setting one list removes everyone from the other list is somewhat unexpected (the different behavior with empty lists makes it especially so).
It does not have any side effect although , its assumed by developers that getters and setters may not have any underlying code apart from getting and setting the variable. Hence when another developer tries to maintain the code , he would probably overlook at your code of the Bean and do the same checks as done by you in the setters - Possible Boiler Plate code as you would call it
I'd not consider it as a side effect. You are maintaining the underlying assumptions of your object. I'm not sure it's the best design, but it's certainly a working one.
In this case I don't think changing the other linkedlist will be a side affect, since the scope is within this class.
However, based on your description, maybe it is better design to have one linkedList (called nameList) and a boolean (isValid) that differentiate between a whitelist and a blacklist. This way it is clear that only one type of list be filled at any time.
I think it's OK. E.g. if you want your class to be immutable the best place to do it is setter:
public void setNames(List<String> names) {
this.names = names == null ? Collections.emptyList() : Collections.unmodifiableList(names);
}
I have this class:
public MyClass {
public void initialize(Collection<String> data) {
this.data = data; // <-- Bad!
}
private Collection<String> data;
}
This is obviously bad style, because I'm introducing a shared mutable state. What's the preferred way to handle this?
Ignore it?
Clone the collection?
...?
EDIT: To clarify why this is bad, imagine this:
MyClass myObject = new MyClass();
List<String> data = new ArrayList<String>();
myObject.initialize(data); // myObject.data.size() == 0
data.add("Test"); // myObject.data.size() == 1
Just storing the reference poses a way to inject data into the private field myObject.data, although it should be completely private.
Depending on the nature of MyClass this could have serious impacts.
The best way is to deep clone the parameter. For performance reasons, this is usually not possible. On top of that, not all objects can be cloned, so deep copying might throw exceptions and cause all kinds of headache.
The next best way would be a "copy-on-write" clone. There is no support for this in the Java runtime.
If you think that it's possible someone mutates the collection, do a shallow copy using the copy constructor:
this.data = new HashSet<String> (data);
This will solve your problem (since String is immutable) but it will fail when the type in the set is mutable.
Another solution is to always make the sets immutable as soon as you store them somewhere:
Set<String> set = ...
...build the set...
// Freeze the set
set = Collections.unmodifiableSet(set);
// Now you can safely pass it elsewhere
obj.setData (set);
The idea here is turn collections into "value objects" as soon as possible. Anyone who wants to change the collection must copy it, change it and then save it back.
Within a class, you can keep the set mutable and wrap it in the getter (which you should do anyway).
Problems with this approach: Performance (but it's probably not as bad as you'd expect) and discipline (breaks if you forget it somewhere).
Null check (if you want to restrict null)
Either defensive copy (if you don't want shared state)
or as you did (if a live view on data is useful)
Depends heavily on your requirements.
Edited:
Ignoring should be no option. Silent fail is, well... a debugging nightmare.
public class Foo {
private final Collection collection = new ArrayList();
public void initialise(final Collection collection) {
this.collection.addAll(collection);
}
}
Sorry for not addressing your concern directly, but I would never directly pass a Collection to a setXxx() bean setter method. Instead, I would do:
private final List<MyClass> theList;
public void addXxx(MyClass item) { ... }
public void removeXxx(MyClass item) { ... } // or index.
public void Iterator<MyClass> iterateXxx() {
return Collections.unmodifiableList(theList).iterator();
}
I would go for defensive copying / deep cloning only if I am sure there would be no side effects from using it, and as for the speed, I wouldn't concern myself with it, since in business applications reliability has 10 times more priority than speed. ;-)
An idea will be to pass the data as a String array and create the Set inside MyClass. Of course MyClass should test that the input data is valid. I believe that this is a good practice anyway.
If both the caller of MyClass and MyClass itself actually work with a Set<String>, then you could consider cloning the collection. The Set however needs to be constructed somehow. I would prefer to move this responsibility to MyClass.