Sane pattern for immutable pojos and single field changes - java

Usually I'd love all my POJOs to be immutable (well, to contain only final fields as Java understands immutability). But with my current project, a constant pattern is that I need to change a single field from a POJO. Working with immutable POJO's in this scenario seems cumbersome.
How would you go about having POJO's with bunch of fields and for each field you should be able to say "please give me a copy of this POJO but with this one field changed"?
Big plus here would be something that I can use with composable Functions. "Start with this immutable pojo, then basically push it through bunch of UnaryOperators and give me back new immutable pojo".

Yes, that's a fairly common pattern - usually with a bunch of methods with a with prefix. Each with* method "changes" a single field, so you can have:
Person jon = new Person("Jon", "Skeet");
Person holly = jon.withFirstName("Holly"); // Holly Skeet
You can chain the calls together, too:
Person fred = jon.withAge(...).withFirstName("Fred").withJob(...);
Note that if you end up changing K fields in a POJO with N fields, you'll create K objects and need K * N assignments.
The implementation is usually just a matter of calling a big constructor with the existing field values and the new one:
public Person withFirstName(String newFirstName) {
return new Person(newFirstName, lastName, job, age, ...);
}
I've used the term "pseudo-mutator" for this kind of method - it's a method which sounds a bit like it's mutating something, but it's more like it's creating a clone, mutating the clone, then returning it to you in a "frozen" state.

Related

Java - store name field by using hashmap vs using seperate class

If I need to capture the name (first, middle and last) of a Person, I thought of the following possibilities:
Use a Map<String, String> name;
Use a separate Name class.
If I use a Map, I can store the names like this:
name.put("first", "xyz")
name.put("middle", "abc")
name.put("last", "nhf");
Then in the Person class:
class Person
{
Map<String, String> name;
//below write setter and getter for it.
}
If I use a Name class, I can store like this:
class Name
{
String first;
String middle;
String last;
//Below write setters and getters for them.
}
Then in the Person class:
class Person
{
Name name;
//below write setter and getter for it.
}
I wanted to know which one is a better way of doing and why. Also if there is any other better way of doing this.
Maps are great for flexibility. I.e., if you don't know exactly what keys you're going to have. E.g., if one person will have a Christian name, another will have a nickname and a third will have a paternal and maternal surnames, a Map may make sense. In your example, everybody has a first, middle and last name (although some of them may possibly be null?), so a map just adds redundant complication (as as noted here on the thread, memory consumption). Frankly, unless you have some special use for the entire Name as an object (e.g., using it as a key in a map), I'd just place three string members directly in the Person class.
This is entirely up to you -- there is no "best" answer here. It depends on how you are using the class.
Generally you do not want to hide things in a map like that. It makes more work to ensure things are correct. What if you accidentally add an incorrect key to the map? Your data structures could get out of whack easily with that method.
Personally, I would most likely just have the 3 values on the Person class directly and not bother with a Name class or a Map.
Once again, I am using words like "most likely" and "generally" because I do not know how the class is being used.
Creating a map is quite memory consuming, compared to creating a name class.
It's better to create the name class, (for one thing, less lines of code :P), mainly because it's less prone to be changed mid-run, unlike the map.
The entries in a map might be accidentally changed during runtime, which could cause problems. If the Name class doesn't have setters, then this can't happen.

Most maintainable and readable way to create objects with many fields

