• Post Reply Bookmark Topic Watch Topic
  • New Topic

Question regarding horse racing program  RSS feed

 
Christopher Laurenzano
Ranch Hand
Posts: 105
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie (or anyone else) --

Was away and tried to think about this. Maybe I should ask the question regarding my own horseracing program.

I have a couple of classes already -- a class and method for the user to enter the horses he wants to run in a race. The arraylist for it is called entryField. I want to create another class called race that uses the elements in that entryfield. But I've tried to understand the examples given here and use and import statement, but every time I try to use the race class to manipulate the entryField, I get error messages. Can you explain to me what import statements or other statements i need to put in my race class (or the entryField class, or both) so the race class can access the elements in the entryField array list? Even if for right now I just want to display the entryField in the methods for the race class.

I think I asked that the right way.

Perhaps I should include the code for the entryField class here, to make it clearer:



As well, the thoroughbred class describes the fields for each horse, and a little method checks to see if the user has entered the proper number of characters for the horse's name:




The helper in the code is taken from the Head First Java books, and is used to enter the information about the horse. There's only a name so far, but I plan to add age, color, etc. later.
By the way a couple more questions: the helper class only takes a string and parses it into an integer when asking the user which horse he wants to scratch before he decides on the final field. If something other than a number is entered, then I get an number format error message.

There has to be some kind of method to enter either numbers or strings and have java properly interpret it. Can anyone tell me what it is?

 
Christopher Schneider
Greenhorn
Posts: 11
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Holy smokes!

I'd like to help, but I can't figure out what's going on here. You have a method that is 90 lines of code, and that is far, far too long. Your first step, before anything else, is refactor. Some things you definitely need to fix before you progress:

1. Methods should be kept short and do one thing. As an example, on line 56:

You might extract the code beyond that if statement into a method called scratchHorses().
2. You don't need to call System.out.println() to print a new line. This:

can be shortened to

3. Class names need to start with uppercase letters, methods with lowercase letters. e.g. thoroughbred should be Thoroughbred.
4. Give meaningful variable names. Don't do this:

If you can clean up this code, I'd be happy to help. Ideally, a method should only be 10-20 lines.
 
Christopher Schneider
Greenhorn
Posts: 11
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I missed this, but this is a perfect example on how you should refactor. This class:



Logically, think about setName(). What should a method called setName() do? It should set the name. It shouldn't accept user input, do validation, or anything like that. All it should do is set the name. If you want to validate input, create a method called validateName(). If you want to get input from the user, make a method called getUserInput().
 
Campbell Ritchie
Marshal
Posts: 56533
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
… and you can use the getUserInput and validateName methods from inside the setName method.
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:… and you can use the getUserInput and validateName methods from inside the setName method.

I would advise against doing that. The validateName might be fine to call from a method called setName but a method like getUserInput would be best called outside of setName. Separation of concerns is the principle in play here. By convention, a method that starts with "set" has a specific purpose and getting input is not part of that purpose. You can certainly flout that convention but doing so will increase the likelihood of your code violating the Principle of Least Surprise.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Exactly what error message(s) do you get?
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christopher Laurenzano wrote:Can you explain to me what import statements or other statements i need to put in my race class (or the entryField class, or both) so the race class can access the elements in the entryField array list?

That's a road you don't want to get used to going down because it will likely lead you to places where the Law of Demeter and "Tell, Don't Ask" are violated. Violating these will make your code less object-oriented and more procedural in nature.

Most code examples you see that involve lists and for loops are idiomatic but actually very procedural (Edit: "imperative" might be a more appropriate adjective) in nature. This article gives a nice example of the difference: http://www.drdobbs.com/jvm/lambdas-and-streams-in-java-8-libraries/240166818

External iteration (iteration happens outside the object/methods):

In the above code, you ASK the object to give you each of the things it encapsulates so you can do something with them. This is intrusive. Recent additions to the Java language can help you preserve encapsulation and make the code less intrusive on the object being used.

Internal iteration (iteration happens inside the object/methods):

Here, you are TELLing the object what you want it to do with each of its elements.
 
Campbell Ritchie
Marshal
Posts: 56533
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I presume shapes is a List<Shape>? I keep forgetting that some of the methods of Streams are also available in collection interfaces.
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The forEach method comes from the Iterable interface of which List is a subinterface.
 
Christopher Laurenzano
Ranch Hand
Posts: 105
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, y'all --

I re wrote the code in the Entryfield class and separated the various parts into different methods.

So far, here's what I've got -- it's all still in the same class Entryfield. I think this may make it a bit clearer.




As well, here's the re-written Thoroughbred class that sets and gets the name for each horse (age and sex have not yet been incorporated into the program yet).



So my question(s) are these:

First: The input of information works fine for now, except when I get to the scratch () method. If I enter anything other than a number or "done" or just enter, I get a number format exception, and I can't figure out why. Even if I put in a condition in the method to check if the input IS NOT either "done" or enter, I still get the exception.

I know it has something to do with the parseInt method, but I don't know of any other means of input that will take either a number or a string. Is there any other means of input that doesn't require the parsing of a string to a number?

As well, what I want to do eventually is create a race program that will use the entryList objects and run the horse race, but I don't know how to write the race method(s) or class that can do this. I've tried to do it but all I get are various types of errors.

Any other helpful tips are welcome and appreciated.
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christopher Laurenzano wrote:
So my question(s) are these:

First: The input of information works fine for now, except when I get to the scratch () method. If I enter anything other than a number or "done" or just enter, I get a number format exception, and I can't figure out why. Even if I put in a condition in the method to check if the input IS NOT either "done" or enter, I still get the exception.

