Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
      You have completed Java Objects!
      
    
You have completed Java Objects!
Preview
    
      
  Let's take care of a bug we found surrounding uppercase and lowercase guesses.
Learn more
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
                      So we ran into that slight
little issue that popped up
                      0:00
                    
                    
                      when we added an uppercase value as input.
                      0:03
                    
                    
                      The uppercase value T is different
than the lowercase value of T.
                      0:05
                    
                    
                      So we need to ensure a specific
case in the letters of our data.
                      0:09
                    
                    
                      So when dealing with input, what our end
user is providing us through our prompts,
                      0:13
                    
                    
                      like those letters, there are a few
things that we can and should always do.
                      0:16
                    
                    
                      Firstly, we should check
the correctness of the input.
                      0:21
                    
                    
                      This is called validation.
                      0:23
                    
                    
                      Input that has been checked
is said to be validated.
                      0:25
                    
                    
                      Another option is to modify or
transform the value so
                      0:28
                    
                    
                      that it becomes a valid value.
                      0:32
                    
                    
                      This process is called normalization,
and the data is said to be normalized.
                      0:34
                    
                    
                      So in our, hey, you already guessed
that letter exception example,
                      0:38
                    
                    
                      we validated the input and let the caller
know that the validation had failed.
                      0:42
                    
                    
                      Now, we're looking at a place where
we need to normalize the input.
                      0:47
                    
                    
                      We need to normalize
alphabetic case of our values.
                      0:50
                    
                    
                      So, what we'll do is when we start
the game with new Game("Treehouse"),
                      0:54
                    
                    
                      we'll ensure that the value is lowercase.
                      0:58
                    
                    
                      And then we'll also make sure that any
time someone calls applyGuess on the game
                      1:00
                    
                    
                      object like so, we'll take whatever
they gave us and make it lowercase.
                      1:05
                    
                    
                      A great practice to make sure things are
working as you anticipate is to write what
                      1:10
                    
                    
                      are known as tests.
                      1:14
                    
                    
                      Tests exercise your code and
                      1:15
                    
                    
                      make sure that your code works
exactly as you expected it to.
                      1:16
                    
                    
                      We, unfortunately, are not going to
get into writing tests in this course.
                      1:20
                    
                    
                      But we do offer content that covers
testing, check the Teacher's Notes.
                      1:24
                    
                    
                      So for now, while we're coding up this
validation and normalization a bit,
                      1:28
                    
                    
                      we'll do some quick manual
spot check testing.
                      1:32
                    
                    
                      I'd like you to get a feel for what kind
of tests we might actually write, and
                      1:35
                    
                    
                      show you why they're such a critical
part of writing applications.
                      1:39
                    
                    
                      Let's get to it.
                      1:42
                    
                    
                      Okay, so let's get to work on this bug.
                      1:44
                    
                    
                      I'm gonna pull this over
into In Progress column.
                      1:46
                    
                    
                      And first off,
                      1:50
                    
                    
                      let's make sure that the answer
that's passed in is always lowercase.
                      1:51
                    
                    
                      And we can do that by this,
toLowerCase, right?
                      1:55
                    
                    
                      Remember that on strings toLowercase.
                      1:59
                    
                    
                      Now to tackle the guest side of things,
                      2:01
                    
                    
                      one thing that we haven't even checked is
if our user is even giving us a letter.
                      2:04
                    
                    
                      So let's go explore the character class,
the documentation for the character class.
                      2:09
                    
                    
                      So if we go here and we go Java 8,
and we search for Character.
                      2:13
                    
                    
                      So this first result here.
                      2:19
                    
                    
                      So the character class is a wrapper
class for our primitive data type char.
                      2:21
                    
                    
                      Now much like how we saw integer
wrapper for a class for ints, right,
                      2:26
                    
                    
                      where we used integer.parseInt.
                      2:30
                    
                    
                      Well since a primitive char
doesn't have any methods,
                      2:32
                    
                    
                      this class is used to provide
helper methods for chars.
                      2:35
                    
                    
                      And it does it through, guess what.,
let's go look at the methods here,
                      2:38
                    
                    
                      through static methods.
                      2:43
                    
                    
                      So, here's some common getters and things.
                      2:45
                    
                    
                      But what we're looking for
is we're looking for something that says,
                      2:47
                    
                    
                      is this a letter?
                      2:51
                    
                    
                      So, if we look through here and
we say, is letter.
                      2:52
                    
                    
                      Hey, look at that, it takes a char and
it returns a boolean of true or false.
                      2:55
                    
                    
                      So, let's try it out.
                      3:00
                    
                    
                      Let's pop over to jshell.
                      3:01
                    
                    
                      So, we come in here and we'll say,
