Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranî)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
So as our game stands now, the same thing happens for every player.
One blam, two woots.
In other words, there's only one path through the game.
But we know from real life that things happen based on different circumstances.
If this is true, then we do this, and if this is true or false, then we do another thing.
Yeah, and in programs, the way we do that is we use conditionals to control the flow
of the program, which is sometimes why we call it branching.
We go down one branch of the code or a different branch of the code, depending on some condition.
So to look at that, let's just start with a simple example.
Let's say we want to determine if our movie is a hit or a flop, and then do something
based on that.
So I just created a new file here called Conditional, so we can play around with conditionals.
And we're going to use our movie class to do that, so I'll just go ahead and require
that in.
We'll have a movie variable.
We've seen this a number of times now.
Actually, I'm going to change this movie name to Godfather, and it has initial rank of 10.
So conditionals are pretty straightforward.
Let's just play around with a couple of them here.
Let's print out if we have a movie whose rank is equal to 10, what does Ruby print out here?
Well, Godfather, its rank is equal to 10, so if we print that, we just get true.
What if we try something like movie.rank is greater than or equal to 10?
Well, that's true as well, because it's equal to 10.
What if we test that the movie's rank is less than 10?
Well, you probably guessed that we would get something like false.
So these true and false are used to control the flow of our code.
We can use these to do comparisons and then make decisions in our program as to which
parts of the code we want to run.
So let's do that.
I'll just remove these, and we're going to start an if statement here.
We're going to say if the movie.rank is greater than or equal to 10, then inside of that,
I'm going to print out.
It's a hit.
It's a hit.
All right.
And if we run that code, it prints hit, because what happened was it evaluated this expression,
and the movie's rank is greater than or equal to 10, it returned true.
So the if statement runs, and that part of the code that's inside of that if block actually
executes.
Now, there's another way to do this if you have a single line if block like this.
We can just put the put as on the front.
We say put as hit, and then put this statement at the end.
We call this a statement modifier, because this is going to modify whether this statement
runs or not.
So if the movie's rank is greater than or equal to 10, then go ahead and print out hit,
which is what we get.
So what if the movie's rank is less than 10?
Well, movie.rank less than 10.
Oh, then it's just a flop.
Okay.
Give it a flop like that.
Now if we run it, we see that hit is still printed, because the movie's rank isn't less
than 10.
This returns false.
So this code won't run, because the if statement evaluated to false.
So if we switch this around a little bit, we'll change Godfather to a nine now.
Now when we run it, we get flop instead of hit.
So you notice that this did not run, because that if condition wasn't satisfied.
Now we often want to do one thing if the expression is true, and another thing if the expression
is false.
Yeah, let's just combine this all together.
So we can say if movie.rank is greater than or equal to 10, then we're going to print
a hit.
Otherwise, or else, we're going to print flop, just like that.
Now we've got Godfather set to a nine, so if I run that, we get a flop.
If I set it back to a 10, no surprise here, it prints hit.
So it's easy to see how we would use conditionals to control the flow of a game.
It's a fairly straightforward concept.
And since there isn't a lot to conditionals, we thought we would take this as an opportunity
to show you another programming style, test-driven development.
So how is this different than the way we've been doing programming so far?
Well, in the last section, we learned how to write unit tests.
And we wrote our code, and then we wrote our unit test afterwards.
Now we want to turn things around.
We're going to start by writing the test that expresses the code that we want.
So we're going to write our expectations about the code first.
Then we're going to run the test, and it's going to fail because, well, we don't have
that code.
Then we'll go back in and write just enough code to get the test to pass.
And then once we have a passing test, we can safely refactor, knowing that we haven't broken
anything.
And we'll just do that.
We'll rinse and repeat, do that in really small increments until we have the features
we want.
So coming back to this code that we just wrote, we noticed that we're getting the rank from
a movie and then determining whether it's a hit or a flop.
So a question here is, where should this code live?
Because right now, it's violating the tell-don't-ask principle.
We're asking a movie for some attributes, and then we're making a decision based on
its behalf, and then we do something with that.
Instead, we would rather just tell the movie to do that.
So this code really belongs inside of the movie class.
But since we're going to do this test first, we need to write the test first.
So let's just go over to our movie spec file where we've been writing some specs.
I'm just going to create a bunch of space down here.
And we're going to set up a new context here.
And the context is going to be a movie with a rank of at least 10.
And then we're going to have a before block in here.
And we're going to have a movie.
And the movie is going to be Goonies with a rank of 10.
That's fine, because that's a rank of at least 10.
And then we want a code example.
So it's going to be ItIsAHit.
So how are we going to express that a movie is a hit?
Well, we're going to take our movie object, and we want to call some method to determine
whether it's a hit or not.
So we can just think about the name right here, because we don't have this code yet.
I'm just going to call the method Hit?
Because we know that question mark methods return a true or a false.
So then we can tack on Should, and it should be true, just like that.
So if we run this back now, of course it fails, because we haven't defined the hit method
yet.
That's OK.
We'll go over to our movie class.
And just right up in here, I'm going to define the method Hit.
And just to get the test to pass, I'll just have it return true, just like that.
We'll go back to the test.
We'll run it.
And now we've got green.
So we went through the cycle.
We wrote the test first, then we went and wrote the code that makes it pass.
Well, clearly that's not going to stand up for very long.
So let's write another test to drive out more functionality.
We want a context where the movie has a rank of less than 10.
Inside of that, we'll create a before block.
And inside of this before block, we'll have a movie.
It's going to be movie, Goonies, and we'll just say it's 9 in this case.
All right.
Write our it structure.
It is not a hit.
So then, oops.
So then down in here, we can just say movie.callingTheHit method should equal false.
Let me just clean this up a little bit.
There we go.
So there's our two contexts.
One that's a hit and one that is not a hit.
If we run this now, well, now it fails again because we're always returning true in this
method.
So let's go back to our movie.
Now we have to make a real decision here.
So how are we going to know if a movie is a hit or not?
Well, we're just going to look at the rank.
And if it's greater than or equal to 10, it's going to return true.
Otherwise, it's going to return false.
So go back to the spec file here, run it, and we've got green across the board.
So I want to show you a couple shortcuts that RSpec has for testing expectations that are
true or false.
We see this should equal equal true.
Another way to do this is just to use should be underscore true.
That's called a matcher in RSpec.
And in the same way, down here, we could say should be false.
And those still pass.
But there's another way we can do this as well.
We can just say movie.should, and then we can say be a hit.
And what RSpec does there is it drops the be part of it.
It takes the hit.
It automatically appends a question mark.
So it expects to call a method called hit question mark.
In the same way, down here, we can drop hit from here.
We can say movie should not be underscore hit.
It's going to call the same hit method, but now it's going to expect it to return false.
If we run that, our tests are still green.
So that's a glimpse at test-first programming.
We wrote the test first, and they failed.
Then we went back in and we wrote the code to make the test pass.
And then once everything was green, we went back through.
We refactored stuff.
And then we got back to a safe spot with green again.
So let's go through that cycle again.
But this time, we want to get the status of a movie and return the string hit or flop.
So we need some more code examples for that.
So if we go back in, let's see.
We've got this context with a rank of at least 10.
Well, in that case, our code example is going to be that it has a hit status.
So the expectation is when we call movie status method, we'll just make up that name now.
We'll have to implement the method later, but sounds like a good enough name at this
point.
It should return a string equal to hit.
We run that.
The tests fail.
We don't have a method called status.
Back over to our movie class, we'll add one in.
Status and we'll just return the string hit just to get it to pass.
Back over to the test again.
Sure enough, that works.
But we just faked the test to get it to pass.
So let's add another code example to really drive out the functionality here.
When our context is a movie with a rank of less than 10, then it has a flop status.
So our expectation is when we call movie.status, it should equal the string flop.
Run that.
Of course, it fails because we're always returning the string hit.
So back over to our movie.
Now we've got to add a conditional here.
We want to return hit.
If it's a hit, we want to return flop if it's a flop.
So let's use a conditional.
We can say if we already have this method called hit question mark that returns true
or false, so we can just piggyback on that right here.
String hit, else the string flop.
And remember with a conditional, if this fires, if it's true, then it's going to return this
string.
It's the last expression that's evaluated in this method, so it's going to be automatically
returned.
Otherwise, this path in the code is going to be run and that's the last expression that's
returned.
So let's see if that worked.
Let's back over to our specs, run them, and we've got everything green.
The last step of TDD is that we can refactor because we know that everything works.
We can clean up our code just a little bit.
So back in our movie class, instead of using the FL structure like this, if you've got
a really simple branch, something like this, you can use the ternary operator in Ruby.
And the way you do that is you call a method that returns true or false or you evaluate
some expression that's true or false.
If it's true, then we're going to return hit.
If it's false, we're going to return flop.
And this does exactly the same thing as this construct.
It looks a little odd because we have two question marks, but that question mark is
part of the method name.
This question mark denotes that the thing that follows is what happens if the thing
on the left-hand side is true.
This is kind of like the else statement.
This is what is going to be returned if hit question mark returns false.
Next step, we go back over to our movie spec.
And thankfully, after doing that refactoring, our tests still pass.
You know, it would be kind of nice if the status was included in the movie listing.
Oh, so the word hit or flop in the actual movie listing.
Right, right.
OK, well, let's change our spec for that.
OK.
So our spec for that is up here.
It has a string representation.
And so we're expecting the status not to be in here.
So let's say, well, this one has a rank of 10, so it's going to be a hit.
And we want the status or the printout to look like that.
So we run that.
Sure enough, it fails because it doesn't include that word.
So we can come back over to our movie.
And now in our 2S method, which is right here, we can just include in parentheses.
We've got this status method at the top.
So we'll just call it right here.
It's going to return a string for us back over to the spec.
And sure enough, we've got that.
It's all neatly nested.
We've got our conditions for with a rank of less than 10, it's a hit, and it has a hit
status.
With a rank of, or actually with a rank of at least 10, it's a hit and a hit status.
With a rank of less than 10, it's not a hit, and it has a flop status.
So you can almost see how this is generating a little bit of documentation about what this
object should do.
And it'sSound GoodnessTutorial.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.