'A design pattern approach to return both boolean and strings

I want to write a method in java which receives an array of objects, checks for some compatibility and return a boolean value true if all meet, otherwise to return a string containing a message to inform user why some of the compatibilities don't meet. I came up with simplified version of my question as follows:

Suppose you wanna compare cars and in order that comparison make sense you wanna make sure all are of same class, same color, same make.

So what I am trying to get from this method are two:

1- are all care compatible? (boolean using return)

2- if not, why? so to inform user of the reasons(String using throw)

What is the best design pattern for this?

Below is one way of implementing it:

boolean areCarsCompatible(Car [] cars) throws CarException {
String errorMessage = "";
   for(Car car:cars){
    if (cars done have same color) errorMessage +="Cars dont have same color";
   }

   for(Car car:cars){
    if (cars done have same make) errorMessage +="Cars dont have same make";
   }

   for(Car car:cars){
    if (cars are not all of same class) errorMessage +="cars are not all of same class";
   }

   if (errorMessage.equals("")){
    return true 
   } else {
       throw new  CarException (errorMessage);
   }

 }


Solution 1:[1]

to return both boolean and strings

Although you can do this in other (dynamic) programming languages, it's strongly recommended that you don't design your method like this in Java. In Java, types are statically checked and strict, you simply can't return two different types from the same method, and throwing an exception when you intend to return a string is, well, just an ugly hack.

A different matter would be throwing an exception with a message to indicate an error, that's a very common practice and within the good practices of the language. But notice that you wouldn't be "returning both boolean and strings", an exception is intended for error handling.

Solution 2:[2]

There is a lot to address here.

First, you are seeking a design, an approach, an algorithm, etc., but please don't call this a design pattern. That term has a very specific meaning.

OK, nitpicking semantics aside, your approach is a bit awkward for a couple of reasons. First, the boolean is sort of useless because you don't care about "falseness." Either it all works, or you get a message of some kind. The value false has no value for you.

The other reason it is awkward is as @OscarLopez suggests. There is no neat way in Java, as in Ruby for example, to return a multi-type value.

I will say though that if you are going to throw an exception, your CarException is getting close to the right approach--if it is a checked exception as it seems. I strongly disagree with @cherouvim (though I didn't downvote) that it should be a RuntimeException. You want the caller to know about it and to have to deal with it.

As for my own suggestions for solutions, I have two:

1) Maintain some notion of the criteria necessary for a Car to be in the collection. Then simply don't add a Car to the collection if it doesn't meet those criteria. In other words, solve the problem by preventing it from ever happening in the first place.

2) Use Enums.

public enum CarFeedback {
        ALL_SAME, DIFFERENT_COLORS, DIFFERENT_MAKES, DIFFERENT_CLASSES 
}

public CarFeedback checkCars(List<Car> cars) {
      //Do checks 

      return ALL_SAME; //or whichever enum value is appropriate

}

Solution 3:[3]

Your method can be void and throw an exception if there are any problems. There is no need for it to return a boolean. The caller should assume that if no exception was thrown then everything is OK. This is exactly how exceptions were designed to be used.

I would rename the method:

void checkCompatibilityOf(Car... cars) throws IncompatibleCarsException


Alternative approach: Inversion of Control

Rather than returning a value from the method, you can ask the method to callback with its answer(s). E.g.

interface CompatibilityListener {

    void onSuccess();

    void onFailure(String message); 
}

This will avoid the need for a boolean return value, and remove the need for exceptions.

You could go further and extract the logic of building the error message too:

interface DifferenceListener {

    void onDifferentColor(Car car1, Car car2);

    void onDifferentMake(Car car1, Car car2);

    //etc.
}

And this method:

public void checkCompatibilityOf(DifferenceListener listener, Cars... cars) {

    for (Car car: cars) {
       if (...) {
           listener.onDifferentColor(car1, car2);
       }
       if (...) {
           listener.onDifferentMake(car1, car2);
       }
       // etc.    
    }
}

Inversion of control can be a powerful approach in some cases, although, as Vidya says (in the comment) it's probably over-engineering in your case!

Solution 4:[4]

You can do everything you want with JAVA. You can create your own class to get the object with any included values you prefer. See below :

import java.math.BigInteger;
import java.util.Date;