Character.isLetter, and
                      3:02
                    
                    
                      I sure hope that a is.
                      3:07
                    
                    
                      And boom, it returns true,
cool, just like we thought.
                      3:09
                    
                    
                      So what happens about the character 2 or
a weird @ or something?
                      3:12
                    
                    
                      Okay, I'll submit it works for
uppercase too right?
                      3:17
                    
                    
                      Great, so I wonder if there's
a toLowerCase for chars,
                      3:21
                    
                    
                      just like we looked at for
the strings, I wonder if that exists.
                      3:24
                    
                    
                      So let's come here and
I'm just going to do a search.
                      3:28
                    
                    
                      And a look for to, look at that,
there it is, toLowerCase.
                      3:30
                    
                    
                      And it's a static method
off of the char and
                      3:33
                    
                    
                      it converts the character
argument to lowercase, cool.
                      3:35
                    
                    
                      So we could also for over here we
could say a character too low and
                      3:38
                    
                    
                      just tap complete and
boom there it is to lower case and
                      3:42
                    
                    
                      if we give it an a That should
return as a lowercase A, beautiful.
                      3:46
                    
                    
                      Okay, so with that information, we should
be able to get a valid lowercase letter
                      3:51
                    
                    
                      and throw an exception
if in fact we don't.
                      3:56
                    
                    
                      You know what?
Now is a great time to show off a concept
                      3:59
                    
                    
                      that we haven't touched on yet,
and that is private methods.
                      4:01
                    
                    
                      So our game object here currently is doing
some validation inside of this applyGuess.
                      4:05
                    
                    
                      Let's go ahead and
let's make a new method and
                      4:11
                    
                    
                      we'll kinda group our
logic together there.
                      4:13
                    
                    
                      So we'll make it private.
                      4:16
                    
                    
                      And by making this private, it will not be
accessible to anyone but the class itself.
                      4:18
                    
                    
                      So we'll say private is gonna return
a chart that has been normalized.
                      4:23
                    
                    
                      All right, so let's say normalizeGuess.
                      4:28
                    
                    
                      And it's gonna take a char and
it's gonna return a char.
                      4:33
                    
                    
                      So again, because it's private, the
prompter, like for instance, the prompter
                      4:37
                    
                    
                      can't say game.normalizeguess,
only our code here can.
                      4:41
                    
                    
                      So this method is a good way to
group common functionality and
                      4:45
                    
                    
                      not clutter up your other methods.
                      4:49
                    
                    
                      Here let's build it.
                      4:51
                    
                    
                      So first we wanna know if
it is not a letter, right?
                      4:53
                    
                    
                      So if it is not a letter,
gonna pass on letter.
                      4:58
                    
                    
                      Ideally this would kinda be
a custom exception, but for
                      5:05
                    
                    
                      now we'll just do a throw new
IllegalArgumentException, right?
                      5:09
                    
                    
                      They passed in a illegal
argument to make a guess.
                      5:13
                    
                    
                      So we'll say a letter is required.
                      5:16
                    
                    
                      So now that we know it's a letter,
we can transform it to lowercase.
                      5:22
                    
                    
                      So we can say letter =, again using
that same character wrapper class,
                      5:25
                    
                    
                      toLowerCase(letter).
                      5:30
                    
                    
                      Awesome, great, now we already have
some validation and applyGuess,
                      5:35
                    
                    
                      why don't we put that in
here in the normalizeGuess.
                      5:39
                    
                    
                      So I'm going to cut that out,
and I'm gonna paste it here.
                      5:42
                    
                    
                      And then finally our normalizeGuess
needs to return the letter, great.
                      5:46
                    
                    
                      So now in applyGuess we can just
call our private method there.
                      5:52
                    
                    
                      We'll say letter = normalizeGuess(letter).
                      5:56
                    
                    
                      See how it keeps things readable?
                      6:02
                    
                    
                      We could very easily just jam all of these
lines in this applyGuess method here.
                      6:04
                    
                    
                      But see how nice and concise this is?
                      6:08
                    
                    
                      Methods provide a great
way to name grouped logic.
                      6:10
                    
                    
                      So how about we do this, let's add
a little smarts to our prompter object.
                      6:14
                    
                    
                      If we come over to prompter object and
we look here at promptForGuess.
                      6:18
                    
                    
                      What if we made this thing just keep
trying until it got a valid guess?
                      6:21
                    
                    
                      Sounds good, right?
                      6:26
                    
                    
                      So there's a couple ways
to do this approach.
                      6:27
                    
                    
                      But first let's move this isHit up the top
here, let's get this stuff down here.
                      6:29
                    
                    
                      So we move isHit to the top.
                      6:36
                    
                    
                      And I'm gonna bring this scanner
definition to the top too.
                      6:38
                    
                    
                      Let's go ahead and do that.
                      6:42
                    
                    
                      It's kinda common to the whole method,