I'm creating a Java class that should encapsulate the six orbital elements of a celestial object, the six osculating elements of the same celestial object, the mass of the body and the name of the body. This means that my Java object must be created with no less than fourteen parameters, and I am now thinking about including another four constants of perturbation as parameters, which will bring that number up to eighteen.
This is how it looks with fourteen parameters:
new Planet("Mercury", 3.3022E23,0.387098, 0., 0.205637, 0.00002123, 7.00559, -0.00590158, 252.252, 149473., 77.4577, 0.1594, 48.3396, -0.122142)
I've looked around people say that a class that takes in more than ten parameters is probably poorly designed. They also say that a class should do one thing and one thing only. Well, I'm just doing one thing literally, the only thing the class does so far is calculating the position of the celestial object with those parameters as a function of time.
What is best practice for dealing with this situation?
I recommend the Bloch Builder, by Joshua Bloch (item 2) in Effective Java, 2nd edition:
http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2
It is a pattern designed specifically for classes with lots of fields, although it is intended for optional parameters, which is not your case. However, I still think this might be a good way for you to approach it. Such as
Planet p = new Planet.Builder("Mercury").gravity(3.3022E23).
anotherAttribute(0.387098).avgTemp(0.).
somethingElse(0.205637).andAnotherThing(0.00002123).
....
build();
(change them to meaningful stuff...I have no idea what the numbers actually represent :)
I recommend against setters in the Planet object, in order to make the fields immutable ( https://www.google.com/search?q=fields+immutable+java+benefit).
I hope this helps.
I would prefer combining the already mentioned solutions - as you write in your intro "I'm creating a Java class that should encapsulate the six orbital elements of a celestial object, the six osculating elements of the same element, the mass of the body and the name of the body.", it seems to me that you can group each six parameters into a new datastructure, so that you end up with four parameters for the Planet constructor (name, mass and the two parameter objects with six own values each) - next step I would ask myself if the six orbital and osculating elements somehow carry extra meaning or are merely a group of six (as in "arbitrary number") elements and can therefore be represented as a list.
I would just have a bunch of setters. Maybe use name as constructor parameter. Just to make it clearer to read. Figuring out which of those 14+ parameters is which is just too difficult for the reader if you set them all in the constructor. Or use a builder as suggested by others.. Both are about the same for me.
I would recommend you to use Builder Design Pattern.
If you are using lombok annotation all the verbose code can be generated by using #Builder annotation.
#Builder
class Some{
private String a;
private String c;
private String d;
private String e;
}
You can generate object with the following semantics:
Some someObject = Some.builder()
.a("a")
.b("b)
.c("c")
.d("d")
.e("e)
.build();

Map vs. Class Properties advice

I'm writing a program with a bunch of classes that will be serialized to save in a database and to be sent through a network.
To make things easier for accessing the class properties via command line interface, I'm considering storing the properties in a Map class, instead of giving each property it's own variable.
Basically, instead of using something like this:
String id = account.getUserId();
I would do this
String id = account.properties.get("userId");
Is this an advisable way to do things?
Yes, it's a pretty sensible model. It's sometimes called the "prototype object model" and is very similar to how you would work in JavaScript where every object is effectively a Map. This in turn has led to the very popular JSON serialisation format.
Nice features:
You don't have to worry about messy inheritance heirarchies - you can just alter the properties at will.
You can create a new object just by copying from another object (the prototype)
Code to manipulate the data can do so in a uniform way, without having to explicitly name all the variables.
It's more "dynamic" compared to a static class definition - it's easy to extend and modify your objects
Potential risks / downsides:
You need to keep track of your property names if you use Strings - the compiler won't do it for you! This issue can be alleviated by using Enums as keys, but then you lose some flexibility...
You don't get the benefits of static type checking, so you may find that you need to write more JUnit tests as a result to ensure things are working properly
There is a slight performance overhead (though probably not enough to worry about, as map lookups are very fast)
I actually wrote an entire game in the 90s using a variant og this object model (Tyrant) and it worked very well.
Rather than having a Map object exposed however, you may want to consider encapsulating this functionality so that you can use an accessor method on the object itself, e.g.
String id = account.getProperty("userId");
How I prefer to do this is often like this:
enum StringPropertyType {
USERID, FIRSTNAME, LASTNAME
}
interface StringAttributes {
String get(StringPropertyType s);
void put(StringPropertyType s, String value);
}
class MapBasedStringAttributes implements StringAttributes {
Map<StringPropertyType, String> map = new HashMap<~>();
String get(StringPropertyType s) { return map.get(s); }
void put(StringPropertyType s, String value) { map.put(s,value); }
}
this gives you compile-time safety, refactoring, etc.
you could also use the stringPropertyType.name() to get the string representation of the enum value and use
Map<String,String>
instead..

generating unique string for each java object instance

I need to write a function which returns a string which should be unique for each state of the object.
i.e. if any of the instance variables are changed, then this method should return another string which should be unique for the given set of instance variables of object.
Similarly I would later require write another method which represents unique static state of the class.
Please suggest any efficient ways to achieve my requirement.
Thanks,
Harish
If you want to track the changes to a given object's state (in its own boundary), this is achievable with a bit of coding or adopting an already implemented approach. Is that what you are asking? What does make using an incrementing serial number inappropriate in your case?
If you are about to guarantee uniqueness amongst all the existing instances of a given class, this is a bit hard. You might need to distinguish an object individually, then asking each object for their unique string representation.
I'd recommend reading about Object.hashcode(). The ideas recommended for hashcode generation could be used for the purpose you want.
You can use Java reflection to find all the fields in your class and work from there:
public String tos() throws IllegalAccessException {
StringBuilder b = new StringBuilder();
for (Field f : getClass().getDeclaredFields()) {
f.setAccessible(true);
b.append(f.get(this));
}
return b.toString();
}
A fairly naive approach would be to serialize the object to memory and take a secure hash of the content. Quite inefficient but it works with any serializable object.
What are the requirements exactly?
Do nested objects also affect state (or is this applicable)? if a.b.c changes does this affect state of a?
Do two different objects with the same content have to end up with the same string?

Common algorithm for generating a diff of the fields in two beans?

Let's say you have two instances of the same bean type, and you'd like to display a summary of what has changed between the two instances - for example, you have a bean representing a user's settings in your application, and you'd like to be able to display a list of what has changed in the new settings the user is submitting (instance #1) versus what is stored already for the user (instance #2).
Is there a commonly used algorithm or design pattern for a task such as this, perhaps something that can be abstracted and re-used for different types of beans? (I'm having a hard time thinking of a good name for this type of problem to know what to Google on). I've checked commons-beanutils and nothing popped out at me.
If you are talking about comparing values, I would consider using reflection and just comparing them field by field.
Something like this:
Field[] oldFields = oldInstance.class.getDeclaredFields();
Field[] newFields = newInstance.class.getDeclaredFields();
StringBuilder changes = new StringBuilder();
Arrays.sort(oldFields);
Arrays.sort(newFields);
int i = 0;
for(Field f : oldFields)
{
if(!f.equals(newFields[i]))
{
changes.append(f.getName()).append(" has changed.\n");
}
i++;
}
This code hasn't been tested. You might need to get the values in the fields and compare them instead of just comparing fields to each other, but it should work in theory.
The reflection not mantains the order of the Field in next calling: it's safier order the arrays.
/*
*declarations of variables
*/
Arrays.sort(oldFields);//natural order - choice 1
Arrays.sort(newFields, new Ordinator());//custom Comparator - choice 2
/*
*logic of comparations between elements
*/
In choice 2 you can decide the logic of sorting (HOW SORTING THE ELEMENTS) with an inner class Ordinator extending Comparator.
PS the code is a draft
We've done something similar with bean utils and it worked well. Things to consider: Do you drill down into field objects - If a Person contains an Address and the address changes do you say the address changed or that address.postalCode changed(we do)? Do you return a list propety name, old value, new value from the diff (we do)? How do you want to handle dates - if all you care about is date part then your comparison should ignore the time? How do you say which fields to ignore?
This isn't really a copy and paste answer but more of list of things that weren't immediately obvious when we wrote our differ.
As for implementation, we just have a static util method that takes two beans and a list of properties to compare and then returns a map of properties to a Pair containing the old value and the new value. Then each bean has a diff(Object o) method that calls the static util method as needed.
These libraries should help.
https://code.google.com/p/beandiff/ - An annotation based bean diffing library. Apache License 2.0
https://github.com/SQiShER/java-object-diff/ - A bean differ based on Visitor pattern. Apache License 2.0
We had a requirement to generate difference between beans in json format for auditing purpose. We ended up implementing it using beandiff library.
** EDIT **
This looks like a newer option. I have not used it though.
http://beandiff.org/
Hope it helps.
Good answers above.
If your data changes structurally, i.e. whole collections of fields may be relevant or not depending on others, you might want to consider differential execution.
Basically, you have a loop over the fields, and you serialize the current field values at the same time as you deserialize the prior values, comparing them as you go.
If there is a conditional test that makes a block of fields relevant or not, you serialize/deserialize the true-or-false value of the conditional test, and use that to decide whether or not to serialize and/or deserialize the affected fields. And it recurs nicely.
Just a suggestion.
Solution using reflection and standard data structures.
Field[] declaredFields = ClassOne.class.getDeclaredFields();
Field[] declaredFields2 = ClassTwo.class.getDeclaredFields();
ArrayList<String> one = new ArrayList<String>();
ArrayList<String> two = new ArrayList<String>();
for (Field field : declaredFields)
{
one.add(field.getName());
}
for (Field field : declaredFields2)
{
two.add(field.getName());
}
List<String> preone = (List<String>)one.clone();
one.removeAll(two);
two.removeAll(preone);
Collections.sort(one);
Collections.sort(two);
System.out.println("fields only in One : " + one);
System.out.println("fields only in Two : " + two);

Categories