In this HTDF example problem, you're going to see a case where the problem statement isn't very specific about the function that wee need to design. That's going to happen more and more as we go foward in the course. Remember what I said in the first video. Design is the process of going from a poorly formed problem, to a well structured solution. So, making the problem more specific is part of the design process. In this video I'm also going to talk, about how many tests you need for a function. And we'll see another example of a case where you get part way through the recipe. And realize that you need to go back and refine some work that you did in an earlier step of the recipe. In this problem we're asked to design a function that consumes an image and determines whether the image is tall. So let's see, it seems clear that it consumes an image. [SOUND]. But what does it mean to determine whether the image is tall? Well, we're asking, is this image tall? So that's kind of a yes, no question. By convention, whenever we design a function that produces the answer to a yes, no or true, false question. We designed that function to produce a Boolean, so we'll say Boolean here, okay? And now what's the purpose going to be? The purpose is going to be something about, if the image is tall. And the key thing is so far, I've only said it produces a boolean, but I haven't said what true means. So you want to say in the purpose, produce true if the image is tall. You need to distinguish which does true mean. Does true mean that its tall or that its not tall? So whenever you got a function producing a, a boolean, your purpose has to be very clear about what true means, and by implication, what false means. So let's see, here's a stub. And this didn't tell us what name of a function to use. The problem statement didn't tell us what name to use. That's usually going to be the case. You're usually going to have to invent the name of a function when you design it. And it turns out that in the programming language we're using, there's a convention that functions that produce a boolean. Functions that produce an answer to a yes, no question or a true, false question, have a name that ends in question mark. So we're going to call this function tall question mark. It's going to consume image and a good dummy answer is false. So that would be the stub. And now we can write some tests. So let's see, check, expect, tall question mark, let's see I need an image, so let's take a rectangle. Oh, wait a minute, before I forget here, I'm using rectangle. So let me quickly go up top here and say require 2htdp/image. So I'm going to make a rectangle that let's say, is 2 wide and 3 high, and is red. The color doesn't really matter here but, rectangle needs the arguments. Let's see, it seems to me that rectangle that's 3 high and 2 wide is tall, so, we'll say true. Now, I want you to ask yourself right now. How many tests does this function need? The right number of tests for a function, is going to be an issue we talk about more, and more during the course. How many do you think this function needs? Write down your answer, or just remember it, and, we'll see where we end up. For now I'm just going to kind of, assume that it only needs this one test. That won't turn out to be right but we'll see what happens. Let me run the test and there's one test and it runs and fails. So it's well formed, so we can keep going. Let's see, this is the stub, we'll comment it out, all right, the template, the template is tall? img...img, we'll make a copy of that. And we'll comment out the original template, we'll label it as the template. And now let's see what does it mean the function let's see these functions have two cases right? Sometimes its tall and sometimes its not tall. So when you have two cases you can use an if because that be the case where it is tall and the case where it isn't. And what I like to do whenever I add an if to my template. Is I put in the f, and then I make myself three copies of the rest of the template. As a way of saying, okay, now I've got the if in there and I need to decide what happens here. Now let's see , tall involves comparing the width to the height, so let's see. If the image height of the image is greater than the image width of the image. Let's see, if that's true, then the image is tall, and so I should produce true, and otherwise, I should produce false. Well, let's try running that. Okay the test passed, the test passed, the test passed, but are we done? Have we really tested this function? Well one clue that we haven't Dr Racket is giving right here in the way it's colored this false. Depending on how you have your DrRacket configured, it might actually just highlight this false with black. But in both cases, what it's saying is it's saying, hey, this expression here was never evaluated. There's this concept called code coverage for a test, or test coverage, which says, given all my tests, how much of the code is actually being evaluated? And if the answer is not all of the code, then you don't have enough tests, because what if the piece of code that isn't evaluated is wrong? You haven't tested that piece of code. So whenever you run your tests, if you see code that's highlighted that says that it didn't get evaluated, then you know for sure you need more tests. And what's happening, of course, in this case is we tested the case where it is tall But we didn't test the case where it isn't tall. In this case we do that fairly straightforwardly by copying the first test, and just swapping these two around. And saying, well in that case, it's false. Now let's run it, both tests pass. But are we really done? Let me make this a little bit, give us a bit more room here. Are we really done? At this point, what you might think of is, hey, wait a minute. There's one more case. What if,it's the image width and the height are the same? What should happen then? And this is a thing that happens in function and program design all the time. You realize partway through the design process that there's a boundary condition, or sometimes we call it a corner case, that you hadn't quite thought of. It's perfectly fine for that to happen, but when it happens, when you say to yourself, wait a minute, what if the width and height are the same? You need to immediately do a couple of things. First, write an example for. Then decide what the behavior is. And I'm going to decide in this case that if your width and height are the same, you're not tall. So write the example, write the expected result, fix the purpose, height is greater than width. So that's unambiguous in the purpose, and if what you decided required you to change the function, change the function. In this case it didn't. But if I had decided this the other way, I would have to change that to a greater than or equal. And now, run the tests again. Now all three tests are passing. So that's the design effect function, that works. When I run it and the tests pass, all my code is evaluated, so I've got good test coverage. So, I'm pretty good here. At this point, I just want to make one minor detail point, which is whenever you have an expression of the form, if something, true, false. You can also replace that by just this simpler thing. Let me comment this one out, Racket > Comment Out with Semicolons. Why are these two the same? Well, look this one says if this expression evaluates to true, then produce true. Otherwise, if this expression evaluates to false, then produce false. So that's really just the same as the expression itself. Either this expression evaluates to true or it evaluates to false. So whenever you have, if something true, false, you can just replace it with the question itself. And in a normal program, once you've done something like that, you would clean this up, you'd Delete that out from there. And in a couple weeks, you also won't leave the stub and template behind. So now you've seen the How To Design Functions recipe. And you've seen me work through four examples of it, where each example showed some more wrinkles to the process. What you should do now is go work through all the practice problems for this week and then do the homework problems and the quiz. Let me stress sometrhing about this material. I ja, I just can't make this point strongly enough. This is the kind of material that you learn by doing. I really want to encourage you, don't look at the problem and then look at the solution. If you do that, you're going to say to yourself, oh I know how to do this. You need to actually take the blank starter file and work through the problem yourself from beginning to end. That's the only way to learn this kind of material. At any rate, have fun with the practice problems and the homework and I'll see you next week.