This workshop will be retired on May 1, 2025.
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 Debugging an Existing Java Application!
You have completed Debugging an Existing Java Application!
Preview
Let's leave the campground cleaner than we found it.
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 thanks for taking on that imaginary
demo of our software with our
0:00
imaginary client.
0:03
I'm glad that we took the time to do that,
aren't you?
0:05
As you know already,
it turns out that once we fix the bug
0:07
things weren't working
exactly like they wanted.
0:10
They definitely didn't like that
the counting seemed strange and
0:13
some were getting seen more often.
0:16
However they did like the randomness
of things. With the current set up,
0:17
the same order is returned
through each iteration.
0:21
So they were hoping that we could get
some random shuffling of the cards.
0:24
That seems reasonable for
a study app right?
0:29
Now this is a common issue,
you fix some code and
0:30
the client likes how it used to work.
0:34
The lines between feature and
bug can sometimes get pretty blurry.
0:36
Iβm glad we're getting a chance to
get back in there and clean stuff up.
0:41
I know it had me so confused that I
had to actually walk a line by line.
0:44
I kind of felt bad leaving it that way for
the next poor soul who had to come in and
0:49
decipher what it's doing.
0:52
Right now that only is
living in our brains.
0:53
So there's a saying for
what we're about to do,
0:56
here in the US we have a group
of kids that we call Scouts.
0:59
They get together and they get taught
things about wilderness and survival and
1:02
how to be a good human and all that stuff.
1:06
And they're separated into boy scouts and
girl scouts, and
1:07
somewhere along the lines
in coding a famous phrase
1:11
came up that mirrored one of the rules
from the boy scout side of things.
1:14
Always leave the campground
cleaner than you found it, so
1:18
the idea is you leave the campground clean
because you are thinking about future
1:20
campers who will come and enjoy it.
1:24
You clean it up regardless
of who made the mess
1:27
because you are improving the environment
for future groups of campers.
1:29
So the idea is this, you always check in
code in a better state than you found it.
1:33
The rule has been further
documented as this.
1:38
Try and leave this world a little
better than you found it.
1:41
And I can totally get behind that idea,
and
1:45
in the spirit of making our shared
world here a little bit better.
1:47
I'd like to reframe this lesson
by not thinking about it
1:50
as the boy scout rule but
how about just the plain old scout rule?
1:53
I'm positive that the girl scouts
follow the same principle.
1:57
And by us talking on that boy part,
it doesn't do much for
2:00
our fellow girl coders, and definitely
doesn't handle the logic at all.
2:03
Women leave code better than
they found it all the time.
2:08
So let's make a conscious
decision to garbage collect
2:10
useless exclusionary words.
2:13
So ready scouts?
2:15
Let's go clean up this mess.
2:15
So let's go ahead and
let's switch back to master.
2:18
Let's checkout master and I'm gonna pull,
2:23
since we committed there we're
gonna update our project.
2:26
Cool, and then probably get rid of
our old branches that we deleted.
2:33
Cool, all right, so let's
2:37
go ahead and let's open up a,
2:42
getNextFlashcardBasedOnViews, and
2:47
we wanna open up the, here we go.
2:54
Open up the definition of that, just in.
3:00
There is a service, FlashCardServiceImpl.
3:06
Here we go, let's scroll down this page.
3:12
I'm gonna go ahead and get rid of
these repo things we have going on.
3:14
I wanna stop the debugger from running,
so we don't have that going on,
3:19
I'm gonna clean up all the space,
here we go.
3:24
So we want to get this what we
getNextFlashCardBasedOnViews.
3:27
Boy, I've already kind of forgotten
what it's doing in here have you?
3:35
Now part of the reason why that's hard to
grok what's happening is because there
3:37
are multiple things happening.
3:42
So I like how descriptive
this first call is.
3:44
It says getNextUnseenFlashCard.
3:46
We need something kind of similar for
this stuff below here.
3:49
So when you start feeling that one
thing that you should do is you can
3:53
highlight it and choose Refractor,
and we're going to Extract > Method.
3:58
And so I like that least viewed ID,
let's go ahead,
4:04
we can change this, we can make it public.
4:09
Let's make it public, and
4:13
how about getLeastViewedFlashCard.
4:17
So this looks better already.
4:26
We could probably flip this logic around
a little bit to make a single return.
4:28
It feels like we can make it just
4:33
return once, so let's say,
4:38
we do this if card = null.
4:43
The card is going to equal this method.
4:47
And finally, we just return card so
there's just one return.
4:51
Wow, look at that.
4:59
Look how much cleaner that reads.
5:00
Our scout leaders would be proud already.
5:02
It's super legible. So let's do something
about that randomness that they want.
5:04
Now I saw a pretty nice implementation
earlier I think about shuffle and yeah,
5:09
here we go.
5:13
So why don't we shuffle our entries.
5:15
We'll get the entries out and
we'll shuffle.
5:17
So let's refactor and extract our
entry set from this for loop here.
5:19
So let's pull these out, so
I'm gonna come out here and
5:25
we'll choose Refactor > Extract and
we'll extract that to a Variable and
5:29
entries is fine, that makes sense to me.
5:34
And I don't think that
you can shuffle that.
5:41
Let's try, letβs try
Collections.shuffle(entries); sorry,
5:46
it's Collections.shuffle yeah,
5:53
Collections.shuffle(entries).
5:57
Letβs see,
it says you can't do it to a set.
6:01
So why don't we just make a list,
6:04
then here we'll make a new ArrayList.
6:10
And we'll pass in this set
that we were using before.
6:17
So now, we have shuffled entries and
I'm going to comment this out here.
6:25
It can use, Cmd+Shift that, there we go.
6:30
So the algorithm here is really just about
finding the entry with the smallest count.
6:35
So if we took a look over again
at this getRandomFlashCards,
6:42
it's making use of these streams
which I think are super powerful.
6:46
They're introduced in Java 8 and
they really help you to do some
6:50
great functional programming,
which is kind of what we're at right now.
6:53
So I think that we should probably follow
the same style that the authors of this
6:57
originally were using.
7:01
We should try to dive into
what they were doing.
7:02
We want things to read similar for
people coming to our codebase,
7:05
especially in the same file.
7:09
These two are completely
different ways of doing things.
7:10
So let's do it, so one thing that
a stream can do is find the minimum
7:13
value in all the results and
that is exactly what we want to do so.
7:18
So our results are entries,
so let's go ahead.
7:23
We're gonna say return,
we're gonna do entries and
7:25
we're gonna open up the stream() on it.
7:28
Now, the method that finds
the minimum is called min, and
7:31
what the minimum takes is
it takes a comparator.
7:36
So we can use a higher
order function, which is
7:40
(Comparator.comparing) and
that will return what we want.
7:44
It will return a comparator, that will
compare two entries to each other.
7:49
And what we want to be compared
is the count side of things.
7:53
Remember, we're comparing the value.
7:57
So we can use a method reference,
because what's gonna come
8:02
through each one of these is, each entry
is going to be compared to the next one.
8:08
So we'll do, (Map.Entry::), and then we're
going to a method reference to getValue.
8:10
So minimum, you might think just
returns the thing, but it doesn't.
8:18
It returns an optional value,
8:22
because it assumes that what happens
if we don't have any values in there.
8:23
Streams are super cautious
about no pointer exceptions.
8:27
So one of the things that optionals have
is a really nice function that you can do
8:30
and it's called mapping.
8:34
So you can map what was passed in if
it was passed in, we're gonna map that.
8:35
So we have an entry,
that was key in the value and
8:41
we're just gonna do the same code
that was happening down here before.
8:43
So it was using this findOne,
so I'm gonna copy that,
8:47
And we're gonna do (entry.getKey).
8:53
Now it's possible, remember still
this optional might not be here.
9:00
So to properly handle
that let's go ahead and
9:06
we'll say orElseThrow, and
you really shouldn't be finding
9:09
the least viewed card if you
don't have anything in there.
9:14
You should be calling this method, so I'm
gonna say that it's an illegal argument
9:19
except that we could probably make
one of our own if we wanted to.
9:22
To make that a little bit more clear, but
9:25
what will happen here is
it will throw an exception.
9:27
The exception will be thrown, so
let's walk that one more time.
9:29
We're gonna shuffle everything
that we know about these counts.
9:34
And we're gonna find the minimum of those
values by comparing each of the entries
9:38
together.
9:42
Then we're gonna transform
that into an actual card and
9:43
if we can't find it we're gonna
throw an illegal argument exception.
9:47
Declarative program really
shines here I think,
9:51
the imperative version
of about 15 lines long.
9:54
But now we're looking at about three,
and I think it reads pretty well.
9:56
There's more in the teacher's notes.
10:01
Now I haven't heard back
from the client yet
10:03
about test, but this is so
screaming for a unit test.
10:07
So a nice trick is if you
wanna give your things a spin,
10:13
there's a nice little trick
that the debugger offers you.
10:16
And I wanna show it to you because this
is super handy when there aren't tests.
10:21
So here let's drop a break point
when that method is called.
10:25
So the first time they haven't seen one,
so we'll drop one right here,
10:31
we'll put a break point here.
10:35
Let's start the debugger up, run that,
I'm going to go over to up here,
10:37
I'm gonna clear our session,
and we will just loop.
10:44
Oops.
10:49
Illegal start of expression,
not a statement.
10:54
[LAUGH] this is the wrong side.
10:59
Sorry, there we go.
11:03
Let's restart the debugger again.
11:06
That's was pretty silly.
11:10
Sure you sit there screaming at me.
11:13
Fix that, you did it wrong!
11:16
So come over here, we got a new session
and we're gonna flip through and
11:18
it should only kick off when
it's in part where they're seen.
11:24
Cool, here we are.
11:27
So in this context we can click
this evaluate expression.
11:28
And so we can call,
where's the right place?
11:33
I think we have a trailing friend here.
11:38
Let's go ahead and we'll step into that.
11:43
Here we go.
11:48
So we'll continue on to our step here.
11:48
So we've got the LeastViewedFlashCard.
11:51
So we're about ready to call that.
11:55
So what you can do,
cuz you can evaluate expressions, and
11:56
I'm gona flip this into code
fragment mode so I get extra lines.
12:00
You can say getLeastViewedFlashCard and
you can pass in idToViewCounts,
12:04
and we'll find out it should be one,
should just be a random one.
12:09
So if we click Evaluate, we're gonna get
that card, and if we click Evaluate,
12:13
we'll get another one.
12:16
So we can keep on running this thing.
12:17
Now what's super cool about
this is we can make our own
12:18
map cuz we can create
different things here.
12:23
So all we need is we need a map Longs
to Longs and we can call it test,
12:27
we can call it whatever we want and
we can make a new hash map.
12:31
And here you can do test.put and
12:35
we can as long as they line up with cards,
we'll be okay.
12:38
So we can say, card1 and
12:43
we'll say that was viewed 15 times,
and we can copy these.
12:46
And card2, 3 was viewed 2 times and
12:52
this was viewed 7 times and
12:59
4 was viewed 2 times.
13:05
So it should find the minimum,
let's do one.
13:09
Let's do one first just to test it,
then I'm gonna pass in a test.
13:12
So now we can evaluate and
we're running that same thing.
13:18
So it's gonna find the smallest one is,
at the moment 4, cuz it's 15, 2, 1.
13:20
And we can put in 2 here, and
then we can click Evaluate.
13:26
And it should be finding
different random ones.
13:33
Is the shuffle not working?
13:38
There we go.
13:42
Awesome, so we can make sure that things
are behaving like we expect them to with
13:45
how a test framework there,
even though there should be one.
13:49
Let's go ahead and click Close, and
13:52
I am going to mute all these
breakpoints and continue.
13:54
Let's just take a look at it over here,
make sure things are still working.
13:58
Here two times, three times JRE,
YAGNI should be different order.
14:01
Perfect, it is.
14:07
Each time it's coming through
we're getting a different thing.
14:09
We did it.
14:11
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