I have one query that is I have used a method but there is many time I have used If Else ..not it become very ambiguous please advise can I use some other conditional loop also..below is my code..
if (cardType == AARP_CARD_TYPE) {
userResponse = messageBox.showMessage("CandidateAARPCardAttachCardToExistingTransaction",
null, IMessageBox.YESNO); // MSG:31.59
transaction.setValue(ITransactionHashtableWag.LOYALTY_MESSAGE_DISPLAYED,
WalgreensRewardsConstants.ATTACH_CANDIDATE_AARP_CARD);
} else if ((cardType == PSC_CARD_TYPE) && ((!PosHelper.isRunningAsService()))) {
userResponse = messageBox.showMessage("PendingPSCCardAttachCardToExistingTransaction", null,
IMessageBox.YESNO); // MSG:31.60
transaction.setValue(ITransactionHashtableWag.LOYALTY_MESSAGE_DISPLAYED,
WalgreensRewardsConstants.ATTACH_PENDING_PSC_CARD);
} else if ((cardType == DR_CARD_TYPE) && ((!PosHelper.isRunningAsService()))) {
userResponse = messageBox.showMessage("PendingDRCardAttachCardToExistingTransaction", null,
IMessageBox.YESNO); // MSG:31.63
transaction.setValue(ITransactionHashtableWag.LOYALTY_MESSAGE_DISPLAYED,
WalgreensRewardsConstants.ATTACH_PENDING_DR_CARD);
} else if ((cardType == WAG_LOYALTY_CARD_TYPE)){
transaction.setValue(ITransactionHashtableWag.LOYALTY_MESSAGE_DISPLAYED,
WalgreensRewardsConstants.ATTACH_NOT_ON_FILE);
if((!PosHelper.isRunningAsService())) {
userResponse = messageBox.showMessage("CardNotOnFileToAttach", null, IMessageBox.YESNO); // MSG:31.32
// BUC
// 1.22.1
}
} else { // If the device is neither of these, POS displays Message 1
// Button, MSG 31.14. [BUC
// 1.23.2]
displayMessage("InvalidLoyaltyCard");
transaction.setValue(ITransactionHashtableWag.LOYALTY_MESSAGE_DISPLAYED,
NOT_VALID_LOYALTY_CARD);
userResponse = -1;
}
Please advise how can I improve my above logic with some other conditional statements as there is lots n lots of If Else is used..!!
If cardType is an enum, you can add methods to your enum, (say getName, getWag etc.) and call it:
userResponse = messageBox.showMessage(cardType.getMessage(), ...
transaction.setValue(cardType.getWag(), cardType.getRewards());
If it is an int or another non-enum type, you can use a switch as already proposed, or consider switching (haha) to an enum. You could also make PosHelper.isRunningAsService() a boolean parameter to those methods and all your if/else code would be reduced to 3 or 4 lines it seems (although it will introduce some coupling but you seem to have a lot of it already).
Your enum could look like this (simple example that you can complicate as required):
public enum CardType {
AARP_CARD_TYPE {
public String getName() {
return "CandidateAARPCardAttachCardToExistingTransaction";
}
},
PSC_CARD_TYPE {
public String getName() {
return "PendingPSCCardAttachCardToExistingTransaction";
}
};
public abstract String getName();
}
Or more compact, if you don't require complicated logic in the methods:
public static enum CardType {
AARP_CARD_TYPE("CandidateAARPCardAttachCardToExistingTransaction"),
PSC_CARD_TYPE ("PendingPSCCardAttachCardToExistingTransaction");
private final String transactionName;
CardType(String transactionName) {
this.transactionName = transactionName;
}
public String getName() {
return transactionName;
}
}
Use a switch statement instead.
switch (cardType) {
case AARP_CARD_TYPE:
// blah
break;
case PSC_CARD_TYPE:
// blah
break;
// ...
default:
// default blah
break;
}
You have some options: Pattern Strategy, Polymorphism or Events to avoid too much ifs/else
In your example probably the business logic is close to the user interface. You can use the MVC concept to separate the logic from the presentation and reduce the if/elses (if possible).
If you don't like adding methods to CardType as assylias suggested, you can create an 'Action' enum and add the method(s) to that one and use a Map
Related
The code below compiles and does its job, however lets say I needed to added another 100 if statements that uses a reference. Whats the most efficient way to write multiple if statements?
public String getForceDetails(String ref) {
if (ref.equals("IW1")) {
setupForces();
return (ForceDetails.get(0).toString());
} else if (ref.equals("SS2")) {
setupForces();
return (ForceDetails.get(1).toString());
} else if (ref.equals("WB3")) {
setupForces();
return (ForceDetails.get(2).toString());
} else if (ref.equals("IW4")) {
setupForces();
return (ForceDetails.get(3).toString());
} else if (ref.equals("WB5")) {
setupForces();
return (ForceDetails.get(4).toString());
} else if (ref.equals("SS6")) {
setupForces();
return (ForceDetails.get(5).toString());
} else if (ref.equals("SS7")) {
setupForces();
return (ForceDetails.get(6).toString());
} else if (ref.equals("WB9")) {
setupForces();
return (ForceDetails.get(7).toString());
} else if (ref.equals("IW10")) {
setupForces();
return (ForceDetails.get(8).toString());
} else {
return "\nNo such force";
}
}
private void setupForces()
{
ForceDetails.add(new starShip("IW1","Twisters",200,200,ForceState.DOCKED,10,0,0,false));
ForceDetails.add(new starShip("SS2","Enterprise",300,200,ForceState.DOCKED,0,10,20,false));
ForceDetails.add(new starShip("WB3","Droop",300,100,ForceState.DOCKED,0,0,0,false));
ForceDetails.add(new starShip("IW4","Wingers",200,400,ForceState.DOCKED,20,0,0,false));
ForceDetails.add(new starShip("WB5","Hang",400,300,ForceState.DOCKED,0,0,0,true));
ForceDetails.add(new starShip("SS6","Voyager",450,200,ForceState.DOCKED,0,15,10,false));
ForceDetails.add(new starShip("SS7","Explorer",120, 65,ForceState.DOCKED,0,4,5,false));
ForceDetails.add(new starShip("WB9","Hover",300,400,ForceState.DOCKED,0,0,0,false));
ForceDetails.add(new starShip("IW10","Flyers",200,100,ForceState.DOCKED,5,0,0,false));
}
The obvious choice would be a switch statement over ref:
switch (ref) {
case "IW1":
setupForces();
return (ForceDetails.get(0).toString());
break;
case "SS2":
setupForces();
return (ForceDetails.get(1).toString());
break;
// etc.
}
If the code to execute always looks the like this (calling setupForces() and getting the n-th element of ForceDetails) you could also use a map that lets you retrieve n (Map<String, Integer>) which you populate with key-value-pairs like "IW1"->0 and "SS2"->1 etc.
The map solution also has the charme that you do not need to repeat the code that is basically equal for all cases which would be rather inconvenient if you have to change this later.
Well there is no inbuilt solution to that. What you can do is create a Map of condition -> result and return the value to the key.
Map<String, String> mapCondToRes = new HashMap<>();
public String getForceDetails(String ref) {
setupForces();
return mapCondToRes.get(ref);
}
You can check for validations and put more conditions very easily and elegantly.
In the existing code, each invocation of getForceDetails with a valid ref causes adding of 9 entries to a collection of starships ForceDetails. It is doubtful that this behaviour is intended, possibly a lazy initialization of ForceDetails was implied.
Next, to get rid of the multiple if statements using of the map is definitely more preferable than converting into switch statement and copying the same multiple calls to setupForces(). It could make sense to create a map Map<String, starship> instead of the list and populate it in setupForces (so there's no need to have a separate map of references to the index in the list):
Map<String, starShip> forces = new HashMap<>();
private void setupForces() {
forces.put("IW1", new starShip("IW1","Twisters",200,200,ForceState.DOCKED,10,0,0,false));
forces.put("SS2", new starShip("SS2","Enterprise",300,200,ForceState.DOCKED,0,10,20,false));
// ... add other starships mapped by their ids
}
public String getForceDetails(String ref) {
if (forces.isEmpty()) {
setupForces();
}
return Optional.ofNullable(forces.get(ref))
.map(starShip::toString)
.orElse("No such force found");
}
Use a java stream, you should read about them, you'll find it useful later as you progress on Java.
For the following code, I assume you have a getter for your "key" values inside your starShip class ("IW1", "SS2", "WB3"...).
This code also assumes that you cannot change your current List approach, If you can, a Map would be a even better.
private static final String NO_FORCE = "\nNo such force";
public String getForceDetails(String ref) {
String result = ForceDetails.stream() // <-- It's even faster if you use `parallelStream` however is known to have non-thread-safe issues
.filter(starShipItem -> Objects.equals(starShipItem.getKey(), ref))
.map(String::valueOf).findFirst()
.orElse(NO_FORCE)
;
if (NO_FORCE.equals(result)) {
return NO_FORCE;
}
setupForces();
return result;
}
Also, I recommend you to take a look at hackerrank challenges, you'll learn a lot more there.
I have multiple conditions to check as shown below,
if(pouch.getStatus().equals("Finalized") || pouch.getStatus().equals("Ready")
|| pouch.getStatus().equals("Checkout") || pouch.getStatus().equals("Confirmed")
|| pouch.getStatus().equals("Book") || pouch.getStatus().equals("Started")
|| pouch.getStatus().equals("Inital") || pouch.getStatus().equals("Close")) {
// Body Implementation
}
Is there any easy way to check above conditions similar like SQL INcondition, so that code look simpler?
Let's take a look about SQL in features
SQL WHERE IN returns values that match values in a list
So I would use a collection, which implements from Collection<E> and had contains method, make the if statement simpler.
contains(Object o) Returns true if this set contains the specified element.
contains effect is very similar to SQL in.
1.add your multiple conditions in the collection, which implements from Collection<E>
Set<String> dict = new HashSet<String>();
dict.add("Finalized");
dict.add("Ready");
dict.add("Checkout");
dict.add("Confirmed");
dict.add("Book");
dict.add("Started");
dict.add("Inital");
dict.add("Close");
2.using contains to check input value whether exist in the collection.
if (dict.contains(pouch.getStatus()))
{
// do your logic
}
You can use the method matches which is available in String class,
if(pouch.getStatus().matches("Finalized|Ready|Checkout|Confirmed|Book|Started|Inital|Close")){
//your implementation goes here
}
List<String> listOfInputs = new ArrayList<String>();
// add elements in listOfInputs...
boolean isAvailable = listOfInputs.contains(pouch.getStatus());
SQL IN might return more than one result, but in your question, if one condition is satisfied the operation will terminate and return.
You can create an enum to hold all your conditions as shown below.
Assuming your Pouch class is this.
public class Pouch {
private final String status;
public Pouch(final String status) {
this.status = status;
}
public String getStatus() {
return status;
}
}
Here is your enum with the pouch status.
public enum PouchEnum {
Finalized, Ready, Checkout, Confirmed, Book, Started, Inital, Close
}
and check your condition as shown below.
if (PouchEnum.valueOf(pouch.getStatus()) != null) {
// Do some stuff
}
To make it cleaner you can use EnumUtils from apache commons-lang3 this make your code checking more cleaner as shown below.
if (EnumUtils.isValidEnum(PouchEnum.class, pouch.getStatus())) {
// Do some stuff
}
I hope this will help your code to be cleaner.
You can create custom function:
static boolean inCondition(String var, String... ins) {
for (String in : ins) {
if (in.equals(var)) return true;
}
return false;
}
and then use it in this way:
public static void main(String[] args) {
String pouch = "Ready";
if (inCondition(pouch, "Finalized", "Ready", "Checkout" ... )) {
// do something
}
}
Below snippet might help you.
String status = "COMPLETED";
List<String> statusList = new ArrayList<>(Arrays.asList("COMPLETED","INPROGRESS"));
if(statusList.contains(status)){
// do your stuff
}
Using Arrays.asList and then use contains might be the best way at least on my case.
if(Arrays.asList("Finalized", "Ready", "Checkout", "Confirmed",
"Book", "Started", "Inital", "Close").contains(pouch.getStatus())) {
// Body
}
I think if you use the "switch" conditional, the code reads better:
switch (pouch.getStatus()) {
case "Finalized":
case "Ready":
case "Checkout":
case "Confirmed":
case "Book":
case "Started":
case "Inital":
case "Close":
// your code
break;
}
For this particular scenario, I think it's a good candidate for a simple enum like this:
public enum PouchStatus {
FINALIZED, READY, CHECKOUT, CONFIRMED, BOOK, STARTED, INITIAL, CLOSE
}
Usage:
if(PouchStatus.valueOf(pouch.getStatus().toUpperCase()) != null) {
}
You can also move this string sanitizing logic inside a static method in the enum, which would look like this:
public enum PouchStatus {
FINALIZED, READY, CHECKOUT, CONFIRMED, BOOK, STARTED, INITIAL, CLOSE
public static PouchStatus fromDescription(String desc) {
return Arrays.stream(PouchStatus.values()).filter(e -> e.name().equalsIgnoreCase(desc)).findFirst().orElse(null);
}
}
Usage:
if (PouchStatus.fromDescription(pouch.getStatus()) != null) {
}
As a final note, if the Pouch object comes from ORM (e.g.: hibernate/jpa) you can just map these values to the according enum elements right in the entity mapping (pouc.getStatus() would already return a PouchStatus object instead of a String).
Here is full example
public class InConditionJava {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] arr = { "Finalized", "Ready", "Checkout" };
checkData(arr);
}
private static void checkData(String[] arr) {
Set<String> names = new HashSet<String>(Arrays.asList(arr));
System.out.println("AS Checkout is there in our arr is should return True>>" + names.contains("Checkout")); // true
System.out.println(names.contains("Book")); // false
}
}
Here is another way of initializing List in one line with all statuses, and then checking if the list contains the given status.
// Java 9 way of initializing List with one line
List<String> statuses = List.of("Finalized", "Ready", "Checkout", "Confirmed",
"Book", "Started", "Inital", "Close");
if (statuses.contains(pouch.getStatus())) {
// Body
}
You can create an array of all status, then check if pouch.getStatus() in in that list or not?
public String[] statusArray = new String[]{ "Finalized", "Ready","Checkout","Confirmed", "Book", "Started", "Inital", "Close"};
if( Arrays.asList(statusArray).contains(pouch.getStatus())){
//do something
}
There are already plenty of options here, but you could also use Stream for this task, if the version of the JDK you are using is >= 8:
String status = pouch.getStatus();
if (Stream.of(
"Finalized",
"Ready",
"Checkout",
"Confirmed",
"Book",
"Started",
"Inital",
"Close")
.anyMatch(status::equals)) {
// Body
}
The downside of this method, compared to Collection#contains, is that you must make sure that pouch.getStatus() is not null, otherwise you will get a NullPointerException.
I need help in converting an If-case into a switch statement and I'm working on enums.
An example of my enum is as below :
private enum FruitsType{
Apple("Apple"), Orange("Orange"), Mango("Mango"); }
And my method which contains If and Else-if Statements is as follows :
private String getFruitsPrefMsg() {
String message = getMessage();
if (message == null) {
message = getOtherMessage(); }
if(FruitsType.Apple.toString()) {
//return something; }
else if(FruitsType.Orange.toString()) {
// return something; }
else if(FruitsType.Mango.toString()) {
// return something; }
}
Not considering the logic in the code as this is just an example of my code, Can someone please help me to convert this aforementioned if and else-if statements(including the check for null) into a simple switch case, I would need the most simplest code possible using swtich. I want to use switch here as this is the criteria and I have to use switch statement.
I don't understand your conditions, you are not using the obtained message at all.
I would make the enum as follows:
private enum FruitsType {
Apple,
Orange,
Mango
}
As for the switch block, I would probably do something like:
private String getFruitsPrefMsg() {
String message = getMessage();
if(message == null)
message = getOtherMessage();
try {
switch(FruitsType.valueOf(message)) {
case Apple:
//return something
case Orange:
//return something
case Mango:
//return something
}
} catch(IllegalArgumentException exception) {
//Message is not in the enum.
//Handle error
//You can return something here
}
//Or return something here
}
I know the try-catch block is pretty ugly, but that's the easiest solution i'm able to think of.
Good luck with that.
I have read a lot of topics about code refactoring and avoiding of if else statements. Actually, I have a class where I am using a lot of if - else conditions.
More details: I am using the pull parser and on each line of my soap response, I will check if there is a tag I am interested on, if not, check another tag etc:
if(eventType == XmlPullParser.START_TAG) {
soapResponse= xpp.getName().toString();
if (soapResponse.equals("EditorialOffice")){
eventType = xpp.next();
if (xpp.getText()!=null){
editorialOffice += xpp.getText();
}
}
else if (soapResponse.equals("EditorialBoard")){
eventType = xpp.next();
if (xpp.getText()!=null){
editorialBoard += xpp.getText();
}
}
else if (soapResponse.equals("AdvisoryBoard")){
eventType = xpp.next();
if (xpp.getText()!=null){
advisoryBoard += xpp.getText();
}
}
}
eventType = xpp.next();
}
Now, I would like to use something else, instead of those if else conditions, but I don't know what.
Can you please give me an example?
Try to look at the strategy pattern.
Make an interface class for handling the responses (IMyResponse)
Use this IMyResponse to create AdvisoryBoardResponse, EditorialBoardResponse classes
Create an dictionary with the soapresponse value as key and your strategy as value
Then you can use the methods of the IMyResponse class by getting it from the dictionary
Little Example:
// Interface
public interface IResponseHandler {
public void handleResponse(XmlPullParser xxp);
}
// Concrete class for EditorialOffice response
private class EditorialOfficeHandler implements IResponseHandler {
public void handleResponse(XmlPullParser xxp) {
// Do something to handle Editorial Office response
}
}
// Concrete class for EditorialBoard response
private class EditorialBoardHandler implements IResponseHandler {
public void handleResponse(XmlPullParser xxp) {
// Do something to handle Editorial Board response
}
}
On a place you need to create the handlers:
Map<String, IResponseHandler> strategyHandlers = new HashMap<String,IResponseHandler>();
strategyHandlers.put("EditorialOffice", new EditorialOfficeHandler());
strategyHandlers.put("EditorialBoard", new EditorialBoardHandler());
Where you received the response:
IResponseHandler responseHandler = strategyHandlers.get(soapResponse);
responseHandler.handleResponse(xxp);
In this particular case, since the code is essentially identical for all 3 case except for the String being appended to, I would have a map entry for each of the Strings being built:
Map<String,String> map = new HashMap<String,String>();
map.put("EditorialOffice","");
map.put("EditorialBoard","");
map.put("AdvisoryBoard","");
// could make constants for above Strings, or even an enum
and then change your code to the following
if(eventType == XmlPullParser.START_TAG) {
soapResponse= xpp.getName().toString();
String current = map.get(soapResponse);
if (current != null && xpp.getText()!=null) {
map.put( soapResponse, current += xpp.getText());
}
eventType = xpp.next();
}
No "if... then... else". Not even the added complexity of multiple classes for strategy patterns, etc. Maps are your friend. Strategy is great in some situations, but this one is simple enough to be solved without.
In Java 7 you can SWITCH on Strings. You could use that if you could use that ;-)
Besides zzzzzzz(etc.)'s comment... keep in mind that you are using XmlPullParser which makes you write ugly code like the one you have. You could register some callbacks that would split your code and make it 'better', but if possible, just use SimpleXML library or similar.
Also, you can refactor your code to make it more readable and less verbose. For instance, why do you call xpp.next() inside each if statement? Why not just calling it outside just once:
if(eventType == XmlPullParser.START_TAG) {
soapResponse= xpp.getName().toString();
if (soapResponse.equals("EditorialOffice") && xpp.getText()!=null){
editorialOffice += xpp.getText();
}
else if (soapResponse.equals("EditorialBoard") && xpp.getText()!=null){
editorialBoard += xpp.getText();
}
else if (soapResponse.equals("AdvisoryBoard") && xpp.getText()!=null){
advisoryBoard += xpp.getText();
}
}
eventType = xpp.next();
You could create a ResponseHandler interface with three implementations, one for each branch of your if/else construct.
Then have either a map mapping the different soapResponses to a handler, or a list with all the handler if it can handle that soapResponse.
You also should be able to move some of the boilerplate code to a common possibly abstract implementation of the response handler class.
As so often there a many variations of this. By utilizing the code duplication one actually needs only one implementation:
class ResponseHandler{
String stringToBuild = "" // or what ever you need
private final String matchString
ResponseHandler(String aMatchString){
matchString = aMatchString
}
void handle(XppsType xpp){
if (xpp.getName().toString().equals(matchString){
eventType = xpp.next();
if (xpp.getText()!=null){
editorialOffice += xpp.getText();
}
}
}
}
Your code becomes
List<ResponseHandler> handlers = Arrays.asList(
new ResponseHandler("EditorialOffice"),
new ResponseHandler("EditorialBoard"),
new ResponseHandler("AdvisoryBoard"));
if(eventType == XmlPullParser.START_TAG) {
for(ResponseHandler h : handlers)
h.handle(xpp);
}
vast question that is this one and there is no real answer. (and I don't use soap very often)
here a just some ideas based on your code:
first you can groupe duplicate code
if (soapResponse.equals("EditorialOffice")
||soapResponse.equals("EditorialBoard")
||soapResponse.equals("AdvisoryBoard")){
Another good thing you can do is play around with switch staments like:
switch(soapResponse){
case "EditorialOffice":
case "EditorialBoard":
case "AdvisoryBoard":
eventType = xpp.next();
if (xpp.getText()!=null){
advisoryBoard += xpp.getText();
}
break;
Also you should consider breaking down you test into small functions:
public bool interestingTag(string s){
return (soapResponse.equals("EditorialOffice")
||soapResponse.equals("EditorialBoard")
||soapResponse.equals("AdvisoryBoard"));
}
public processData(xpp){
eventType = xpp.next();
if (xpp.getText()!=null){
editorialBoard += xpp.getText();
}
....}
So that you can just process all your answers in a while loop and you super long if else becomes a 5~10 line function
But as I said there are so many good ways of doing the same thing
You haven't mentioned if you can or do use Java 7. As of that java version you can use Strings in switch statements.
Other than that, encapsulating the logic for each case is a good idea, for example:
Map<String, Department> strategyMap = new HashMap<String, Department>();
strategyMap.put("EditorialOffice", new EditorialOfficeDepartment());
strategyMap.put("EditorialBoard", new EditorialBoardDepartment());
strategyMap.put("AdvisoryBoard", new AdvisoryBoardDepartment());
Then you can simply select the correct strategy from the Map and use it:
String soapResponse = xpp.getName();
Department department = strategyMap.get(soapResponse);
department.addText(xpp.getText());
Department is of course in interface...
You can define an enum like the following:
public enum SoapResponseType {
EditorialOffice(1, "description here") {
public void handle(XmlPullParser xpp) {
//do something you want here
return null;
}
},
EditorialBoard(2, "description here") {
public void handle(XmlPullParser xpp) {
//do something you want here
return null;
}
},
AdvisoryBoard(3, "description here") {
public void handle(XmlPullParser xpp) {
//do something you want here
return null;
}
};
public static SoapResponseType nameOf(String name) {
for (SoapResponseType type : values()) {
if (type.getName().equalsIgnoreCase(name)) {
return type;
}
}
return null;
}
public void handle(XmlPullParser xpp) {
return null;
}
}
Use above enum like this:
SoapResponseType type = SoapResponseType.nameOf("input string");
if (type != null) {
type.handle(xpp);
}
It's clean code, isn't it!
I'd like to call a method that either returns false, or an integer. At the moment my code is:
int winningID = -1;
if((ID = isThereAWinner()) != -1) {
// use the winner's ID
} else {
// there's no winner, do something else
}
private int isThereAWinner() {
// if a winner is found
return winnersID;
// else
return -1;
}
I don't like the if((ID = isThereAWinner()) != -1) bit as it doesn't read very well, but unlike C you can't represent booleans as integers in Java. Is there a better way to do this?
I would use something similar to Mat's answer:
class Result {
public static Result withWinner(int winner) {
return new Result(winner);
}
public static Result withoutWinner() {
return new Result(NO_WINNER);
}
private static final int NO_WINNER = -1;
private int winnerId;
private Result(int id) {
winnerId = id;
}
private int getWinnerId() {
return winnerId;
}
private boolean hasWinner() {
return winnerId != NO_WINNER;
}
}
This class hides the implementation details of how you actually represent if there were no winner at all.
Then in your winner finding method:
private Result isThereAWinner() {
// if a winner is found
return Result.withWinner(winnersID);
// else
return Result.withoutWinner();
}
And in your calling method:
Result result = isThereAWinner();
if(result.hasWinner()) {
int id = result.getWinnerId();
} else {
// do something else
}
It may seem a little bit too complex, but this approach is more flexible if there would be other result options in the future.
What about something like:
private int getWinnerId() {
// return winner id or -1
}
private boolean isValidId(int id) {
return id != -1; // or whatever
}
int winnerId = getWinnerId();
if (isValidId(winnerId)) {
...
} else {
...
}
This is all quite subjective of course, but you usually expect an isFoo method to provide only a yes/no "answer".
The problem is you are trying to return two values at once. The approach you have taken is the simplest for this. If you want a more OO or design pattern approach I would use a listener pattern.
interface WinnerListener {
void onWinner(Int winnerId);
void noWinner();
}
checkWinner(new WinnerListener() {
// handle either action
});
private void checkWinner(WinnerListener wl) {
// if a winner is found
wl.onWinner(winnersID);
// else
wl.noWinner();
}
This approach works well with complex events like multiple arguments and multiple varied events. e.g. You could have multiple winners, or other types of events.
I'm afraid not. To avoid errors caused by mistaking if(a == b) for if(a = b), Java removes the conversion between boolean type and number types. Maybe you can try exceptions instead, but I think exception is somewhat more troublesome. (My English is not quite good. I wonder if I've made it clear...)
Perhaps you may wish to consider exceptions to help you with your understanding of asthetics of coding.
Use Integer instead of int and return null instead of -1. Look from this point: "I am returning not integer, but some object that represents winner identity. No winner - no instance"
Joe another suggestion, this is constructed based on #Mat and #buc mentioned little while ago, again this is all subjective of course I'm not sure what the rest of your class/logic is. You could introduce an enum with different ResultStatuses if it makes sense within the context of your code/exmaple.
As Matt mentioned you would expect isValid method to return a boolean yes/no (some may also complain of readability)
public enum ResultStatus {
WINNER, OTHER, UNLUCKY
}
This could be an overkill as well and depends on the rest of your logic (and if logic is expanding) but I thought I'll suggest nonetheless my two cents! So therefore in your public class (similar to #bloc suggested) you could have a method such as below that will return the status of the result checked.
public ResultStatus getResultStatus() {
if (isWinner()) {
return ResultStatus.WINNER;
} else {
return isOtherCheck() ? ResultStatus.OTHER : ResultStatus.UNLUCKY;
}
}