Reputation: 269
I was wondering if their was a smarter and more elegant way of writing a setter, or for that matter, any code which has to check for whether user input is correct
This just seems odd. I'm a novice, so maybe this is just the standard way of approaching this problem, but if not, I'd appreciate knowing what the 'smart' way is
public void setMonth(){
boolean run = true;
while(run){
int input = scan.nextInt();
if(input > 0 && input < 13){
this.month = input;
run = false;
}
}
}
Upvotes: 1
Views: 142
Reputation: 6414
Rules for writing "good" stter:
1) Don't do any Input-Output operations in setter like accessing DB, file, network, email sending, reading from command line etc... If you must, do it before or after you call setXXX, best writing some service method for that.
2) Have as small logic as possible in setter. It is ok to do parameter validation like range check etc...
3) Setter should do only the one thing it is designed for (set a value), it shouldn't have any side-effects.
Upvotes: 1
Reputation: 8840
The setters and getters are also known as mutators and accessors.
My understanding is that these methods are only there to retrieve or modify the 'state' of an object. It should not have the business logic or rather have as less business logic in it as possible.
Basically have Computations/Business Logic which are cheap.
Make your setter to only 'set' the values.
public void setMonth(int month){
this.month = month
}
While method to retrieve values based on input could be re-used anywhere else and that I suggest you can create a utility class and have that as method as static.
class DateUtil {
public static int retrieveMonthBasedOnInput(){
}
}
This class should have the business logic to retrieve the details from user inputs and thereby should be used while trying to set the value of that bean instance.
Upvotes: 2
Reputation: 5474
First of all you can simplify your code like this:
public void setMonth() {
int input = 0;
do {
input = scan.nextInt();
} while(input <= 0 || input >= 13)
this.month = input;
}
In addition to that I'd separate this into two functions. A setter should only set a value.
public void setMonth(int month) {
if(month > 0 && month <= 12) {
this.month = month;
} else {
throw new IllegalArgumentException("Month has to be a value between 1 and 12 inclusively. Actual value was :" + month);
}
}
public void readMonth() {
int input = 0;
do {
input = scan.nextInt();
} while(input <= 0 || input >= 13)
setMonth(input);
}
As suggested by ChiefTwoPencils, you can furthermore extract the setter into an additional class. Thus separating user input and data even more.
class MonthDataHolder {
private int month;
public MonthDataHolder(int month) {
setMonth(month);
}
public void setMonth(int month) {
if(isValidMonthValue(month)) {
this.month = month;
} else {
throw new IllegalArgumentException("Month has to be a value between 1 and 12 inclusively. Actual value was :" + month);
}
}
private boolean isValidMonthValue(month) {
return month >= 1 || month <= 12;
}
}
class InputReader {
public MonthDataHolder readMonth() {
int input = 0;
do {
input = scan.nextInt();
} while(input <= 0 || input >= 13)
return new MonthDataHolder(input);
}
}
Upvotes: 4
Reputation: 2107
The function should be simple and only do one job. Maybe you can code like this:
public void setMonth(int month) throws IllegalArgumentException {
if(month<0 || month>11) throw new IllegalArgumentException("Month can only be set 0~11");
this.month = month;
}
As you can see the function only do one thing that is set the month. If the argument isn't correct, throw the exception.
Upvotes: 1