It's time to make immutability the default
Right. I have to get this off my chest. A follow-on from my habitual coding observation in my previous article.
How many people habitually write Java code like this? (Clue: I see it a lot)
Then you can create an object an use it with something like:
Great, assuming that you want to allow changes to the object later. But if you have no explicit requirement to change anything, then you have left the door wide open to abuse. Your setters are public. You have written too much code.
OK, let's try something else and lock the door. Wouldn't it be nice if we created the object in the correct state from the off, all ready to use, rather than having to construct then initialise. We end up with something like:
But I can't help thinking this is a very short hop from:
My point is the following. If you have no definite requirement to change the values on a POJO, then make it immutable from the start! Only introduce mutator methods as they are required.
One final thing - yes, you can produce a similar result by using frameworks like Lombok to hide the 'getXyz()' methods, but why introduce further complexity of a framework when it can be done so elegantly natively?
There. I feel better now :-)
Note - some of the code is appearing with </string> annotations - no idea why. Seems to be a quirk of the Google Blogger editor
Note #2 - the </string> annotations appear to be a Chrome issue. Oh the irony! :)
How many people habitually write Java code like this? (Clue: I see it a lot)
public class Article { private String title; private String author; private Listtags; public void setTags(List tags) { this.tags = tags; } public void setAuthor(String author) { this.author = author; } public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } public String getAuthor() { return author; } public List getTags() { return tags; } }
Then you can create an object an use it with something like:
Article article = new Article(); article.setAuthor("Cam M. Bert"); article.setTitle("French Cheeses"); article.setTags(Collections.asList("cheese", "food")); // etc etc
Great, assuming that you want to allow changes to the object later. But if you have no explicit requirement to change anything, then you have left the door wide open to abuse. Your setters are public. You have written too much code.
OK, let's try something else and lock the door. Wouldn't it be nice if we created the object in the correct state from the off, all ready to use, rather than having to construct then initialise. We end up with something like:
public class Article { private String title; private String author; private ListA bit better. Remember, you don't have any explicit requirement to change values so do not need any mutator methods. The tags List object is still open to abuse, but hey-ho....tags; public Article(String title, String author, List tags) { this.title = title; this.author = author; this.tags = tags; } public String getTitle() { return title; } public String getAuthor() { return author; } public List getTags() { return tags; } }
But I can't help thinking this is a very short hop from:
public class Article { public final String title; public final String author; public final ListLess code to read, easy access to immutable fields.tags; public Article(String title, String author, List tags) { this.title = title; this.author = author; this.tags = Collections.unmodifiableList(tags); } }
My point is the following. If you have no definite requirement to change the values on a POJO, then make it immutable from the start! Only introduce mutator methods as they are required.
One final thing - yes, you can produce a similar result by using frameworks like Lombok to hide the 'getXyz()' methods, but why introduce further complexity of a framework when it can be done so elegantly natively?
There. I feel better now :-)
Note - some of the code is appearing with </string> annotations - no idea why. Seems to be a quirk of the Google Blogger editor
Note #2 - the </string> annotations appear to be a Chrome issue. Oh the irony! :)
Or, in Groovy:
ReplyDelete@Immutable
@TupleConstructor
class Article {
String title
String author
List tags
}
Unfortunately not possible in not-Groovy Java world :-(
ReplyDeleteIn Kotlin you can simply write
ReplyDeletedata class Article(val title: String, val author: String, val tags: List)
So you get immutable "data" class with all required hashcode, equals, toString and nullability