Design pattern for Immutable object with eventual immutability - java

I want to construct an object which I want to pass on to the rest of the application as an immutable object. However problem here is that some fields are directly available at object construction time whereas some require a response from an RPC call. RPC call takes some time to return and I do not want to block the callers during this time because I would like callers to use the fields which are passed in during the object construction time. I have a design in mind but wanted to know if there is a standard pattern.
Following example illustrates what I am looking for.
public class Player {
private int name; // Available at construction time
private int age; // Available at construction time
private String profileUrl; // Need to get this from an RPC call
// useful for checking whether we have profileUrl
private boolean profileUrlAvailable = false;
Player(int name, int age) {
this.name = name;
this.age = age;
}
// usual getter methods
// Package protected for immutability
void setProfileUrl(String profileUrl) {
this.profileUrl = profileUrl;
this.profileUrlAvailable = true;
}
public boolean hasProfileUrl() {
return profileUrlAvailable;
}
// throws if profile url is not yet available.
public String getProfileUrl() {
if (!profileUrlAvailable) {
throw new IllegalStateException("Profile url not available");
}
return profileUrl;
}
}
This example is not threadsafe, consider that it will be taken care of. To be able to let interested callers know when the profile url is available, I will expose a method to register callables which will be notified when the profileUrl is available.
I think this approach does not work well if I add few more fields similar to profileUrl which will eventually be available. I wanted suggestions on the ways to solve this.
Does it simplify if I make sure that all fields similar to profileUrl are made available at the same time (ie., they are set using a single method) ?

Does Lazy initialization suit your needs?
Code snippet:
public class Player {
private int name; // Available at construction time
private int age; // Available at construction time
private String profileUrl = null; // Need to get this from an RPC call
Player(int name, int age) {
this.name = name;
this.age = age;
}
// usual getter methods
public String getProfileUrl() {
if (profileUrl == null) {
profileUrl = Remote.getProfileUrl();
}
return profileUrl;
}
}
You would move your RPC to the accessor method, in this case getProfileUrl.
Only the first call would actually block waiting for the remote procedure to finish.
Other accessor methods for fields that require this kind of heavy initialization would look the same.
If you can use Player class this way and are able to cache profileUrl for future calls you would solve your problem and hit this pattern's goal.

Related

How to implement #RollbackExecution method for Mongock

I have simple document class:
public class Player {
private String name;
private String age;
}
I want to extend it with field Parameters:
public class Player {
private String name;
private String age;
private Parameters parameters;
public class Parameters {
boolean leftFooted;
boolean leftHanded;
}
}
My Mongock #Execution method would be:
#Execution
public void execution(PlayerRepository playerRepository) {
playerRepository.findAll()
.stream()
.map(this::setDefaultParameters)
.forEach(playerRepository::save);
}
with method:
private Player setDefaultParameters(Player player) {
if (player.getParameters == null) {
player.setParameters(new Parameters(false, false));
}
return player;
}
My question is - how to implement #RollbackExecution method if documents created after model extension can also have Parameters field with values 'false, false' and I just can not set Parameters field to null for all documents in database?
First, am I right on the assumption that, before executing the #Execution method, there may be some documents which already have the parameters field with some value? And, after the execution, you struggle to identify those ones amended in the actual change unit versus those that already had the parameters field?
If that’s the case, you really are not breaking anything, and you would leave the #RollbackExecution empty, and the updated documents will remain with its default value in parameters field.
If you still care, you need to somehow mark those documents that you updated in the ChangeUnit (with a flag or something), so you can filter by the flag and restore your changes.

Java: how do you pass incomplete information to a class? [duplicate]

