1

I am currently working on a project that involves creating an array of objects(in this case, hardware tools from a created ToolItem class), and then creating a class file manipulate this data. The class I am creating now, named HardwareStore, has methods to search, insert and delete private data members for items in my array. Using a method named assign() from the previously mentioned ToolItem class, I call the set methods for each data member and assign them to a spot in the array. Assign looks like:

public void assign(int quality, String name, int id, int numInStock, double price)
    {
        setQuality(quality);
        setToolName(name);
        setID(id);
        setNumberInStock(numInStock);
        setPrice(price);
    }

My insert method currently looks like:

public int insert(int quality, String name, int id, int numInStock, double price)
    {
        //testing the unique ID passed by the user,
        //making sure there isn't an object in the
        //array with the same ID
        testArray = searchArray(id);

        //array holds a max of 10 objects
        if (numberOfItems == 10)
        {
            System.out.println("Array is full");
            return 0;
        }
        //-1 is sentinel value from search method,
        //telling me there isn't an object with the
        //same specified ID
        else if (testArray == -1)
        {   
            for (index = 0; index < toolArray.length; index++)
            {
                if (toolArray[index].getToolID() == 0)
                {
                    toolArray[index].assign(quality, name, id, numInStock, price);
                    numberOfItems++;    //counter for array
                    return 1;          
                }
            }//end for loop
        }
        return -1;    //sentinel value telling me there was a dupe ID

    }//end insert

I am supposed to validate the toolArray[index].assign(quality, name, id, numInStock, price); using a boolean variable in this manner, though:

boolean oK = toolArray[index].assign(quality, id, numInStock, price);

If oK == true, I then increment the number of items in the array. In order for this to work, I would need assign() to have a return type of boolean. This is how it was explained to me:

Yes you will want an Assign method. All that goes into it are calls to "set" values to there appointed places. The assign method will return a value depending on whether or not the value was assigned/inserted. You will need to check the value of oK to make sure it is true or false.

My issue is, I do not know how to change the assign() return type to boolean and make the method work properly. My first thought was something like:

if (setQuality(quality) == true)
{
    return true;
}
else if (setToolName(name) == true)
{
    return true;
}
else
    return false;

but this obviously doesn't work and results in several compiler errors :/ I just don't understand the logic behind this kind of data checking. If someone understands this and could help me, I would greatly appreciate it!

FuegoJohnson
  • 372
  • 6
  • 18

2 Answers2

1

Well, considering that your assign method only contains setter methods that assign primitive values or Strings to inner fields, there isn't much that can go wrong with that so the simplest way to achieve what you want is just to return true at the end of assign():

public boolean assign(int quality, String name, int id, int numInStock, double price)
{
    setQuality(quality);
    setToolName(name);
    setID(id);
    setNumberInStock(numInStock);
    setPrice(price);
    return true;
}

Now if you have specific values that are illegal for your parameters, for example a negative integer for id, or null for the name, you can add a check inside each of your setter methods for the illegal values. If those values get passed you can throw an Exception such as IllegalArgumentException or you can make a custom exception even if you'd like. Here's how it would look for the setID() method:

void setID(int id) throws IllegalArgumentException {
    if(id < 0) {
        throw new IllegalArgumentException();
    } else {
        this.id = id;
    }
}

Then, assuming all of your setters throw the same exception, you can add a try/catch block to the assign() method and return false if any the setter methods received the illegal values. Code would look like:

public boolean assign(int quality, String name, int id, int numInStock, double price)
{
    try {
        setQuality(quality);
        setToolName(name);
        setID(id);
        setNumberInStock(numInStock);
        setPrice(price);
    } catch (IllegalArgumentException iae) {
        return false;
    }
    return true;
}

If your methods need to throw different exceptions for some reason, then you can separate exception in the catch block like:

catch (ExceptionOne e1 | ExceptionTwo e2 ....) {
    return false;
}

Using Exceptions is ok in this case since having one of these values be invalid is a systematic logic failure and should be noted. An illegal id or name corrupts your system logic and therefore should be handled with a proper exception. Also, this will probably never happen or happen very rarely so it would literally be an "exception" to the logic of your program.

However, if for example, you had a function that asks the user for the name of a tool they want and the user gives you an invalid tool name, you don't need to throw an exception there because that doesn't make your system have an error, that's just user not knowing how to use the system or just not knowing his tool names. In that case you can just return an error value like null or false.

nem035
  • 34,790
  • 6
  • 87
  • 99
  • Thanks nem for the quick response! I'm about to test it real quick and see if it works, but it definitely looks like it should! My set methods have their own custom exceptions(at least I think they do based off what you said). For example, if quality data member isn't between 1 and 3, its set to 0, ect. This is how I was instructed, although I like your way better :) – FuegoJohnson Sep 29 '14 at 00:12
  • @FuegoJohnson you are welcome :). Let me know if you get stuck – nem035 Sep 29 '14 at 00:20
  • Much appreciated! There needs to be more people like you on this website – FuegoJohnson Sep 29 '14 at 00:26
  • Still thinking that Exceptions should not be used for flow control. Besides, it decreases readability of the code and performance. This is one of the most common antipattern. I know it might lead to subjective discussions where sometimes it's a matter of taste. If you look at some literature, you will find that there are more people advocating not to use them in cases like this, than there are in its favor. – Manuel Alejandro Sep 29 '14 at 04:03
  • Suppose you would need to make some other comparisons if the value was < 0. Would you put it in the catch clause then? Logic changes as business requirement change, so it's likely that at some point you will have to change this simple conditions that you have now and then, the catch would make the logic to be spread all over your method. Please read this: http://stackoverflow.com/questions/15208544/when-should-illegalargumentexception-be-thrown – Manuel Alejandro Sep 29 '14 at 04:12
1

Notice that I changed the return type... from void to boolean

public boolean assign(int quality, String name, int id, int numInStock, double price)
    { 

     return
        (setQuality(quality) &&
        setToolName(name) &&
        setID(id) &&
        setNumberInStock(numInStock) &&
        setPrice(price))
    }

Then, notice that I changed the sentences with a condition. If I say return A && B it means that it will return true if both A and B are true, so, following that logic, you construct the entire return sentence and save yourself lots of Ifs..

Using exceptions as flow control structure is a bad practice and antipattern.

Manuel Alejandro
  • 588
  • 4
  • 13
  • Wow I didn't even think of doing it like that! I like the simplicity. Thank you for the easy to understand answer. I will test it and see how it works. Much appreciated! – FuegoJohnson Sep 29 '14 at 00:16
  • I'm getting a compiler error, "The operator && is undefined for the argument type(s) void, void" :/ – FuegoJohnson Sep 29 '14 at 00:23
  • you need to change each of your setter methods to return `boolean` in this case – nem035 Sep 29 '14 at 00:23