so we'll bring him to the top.
                      6:43
                    
                    
                      We'll set up a new variable there.
                      6:47
                    
                    
                      And let's do a trick here.
                      6:49
                    
                    
                      Let's store a new value that we're gonna
use to keep track of state in this method.
                      6:51
                    
                    
                      Did we get an acceptable value?
                      6:58
                    
                    
                      So we're gonna set that
to default to start with.
                      6:59
                    
                    
                      Okay, so like we said,
we wanna do a loop here.
                      7:02
                    
                    
                      We wanna loop through things, and
we wanna make sure that it happens once.
                      7:05
                    
                    
                      So while we don't have
an acceptable guess, but
                      7:09
                    
                    
                      we wanna make sure it happens once,
so that's a do while loop.
                      7:12
                    
                    
                      So again, that starts like this,
you say do.
                      7:15
                    
                    
                      And then we kinda wanna run all this
stuff, don't we, to right about here.
                      7:18
                    
                    
                      And then we're gonna close that do loop,
see how it's highlighted?
                      7:22
                    
                    
                      And we'll say while,
we'll go not isAcceptable.
                      7:25
                    
                    
                      Speaking of not acceptable,
look at this lineup of this code.
                      7:31
                    
                    
                      Let's go ahead, and
I'm gonna highlight this.
                      7:35
                    
                    
                      And I'm gonna do a command bracket or
a control bracket, right bracket.
                      7:38
                    
                    
                      And it will move,
you can move left or right with that.
                      7:45
                    
                    
                      There we go.
                      7:49
                    
                    
                      So what we wanna do is we wanna
make sure that we flip or
                      7:51
                    
                    
                      change the isAcceptable
value to true here.
                      7:56
                    
                    
                      And what's happening is
if it comes through here,
                      8:02
                    
                    
                      we know that it's valid,
otherwise it's coming here.
                      8:04
                    
                    
                      And now, since we're looping,
we can try to give a cleaner message.
                      8:07
                    
                    
                      So let's switch this to a printf.
                      8:10
                    
                    
                      And we'll put a format string here of,
we'll say, here's your error message.
                      8:12
                    
                    
                      Please try again.
                      8:16
                    
                    
                      The famous Please try again.
                      8:19
                    
                    
                      All right, so we're gonna pump in there,
just like we were before,
                      8:21
                    
                    
                      the exception message that we set, okay.
                      8:26
                    
                    
                      And we're still returning the isHit.
                      8:31
                    
                    
                      So this is gonna loop and
will return isHit, okay.
                      8:33
                    
                    
                      Let's mentally walk this really quick.
                      8:36
                    
                    
                      So this method, promptForGuess is called.
                      8:39
                    
                    
                      And we set up a variable
to know if it's a hit and
                      8:43
                    
                    
                      we set a variable to
know if it's acceptable.
                      8:45
                    
                    
                      Our first iteration through the loop,
                      8:49
                    
                    
                      which will always happen because
we're using a do while loop.
                      8:51
                    
                    
                      It's going to get an input.
                      8:55
                    
                    
                      It's gonna pull off that input.
                      8:58
                    
                    
                      And because our input returns a string,
we have to use this charAt.
                      9:01
                    
                    
                      Sure would be nice if applyGuess took
a string for us, but it doesn't.
                      9:07
                    
                    
                      So anyway, applyGuess takes the guess,
and in here, it does some normalization.
                      9:10
                    
                    
                      So we pass that single charge through and
it has a way of normalizing our char.
                      9:17
                    
                    
                      Let's take a look at that one more time.
                      9:21
                    
                    
                      As we come through applyGuess,
it comes in here,
                      9:23
                    
                    
                      it calls this private
method normalizeGuess.
                      9:25
                    
                    
                      And we pass that original guess through,
                      9:28
                    
                    
                      it comes through here it does
all of our checks that we want.
                      9:30
                    
                    
                      If it makes it all the way through here,
we have a valid letter.
                      9:33
                    
                    
                      If not,
it throws an IllegalArgumentException.
                      9:36
                    
                    
                      Now because one of those exceptions will
break out of this try block, it will run
                      9:39
                    
                    
                      this message, and this isAcceptable
will never be flipped to true.
                      9:43
                    
                    
                      So therefore, when it comes back down
here to check, it will go again, and
                      9:47
                    
                    
                      again, and again.
                      9:52
                    
                    
                      So let's walk that really quick with one.
                      9:54
                    
                    
                      So if the person entered in a 1 here,
and they came and guessed, and
                      9:56
                    
                    
                      the guesser says, trying to be tricky for
some reason, put in a 1.
                      9:59
                    
                    
                      They hit applyGuess,
they come on over to game.
                      10:03
                    
                    
                      It would go to normalizeGuess,