I've been wondering what the best (i.e. cleanest/safest/most efficient) way of handling multiple constructors in Java is? Especially when in one or more constructors not all fields are specified:
public class Book
{
private String title;
private String isbn;
public Book()
{
//nothing specified!
}
public Book(String title)
{
//only title!
}
...
}
What should I do when fields are not specified? I've so far been using default values in the class so that a field is never null, but is that a "good" way of doing things?
A slightly simplified answer:
public class Book
{
private final String title;
public Book(String title)
{
this.title = title;
}
public Book()
{
this("Default Title");
}
...
}
Consider using the Builder pattern. It allows for you to set default values on your parameters and initialize in a clear and concise way. For example:
Book b = new Book.Builder("Catcher in the Rye").Isbn("12345")
.Weight("5 pounds").build();
Edit: It also removes the need for multiple constructors with different signatures and is way more readable.
You need to specify what are the class invariants, i.e. properties which will always be true for an instance of the class (for example, the title of a book will never be null, or the size of a dog will always be > 0).
These invariants should be established during construction, and be preserved along the lifetime of the object, which means that methods shall not break the invariants. The constructors can set these invariants either by having compulsory arguments, or by setting default values:
class Book {
private String title; // not nullable
private String isbn; // nullable
// Here we provide a default value, but we could also skip the
// parameterless constructor entirely, to force users of the class to
// provide a title
public Book()
{
this("Untitled");
}
public Book(String title) throws IllegalArgumentException
{
if (title == null)
throw new IllegalArgumentException("Book title can't be null");
this.title = title;
// leave isbn without value
}
// Constructor with title and isbn
}
However, the choice of these invariants highly depends on the class you're writing, how you'll use it, etc., so there's no definitive answer to your question.
You should always construct a valid and legitimate object; and if you can't using constructor parms, you should use a builder object to create one, only releasing the object from the builder when the object is complete.
On the question of constructor use: I always try to have one base constructor that all others defer to, chaining through with "omitted" parameters to the next logical constructor and ending at the base constructor. So:
class SomeClass
{
SomeClass() {
this("DefaultA");
}
SomeClass(String a) {
this(a,"DefaultB");
}
SomeClass(String a, String b) {
myA=a;
myB=b;
}
...
}
If this is not possible, then I try to have an private init() method that all constructors defer to.
And keep the number of constructors and parameters small - a max of 5 of each as a guideline.
It might be worth considering the use of a static factory method instead of constructor.
I'm saying instead, but obviously you can't replace the constructor. What you can do, though, is hide the constructor behind a static factory method. This way, we publish the static factory method as a part of the class API but at the same time we hide the constructor making it private or package private.
It's a reasonably simple solution, especially in comparison with the Builder pattern (as seen in Joshua Bloch's Effective Java 2nd Edition – beware, Gang of Four's Design Patterns define a completely different design pattern with the same name, so that might be slightly confusing) that implies creating a nested class, a builder object, etc.
This approach adds an extra layer of abstraction between you and your client, strengthening encapsulation and making changes down the road easier. It also gives you instance-control – since the objects are instantiated inside the class, you and not the client decide when and how these objects are created.
Finally, it makes testing easier – providing a dumb constructor, that just assigns the values to the fields, without performing any logic or validation, it allows you to introduce invalid state into your system to test how it behaves and reacts to that. You won't be able to do that if you're validating data in the constructor.
You can read much more about that in (already mentioned) Joshua Bloch's Effective Java 2nd Edition – it's an important tool in all developer's toolboxes and no wonder it's the subject of the 1st chapter of the book. ;-)
Following your example:
public class Book {
private static final String DEFAULT_TITLE = "The Importance of Being Ernest";
private final String title;
private final String isbn;
private Book(String title, String isbn) {
this.title = title;
this.isbn = isbn;
}
public static Book createBook(String title, String isbn) {
return new Book(title, isbn);
}
public static Book createBookWithDefaultTitle(String isbn) {
return new Book(DEFAULT_TITLE, isbn);
}
...
}
Whichever way you choose, it's a good practice to have one main constructor, that just blindly assigns all the values, even if it's just used by another constructors.
Some general constructor tips:
Try to focus all initialization in a single constructor and call it from the other constructors
This works well if multiple constructors exist to simulate default parameters
Never call a non-final method from a constructor
Private methods are final by definition
Polymorphism can kill you here; you can end up calling a subclass implementation before the subclass has been initialized
If you need "helper" methods, be sure to make them private or final
Be explicit in your calls to super()
You would be surprised at how many Java programmers don't realize that super() is called even if you don't explicitly write it (assuming you don't have a call to this(...) )
Know the order of initialization rules for constructors. It's basically:
this(...) if present (just move to another constructor)
call super(...) [if not explicit, call super() implicitly]
(construct superclass using these rules recursively)
initialize fields via their declarations
run body of current constructor
return to previous constructors (if you had encountered this(...) calls)
The overall flow ends up being:
move all the way up the superclass hierarchy to Object
while not done
init fields
run constructor bodies
drop down to subclass
For a nice example of evil, try figuring out what the following will print, then run it
package com.javadude.sample;
/** THIS IS REALLY EVIL CODE! BEWARE!!! */
class A {
private int x = 10;
public A() {
init();
}
protected void init() {
x = 20;
}
public int getX() {
return x;
}
}
class B extends A {
private int y = 42;
protected void init() {
y = getX();
}
public int getY() {
return y;
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println("x=" + b.getX());
System.out.println("y=" + b.getY());
}
}
I'll add comments describing why the above works as it does... Some of it may be obvious; some is not...
Another consideration, if a field is required or has a limited range, perform the check in the constructor:
public Book(String title)
{
if (title==null)
throw new IllegalArgumentException("title can't be null");
this.title = title;
}
I would do the following:
public class Book
{
private final String title;
private final String isbn;
public Book(final String t, final String i)
{
if(t == null)
{
throw new IllegalArgumentException("t cannot be null");
}
if(i == null)
{
throw new IllegalArgumentException("i cannot be null");
}
title = t;
isbn = i;
}
}
I am making the assumption here that:
1) the title will never change (hence title is final)
2) the isbn will never change (hence isbn is final)
3) that it is not valid to have a book without both a title and an isbn.
Consider a Student class:
public class Student
{
private final StudentID id;
private String firstName;
private String lastName;
public Student(final StudentID i,
final String first,
final String last)
{
if(i == null)
{
throw new IllegalArgumentException("i cannot be null");
}
if(first == null)
{
throw new IllegalArgumentException("first cannot be null");
}
if(last == null)
{
throw new IllegalArgumentException("last cannot be null");
}
id = i;
firstName = first;
lastName = last;
}
}
There a Student must be created with an id, a first name, and a last name. The student ID can never change, but a persons last and first name can change (get married, changes name due to losing a bet, etc...).
When deciding what constrructors to have you really need to think about what makes sense to have. All to often people add set/get methods because they are taught to - but very often it is a bad idea.
Immutable classes are much better to have (that is classes with final variables) over mutable ones. This book: http://books.google.com/books?id=ZZOiqZQIbRMC&pg=PA97&sig=JgnunNhNb8MYDcx60Kq4IyHUC58#PPP1,M1 (Effective Java) has a good discussion on immutability. Look at items 12 and 13.
Several people have recommended adding a null check. Sometimes that's the right thing to do, but not always. Check out this excellent article showing why you'd skip it.
http://misko.hevery.com/2009/02/09/to-assert-or-not-to-assert/