I know it has something to do with the parseInt method, but I don't know of any other means of input that will take either a number or a string. Is there any other means of input that doesn't require the parsing of a string to a number?

As well, what I want to do eventually is create a race program that will use the entryList objects and run the horse race, but I don't know how to write the race method(s) or class that can do this. I've tried to do it but all I get are various types of errors.

Any other helpful tips are welcome and appreciated.
Yes, you'll need to verify in some way that the string is an integer. The two common ways to do this are:

1) Put a try/catch block around Integer.parseInt(). If it throws an exception then it is not an integer, otherwise proceed as normal. This approach is quick and dirty and is frowned upon because it uses the throw mechanism for what is a non-exceptional event, i.e. you really do expect a non-integer at some point.

2) Create a regular expression ("\\d+") for matching integers and test that prior to performing parseInt(). This is the preferred way.
 
Campbell Ritchie
Marshal
Posts: 56533
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is another wayThat may give you the output 246 is you pass "123 Campbell" to it; try it. \u2019 is a right single quote or apostrophe. I am under no obligation to use correct grammar
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your Scanner approach works in this particular case, however I find Scanner to be temperamental. First off I don't like the results of your "123 Campbell" entry. Secondly there would be a temptation to scan System.in instead of a String, which your example doesn't handle without some additional code.
 
Campbell Ritchie
Marshal
Posts: 56533
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, Scanner is not at all temperamental. It is very predictable.

It is also not at all well documented, so people think method XYZ does something when in fact it does something different. The worst offender is nextLine().
 
Christopher Laurenzano
Ranch Hand
Posts: 105
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I haven't encountered regular expressions yet (I'm reading Head First Java, which for me works well; easy to understand and it makes the ideas comprehensible).

My other question, though is this:

I have plans for a Race class that will determine what type of race is run, the purse amount, distance, etc.

So how would i get this class to use the entryList that I've created in the Entryfield class? For the time being I just want the Race class to show the list of horses in the race. I've tried entryList.showfield(), but all I get is an error message saying the class can't find the variable entryList.

If I'm not mistaken, I think, based on the previous example you gave me, I'd have to use some kind of in import statement, correct? But I'm still unclear on exactly what I have to put in which class(es).
 
Campbell Ritchie
Marshal
Posts: 56533
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Crude rough‑and‑ready suggestion, taught to us when we started learning programming:-
Start by writing a description of horse racing. Go through it and look for all the nouns, and all the verbs. Make a list of them; the list of nouns will be similar to your list of classes and the verbs will suggest which methods to use.
 
Christopher Laurenzano
Ranch Hand
Posts: 105
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not sure I'm being clear.

What I mean was:

if include this in the race class:



When I compile the class, I get this message:

Race.java:4: error: cannot find symbol
entryList.showfield();
^
symbol: variable entryList
location: class Race
1 error

It's not the method, from what I can see. It's the fact that it won't even compile. The methods are public in the Entryfield class, and the entryList Array List is part of the class. But I can't figure out how to get the Race class to use the entryList Array List that's already been created.
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Two of the most important things you have to learn as a programmer is organization and abstraction. Organizing involves keeping things either separate or together, depending on their nature and responsibilities. Abstraction is about writing code that clearly shows the organization while hiding the details of the implementation.

You are kind of on the right track with your thinking about needing certain objects like a Race class or a RaceHelper. Those are a start. However, there are many more things you can do to improve abstraction and organization in your code.

For example, it's best to separate the responsibility of getting user input from everything else in the program. In your code, however, this responsibility is mixed in with other things, such as what you have in your setXXX methods. In Java, the code you normally find in set methods does not include obtaining user input. Rather, a value is passed in to the setter as a parameter. The principle here is called "Separation of Concerns".

Read up on Class-Responsibility-Collaborators as this can be a very useful tool for organizing code in object-oriented languages like Java.

Also, it's very important to carefully think about and choose the names you give your program entities. RaceHelper is not a very good name, even though you may have seen something like it in a book. A good name gives the reader a good idea of the purpose of the thing that's being represented. "Helper" doesn't really tell you much at all. If you think about it, getting user input doesn't really have much to do with the program being about race horses. All you're really doing is displaying a prompt and getting a value. If you separate things that have to do with "racing" from things that have to do with getting user input, you'll be able to organize your code a little bit better and end up with some code that can actually be reused in other programs that have nothing to do with racing but still require the user to enter values.
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christopher Laurenzano wrote:
It's not the method, from what I can see. It's the fact that it won't even compile. The methods are public in the Entryfield class, and the entryList Array List is part of the class. But I can't figure out how to get the Race class to use the entryList Array List that's already been created.


You need to read up about scope of variables and members in Java. You get a compile error because the object you are referencing is not in scope in that part of code. That is, it's not visible from where you reference it, hence you get a compile time error.
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christopher Laurenzano wrote:
But I can't figure out how to get the Race class to use the entryList Array List that's already been created.

This takes us back to what I said earlier about having to organize your code better. Instead of trying to make the Race class access a list that exists outside of it, you should consider putting the list inside the Race class. If the list is something that a Race would be using and maintaining, it might make more sense for a Race to HAVE a list of entries. That is, the list of entries becomes an attribute of a race.

Then, you can write code that looks like this:

This is an example of abstraction -- you can clearly see what's going on and how things are organized but you don't see a lot of the implementation details.
 
Campbell Ritchie
Marshal
Posts: 56533
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you go to a real horse race, you will see that there are several races at a meeting and each race has a field and that field comprises several horses (each with a rider).
So you should consider having a List<Horse> called field inside the Race class.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!