public class BoolVariable {

private static BoolVariable instance;
public static BoolVariable BOOLVARIABLE = getInstance();
private boolean bool;
private char c;
private String s;
private int i;
private double d;
private float f;
private BigInteger bi;
private Date date;

private static BoolVariable getInstance() {
    if (instance == null) {
        instance = new BoolVariable();
    }
    return instance;
}

private BoolVariable() {
}

public BoolVariable(boolean bool, char c) {
    this.bool = bool;
    this.c = c;
}

public BoolVariable(boolean bool, String s) {
    this.bool = bool;
    this.s = s;
}

public BoolVariable(boolean bool, int i) {
    this.bool = bool;
    this.i = i;
}

public BoolVariable(boolean bool, double d) {
    this.bool = bool;
    this.d = d;
}

public BoolVariable(boolean bool, float f) {
    this.bool = bool;
    this.f = f;
}

public BoolVariable(boolean bool, BigInteger bi) {
    this.bool = bool;
    this.bi = bi;
}

public BoolVariable(boolean bool, Date date) {
    this.bool = bool;
    this.date = date;
}



public boolean getBool() {
    return bool;
}

public char getC() {
    return c;
}

public String getS() {
    return s;
}

public int getI() {
    return i;
}

public double getD() {
    return d;
}

public float getF() {
    return f;
}

public BigInteger getBi() {
    return bi;
}

public Date getDate() {
    return date;
}

public void setBool(boolean bool) {
    this.bool = bool;
}

public void setC(char c) {
    this.c = c;
}

public void setS(String s) {
    this.s = s;
}

public void setI(int i) {
    this.i = i;
}

public void setD(double d) {
    this.d = d;
}

public void setF(float f) {
    this.f = f;
}

public void setBi(BigInteger bi) {
    this.bi = bi;
}

public void setDate(Date date) {
    this.date = date;
}

public BoolVariable create(boolean bool, char c){
    return new BoolVariable(bool, c);
}
public BoolVariable create(boolean bool, String s){
    return new BoolVariable(bool, s);
}
public BoolVariable create(boolean bool, int i){
    return new BoolVariable(bool, i);
}
public BoolVariable create(boolean bool, double d){
    return new BoolVariable(bool, d);
}
public BoolVariable create(boolean bool, float f){
    return new BoolVariable(bool, f);
}
public BoolVariable create(boolean bool, BigInteger bi){
    return new BoolVariable(bool, bi);
}
public BoolVariable create(boolean bool, Date date){
    return new BoolVariable(bool, date);
}

@Override
public String toString() {
    return "BoolVariable{" + "bool=" + bool + ", c=" + c + ", s=" 
            + s + ", i=" + i + ", d=" + d + ", f=" + f + ", bi=" 
            + bi + ", date=" + date + '}';
}

}

You can call this class in any routine that you want to get double variable like below:

BoolVariable bv = BOOLVARIABLE.create(true, "HERE IS YOUR VARIABLE LIKE INTEGER, STRING ETC");

So then you can get any value like bv.getBool();

Solution 5:[5]

One idea is to always return boolean but if a condition is not met then you throw a flavour of RuntimeException describing the problem. The caller of this method should handle that.

Solution 6:[6]

I know this question is pretty old but I still think this method will clear up a lot of things given the nature of the question. Particularly where it says "... a method in java which receives an array of objects, checks for some compatibility and return a boolean value true if all meet, otherwise to return a string containing a message to inform user why some of the compatibilities don't meet ..." Judging from the question incompatible cars are not supposed to be an error, it is actually as per design part of the behavior of the program, meaning that the car can be compatible or not and from what you want to do you want to know why it is not compatible. If all my current assumptions are right I would rather write my method to return Boolean and incase the method returns a false cause the cars do not match I create a local methods and property in my class getCompareErrorMsg() and compare_error_msg before returning the false in this given method I set the compare_error_msg to the exact comparison error msg, which from what I understand from your question was what you wanted to return as string. so the caller of the method check for it's Boolean value, if it is false the caller can call the method getCompareErrorMsg() which actually returns a string and do what ever it wants to do with it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Óscar López
Solution 2 Vidya
Solution 3
Solution 4 Stefanidis
Solution 5 cherouvim
Solution 6 Marcel