isLetter, false, a letter is required.
                      10:05
                    
                    
                      Here it comes, a letter is required,
please try again.
                      10:08
                    
                    
                      And notice that it jumped
over the isAcceptable.
                      10:12
                    
                    
                      So isAcceptable is still false.
                      10:15
                    
                    
                      So take a second and think about an app
that you've used that takes your input.
                      10:18
                    
                    
                      Now this loop is pretty common right?
                      10:22
                    
                    
                      Whether it be on the web or
on an app on your phone or tablet.
                      10:24
                    
                    
                      Do you follow it?
                      10:27
                    
                    
                      It is totally understandable for
you not to grasp this immediately.
                      10:29
                    
                    
                      This very well may be the first
time that you're thinking about
                      10:32
                    
                    
                      this side of the application.
                      10:35
                    
                    
                      But I know that you've
filled out web forms before.
                      10:37
                    
                    
                      So you've had this experience
that we're creating.
                      10:39
                    
                    
                      So if you need to, go ahead and pause me,
and try to walk through each line there
                      10:41
                    
                    
                      on your own in your head, or
out loud if you aren't in public.
                      10:45
                    
                    
                      Rewind me a bit if you wanna
hear me explain it all again.
                      10:48
                    
                    
                      Okay so, let's give this a test run.
                      10:53
                    
                    
                      I am going to do a clear && javac
Hangman.java && jave Hangman.
                      10:56
                    
                    
                      So let's make sure that we
can't guess a number, right?
                      11:10
                    
                    
                      That was our first exception.
                      11:12
                    
                    
                      A letter is required, beautiful.
                      11:14
                    
                    
                      Nice, and there it is,
it'll keep going and keep on asking me,
                      11:16
                    
                    
                      it's pretty insistent there.
                      11:19
                    
                    
                      So that works.
                      11:20
                    
                    
                      So what happens if I give it a capital H?
                      11:21
                    
                    
                      Awesome, it lowercases it.
                      11:24
                    
                    
                      You know what, actually we moved the code
that tests the checks of duplicate
                      11:26
                    
                    
                      guesses into that normalizeGuess method.
                      11:30
                    
                    
                      So we'd better test that too,
to make sure it's working.
                      11:32
                    
                    
                      So I'm gonna guess an h again.
                      11:35
                    
                    
                      Cool, it says h has already been guessed.
                      11:36
                    
                    
                      And then I'm gonna guess t,
and then Guess it again.
                      11:39
                    
                    
                      Cool, and we're still at seven tries.
                      11:41
                    
                    
                      Nice, we did it.
                      11:44
                    
                    
                      Okay, great, and I just wanna point out
if we had actually written a test for
                      11:45
                    
                    
                      all that,
we'd know that we didn't break it.
                      11:50
                    
                    
                      Because we could just
run a series of tests.
                      11:52
                    
                    
                      But as it stands, we have to test that
every single time we change our code.
                      11:54
                    
                    
                      We would write tests for one, and
we'd write tests for uppercase, and
                      11:57
                    
                    
                      we'd make sure that that worked.
                      12:00
                    
                    
                      In fact, we'd also test what happens if
somebody just came here and pressed Enter.
                      12:02
                    
                    
                      No, look, it's trying to get the first
                      12:07
                    
                    
                      character out of a string that
doesn't have any characters.
                      12:10
                    
                    
                      Well that code was the code we
were wanting to clean up anyway.
                      12:14
                    
                    
                      So let's go ahead and
let's close that issue.
                      12:16
                    
                    
                      And unfortunately,
lets make a new one that says,
                      12:20
                    
                    
                      BUG: Sending no values on
a guess causes a crash.
                      12:26
                    
                    
                      There we go.
                      12:33
                    
                    
                      And let's label that,
let's give that a red label.
                      12:36
                    
                    
                      All right, here we go.
                      12:39
                    
                    
                      Nice job on the looping and
exception handling.
                      12:42
                    
                    
                      Doing that manual testing or QA,
which stands for quality assurance,
                      12:44
                    
                    
                      helped us to uncover another issue that
we should probably fix here shortly.
                      12:48
                    
                    
                      If you don't enter a letter, the
application encounters a critical error.
                      12:52
                    
                    
                      Are you beginning to see how handy
it would be to be able to run
                      12:57
                    
                    
                      a bunch of tests and make sure
everything is working at all times,
                      13:00
                    
                    
                      especially if you change a bit of code?
                      13:03
                    
                    
                      You would just run the test to
make sure everything still works.
                      13:05
                    
                    
                      As it stands, we have to do that ourselves
every single time the code changes.
                      13:08
                    
                    
                      All right, let's refactor in clean up
that code right after this exercise.
                      13:13
                    
              
        You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up