Multiple Parameters or is there any way to force use of setters (Java)?

I have a java class named Transactions, with several methods. On in particular, inserts in Sqlite database all values representing a new transaction, something like this:
Date; Time; Category; Payee; Payer; Value; Tags; Description (...)
When I call the method to save a new Transaction, it looks like:
new Transactions().saveNewTransaction(String date, String time, String category, Int Payee, Int Payer, String value, String tags, String Description (...)
I think this method seems big, bad for readable code and the best way would be those fields be as variables from Transactions class and the method saveNewTransaction(), takes no parameters but instead accessing the variables inside the class.
The only problem is: how can I force to a class (In my case an Activity class) call all setters needed to save a new transaction?
The risk would be call saveNewTransaction() and several fields with values not set by the Activity class (at least the method assures all fields must be set by the caller)
Thanks!
If your requirement is that each created Transactions object should result in some database entry, you could consider dropping the saveNewtTransaction method and instead perform the save-action within some "builder" class:
public class TransactionBuilder {
private Date date;
public TransactionsBuilder with(#NonNull Date date){
this.date = date;
return this;
}
public Transaction build(){
validateFields();
Transaction transaction = new Transaction();
transaction.set(date);
createADatabaseEntry(transaction);
return transaction;
}
private void validateFields() {
org.springframework.util.Assert.notNull(date, "The date cannot be null.");
}
Have the checker framework issue compiler warnings, when developers try to pass null to setters annotated with #NonNull.
Obviously, in your case, the builder would have some different with()-methods, namely some which matches what is needed for your Transactiion object / saveNewTransaction()-method.
Ps I have not given it any thought what your Transaction class is all about. But if the Transactions class only has that one method, I would create a variant of above mentioned solution:
Create an interface with a single method that defines the functionality.
Create an implementation which contains the logic of your saveNewTransactions()-method. Only difference being that this method should only accept a single argument, which is an "input bean", fx TransactionInputBean.
Create your input bean (a simply class with private fields, and public getters&setters.
Create a builder for the input bean.
you could leave all of these variables uninitialized or set them to a value that shouldn't occur by the setters (eg. -1).
Then in your new Transactions().save(); you'd need to check if they still have that value.
But this solution won't work in the way you wrote above, because you are already saving the transaction when you create the object. And here you'd need to create the new object first and then call all the setters.
Your transactions class could look like this:
package de.jeanma.stackOverflow;
import java.lang.Integer;
import java.lang.String;
public class Transactions{
private String date, time, category, value, tags, description;
private int payee, payer;
public Transactions(){
//Add everything here, needed for the constructor
}
public Transactions(String date, String time, String category, int payee, //I recommend creating an constructor that sets the values as well, beacause you
int payer, String value, String tags, String Description){ // might want to create the object and call the save() directly withoud calling every setter one by one
this.date = date;
this.time = time;
this.category = category;
this.value = value;
this.tags = tags;
this.description = description;
this.payee = payee;
this.payer = payer;
//Add everything here, needed for the constructor as well
}
//Here you can place all your other methods
public void save(){
if(!(isInitialized(date) && isInitialized(time) && isInitialized(category) && isInitialized(value) //here all values are checked if they are initialized.
&& isInitialized(tags) && isInitialized(description) && isInitialized(Integer.valueOf(payee)) //The primitive int's are made to complex Integer's because
&& isInitialized(Integer.valueOf(payer)))){ // the method isInitialized() expects an object
//here you could throw an exception or do something like: System.exit(-1);
}
}
private boolean isInitialized(Object Obj){ // this is the method that's checking if the value is initialized
if(Obj.equals(null)) return false;
else return true;
}
//Add all the setters here (I'm too lazy to do that now)
}
I hope that this awnser satisfies you.

Is there any way to access this.toString()'s value when calling another constructor?

For everyone who is talking about the fact that the object is in an "unitialized state", please refer to the answer to this question which shows that an object reference can be passed around, dereferenced, have methods invoked from it, and have fields accessed before a constructor terminates and all fields have been assigned (including final fields).
So here's the use case:
public class Entity {
private final String name;
public Entity() {
this(toString()); //Nope, Chuck Testa
}
public Entity(String name) {
this.name = name;
}
}
The compiler error is:
Cannot refer to an instance method while explicitly invoking a constructor.
Note that toString() has not been overriden and is the default call from Object.
I'm certainly interested in the philosophical/technical reasons behind this, so if anyone can explain that, that would be an awesome bonus. But I'm looking for a way to call toString() from that default constructor as it refers down to the more specific one with more arguments. The actual use case is a bit more complicated and ends up referring all the way down to a constructor with four arguments, but that shouldn't really matter.
I know I could do something like this...
private static final String TO_STRING_CONSTRUCTOR_ARGUMENT = "aflhsdlkfjlkswf";
public Entity() {
this(TO_STRING_CONSTRUCTOR_ARGUMENT);
}
public Entity(String name) {
this.name = name == TO_STRING_CONSTRUCTOR_ARGUMENT ? toString() : name;
}
... but it seems like a pretty inelegant solution.
So, any way to pull it off? Or any recommended best practices to deal with this situation?
I would prefer not to pass this around until the object is created. Instead I would do this:
public class Entity {
private final String name;
public Entity() {
this(null); // or whatever
}
public Entity(String name) {
this.name = name;
}
public String getName() {
return name != null ? name : Objects.hashCode(this);
}
}
If you can live without the final name, you can use an initializer block:
public class Entity {
private String name;
{name = this.toString();}
public Entity() {
}
public Entity(String name) {
this.name = name;
}
}
this is only available after all calls to this() or super() are done. The initializer runs first after the constructors call to super() and is allowed to access this.
As for the reasons why that is a compiler error, please see section 8.8.7 of the JLS. The reasons why this was made a compiler error are not clear, but consider that the constructor chain has to be the first thing executed when new'ing an Object and look at the order of evaluation here:
public Entity() {
this(toString());
}
toString() is evaluated first before the even the super constructor is invoked. In general this leaves open all kinds of possibilities for uninitialized state.
As a personal preference, I would suggest that everything an object needs to have in order to create valid state should be available within its constructor. If you have no way of providing valid state in a default constructor without invoking other methods defined in the object hierarchy, then get rid of the default constructor and put the onus on the users of your class to supply a valid String to your other constructor.
If you are ultimately just trying invoke the other constructor with the value of toString(), then I would suggest the following instead:
public Entity() {
name = toString();
}
which accomplishes the same goal you set out to achieve and properly initializes name.
As explained in the JLS this is not allowed before the instance is initialized.
However, there are ways to handle your scenario in a consistent manner.
As I see your case, you want to signify either a generated value (toString()) or a user provided value, which can be null.
Given this constraints, using TO_STRING_CONSTRUCTOR_ARGUMENT is failing for at least one specific use case, however obscure it may be.
Essentially you will need to replace the String with an Optional similar to what exists in Google Guava and will be included in Java 8, and seen in many other languages.
Having a StringOptional/StringHolder or whatever you choose, similar to this:
public class StringOptional {
private String value;
private boolean set = false;
public StringOptional() {}
public StringOptional(String value) {
this.value = value;
this.set = true;
}
public boolean isSet() { return set; }
public String getValue() { return value; }
}
Then you can call constructors with the knowledge of the inferred path.
public class Entity {
public Entity() {
this(New StringOptional());
}
public Entity(String s) {
this(new StringOptional(s));
}
private Entity(StringOptional optional) {
super(optional);
}
}
And store this for subsquent need:
if (optional.isSet() ? optional.getValue() : toString();
This is how I usually would handle a maybe-null scenario, hope it augments as an answer.
You cannot 'use' an instance that has not been created yet. By calling a second constructor you are postponing the creation, you cannot use it before the call or in the action of calling.
You can use a static method factory in your class Entity, and put the constructor private:
public class Entity {
private String name;
private Entity() {
}
public Entity(String name) {
this.name = name;
}
public static Entity createEntity() {
Entity result = new Entity();
result.name = result.toString();
return result;
}
}

Java Public Var question [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Property and Encapsulation
NEWB Alert!!
I am starting with Android and Java and I am starting to understand it but I am wondering why I should use getters and setters and not just public variables?
I see many people make a private variable and create a get and set method.
What is the idea here?
Its called encapsulation and the concept is central to object oriented programming. The idea is that you hide the implementation of your class and expose only the contract i.e. hide the how and only expose the what. You hide the variables by making them private and provide public setters-getters and other public methods which the clients invoke to communicate with your class. They are not tied to the actual implementation of the methods or how you store your variables.
For example, suppose you had this class where you stored a phone number as a Long object:
public class ContactInfo {
private Long phoneNo;
public Long getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(Long phoneNo) {
this.phoneNo = phoneNo;
}
}
Since the clients of the class only see the getter/setter, you can easily change the implementation of the class/methods by switching the phone number representation to a PhoneNumber object. Clients of ContactInfo wouldn't get affected at all:
public class ContactInfo {
private PhoneNumber phoneNo;
public Long getPhoneNo() {
return phoneNo.getNumber();
}
public void setPhoneNo(Long phoneNo) {
this.phoneNo = new PhoneNumber(phoneNo);
}
}
public class PhoneNumber {
private Long number;
public PhoneNumber(Long number) {
this.number = number;
}
public Long getNumber() {
return number;
}
}
The OOP concept involved is encapsulation (google it).
Some of the advantages are: you can specify different access level for setters (mutators) and getters (accessors), for example public getter and private setter. Another advantage is that you can add another code other than changing or retrieving the value. For example, you may want to check the validity of the set value, or you want to throw exceptions or raise some events in response to changing the variable to certain value. If you implement these inside an accessor or mutators, you can also change their implementations without changing any code outside of the class.
I believe the idea is "information hiding" http://en.wikipedia.org/wiki/Information_hiding
It also serves to control the access to variables (provides an interface). For example, you can provide a getter but not a setter, so that they may be read but not written. Whereas if everything was public any thing could read and write to the variables.
Also important is any checking/validation need to set a variable. For example you have a String name that is not allowed to be empty but if it is public it could easily be forgotten and set as name = "". If you have a setter such as public boolean setName(String newName) you can check newNames length and return true or false if it passes and is set or not
The concept is called encapsulation.
What it attempts to do is to separate the inner structure of a class from its behaviour.
For example, suppose a class like this
public class Point{
private float x;
private float y;
public float getX(){
return x;
}
public float getY(){
return y;
}
public float distanceToZero2(){
return x*x + y*y
}
public float getAngle(){
//havent considered the x = 0 case.
return atan(y/x);
}
public boolean isInFirstQuad(){
return x>0 && y>0;
}
}
In this case, encapsulation hides the inner structure of the class, and exposes only the operations available to a Point. If you dont like it, you can change its inner structure and mantain its behaviour (for example, changing carthesian coordinates to polar coordinates).
Anyoune who uses this class wont care about it, he /she will be happy that they have a Point class with this functionality.
Asides the encapsulation, you can also control the value get or set to your variable in some cases. For example, you want to validate the value of an age variable which should be >=1
class Person {
private int age = Integer.MIN_VALUE;
public void setAge(int age){
if(age>=1)
this.age = age;
}
public int getAge(){
return age;
}
}

Categories

Resources