Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
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