[ Silence ] All right welcome to section. This is July 2nd, we will not have section on Wednesday because it's the 4th of July. So the next section will be one week from today. We're going to talk about Model View Controller today, but first I want to tell you guys how to get a hold of the code that we discuss here. If you go to github.com/ codekiln/S75-Sections, up here you can see it. You'll see the code that is for all of my sections and the code that we're doing today is right here, 7-02 MVC. So I'm assuming that you're using the CS50 appliance that we're using in this class. The CS50 appliance can be found just by doing CS50 appliance and Google, and we're going to be releasing a new version of the appliance later this week. If you want to play around with previous versions of the appliance you can download them here. The instructions that are at this page assume that you're working in the latest version of the appliance. So first of all I'm just going to demonstrate how to download this code and get started with playing with it inside of the appliance. You would go to github.com /codekiln /S75-Sections and then copy this git address right here, and then you would go into the appliance and open up a terminal if you haven't already. I'll close this so you can see what that process is like. It will open up a terminal by clicking on this button down here. The very first time you install the terminal, there is no public HTML directory so you will have to create one and change the permissions on it to 755. If I list -- the files in my home directory which is the tiller directory. You can see here I already have a public underscore html directory that has world executable permissions which is what I need. This rwx, rx, rx it's readable and executable by everyone. Executable meaning that you can go inside of the public underscore html directory. So I'm going to go inside the public underscore html directory and you can see that I already have a few folders. I'm actually going to make a directory called temp and if I look at it I can see that temp if I look at it with ls-l that gives me the long listing of all the files and directories in the directory. You can see that the temp directory I just created only has rwx permissions and I need everyone to have reign execute permissions. So I'm going to chmod that 755 like I discussed last week. You can remember the permissions -- 4 is read, 2 is write and 1 is execute, so whatever permissions you need you add up the various elements. So for the second and third bit which is write for that the middle part is the second bit and that last part is the third bit. You want 5 and 5 for those second bits so that you get 4 plus 1 you get read plus execute. This is write. Now these are permissions that you want for dealing with the appliance. These are not production permission levels, in production permission levels you wouldn't want to grind everyone access to be able to read and write all the directories but in this case it's really helpful. So I'm going to chmod 755 to temp directory and then go inside of it with the CD or Change Directory command and now I'm going to git clone and I copied this right here, copy and in here you can press control shift v or go to edit and paste in order to paste it in. So when I do git clone, it will clone into the section code and download it from the net. Doesn't take too long if you're on the Harvard network. If I do ls-l now you can see that S75-Sections code. I'll also need to chmod 755 S75-Sections code. Now I'm going to change directory inside of it. In here, you can see that the permissions are all wrong and so I've created this little script permissions.php that will recurs into the subdirectories and set all the permissions for you because git doesn't remember all of the necessary permissions for you to be able to use it on a server. So in order to run that permissions.php file you do php-f for file and then enter permissions.php as a -- as an argument and now if we do ls-l all of the directories should be the right permissions and then all of the images and CSS files and other world readable files should also be assigned 644 permissions as well. So you probably don't want to run this permissions.php file if you're not running inside the appliance because the appliance is running with suphp. Which assumes that a Apache is running as you and so, the permissions are slightly different that if you were using for example xm where the server runs as a different user and needs different -- a different permission structure. So now that we have downloaded this folder, you can open up a browser and go to HTTP colon local -- colon 192.168.119.128 you can see the number at the bottom right portion of the appliance and we want to go inside the jharvard directory, and inside the temp directory and because I have assigned 755 permissions, it gives me a nice listing of all of the contents of that directory. If I had chosen 711 permissions, it would have worked but it wouldn't have given me this nice listing. So the code for tonight is here in 7-02 MVC okay. So first of all in Model View Controller, I've written here on the left hand side a little marker blog. This blog is called MVC blog and it says exploring MVC since 2002. Yeah? [ Inaudible Speaker ] GI -- the question is what is GID? Where do you see GID? >>. GID on the top. You know, [inaudible] download it into a [inaudible]. [ Inaudible Speaker ] Yeah, GID [inaudible]. Oh, where it says git clone git@github.com:codekiln what is that about? Git is a source code management program and github is a website that hosts code that is stored using the source code management program and git helps you store different versions of your same code in a really compressed format. So that for instance you could have three or four different versions of the HTML file and you could switch between them in a moment's notice and develop on all of them at the same time. It's really helpful when you are maybe with the resection on git later on this semester once people have gotten more used to development. The thing that is primarily helpful for is being able to work on a separate feature and having it isolated from -- maybe you can work on three separate features and have them all isolated from each other. And then at the end being able to merge that code together after the features are completed. So it helps you kind of isolate where you're working on to the features. So when I did git, that's invoking the source code management program and then clone is the git command to clone repository, which is a collection of source code. So I stored my source code here on github and if you enter the git command clone and then put in the address of that source code, then it will clone that entire repository and make it available locally. And the reason why I'm using git here for source codes, is that I can update them and you can pull the freshest version. Like if I -- after tonight's section I make a few additions to the code from tonight. I can update it and if you pull it tomorrow it'll be fresh and updated on your own machine. Good question. So going back to Model View Controller we're here inside 07-02 and the very first one Model View Controller intro. So I'm just going to read from a little bit of this. Web developers call dynamic websites web applications because from the coder's perspective dynamic websites are applications that run on the web server. Modern applications follow design patterns. One very common design pattern that David just showed us is Model, View, Controller or MVC. To follow MVC when writing an application, you separate your code according to the function of the code. Model code stores the application data and models your application's problem domain. The problem you're trying to solve. For example, if you were writing a blogging application, the Model code would determine what data needs to be stored about a Blog Post, and take responsibility for the storage and the retrieval of each Blog Post and all that data. The View code produces anything that is viewable by the site visitor. For example, in a blogging application, the View code would turn a Blog Post's data like the title and the actual content and the date that it was posted and the person that it was posted by. There's the posted by -- you know these are all accessory pieces of data for the blog post. View code would turn the Blog Post data into HTML and CSS, which would then be rendered in site viewer's web browser which would determine how the site would appear to the visitor. The Controller code receives all of the sites, clicks and other input, and uses them to help your user control the application. For example, on a blogging site, if a user clicks on 'next post', the controller will receive that click, fetch the appropriate Model of the Blog Post from the model code and then send it to the View to turn it into the HTML that the site viewer's browser will render for the site viewer's viewing pleasure. So it's basically just a way to separate your code in order to reduce the amount of code duplication and in order to ensure that your code falls into these categories that are easily recognizable by other programmers and by yourself when you come back to your code many years later. So I'm going to go into MVC folder here and let me just -- I'm actually going to change directory into the actual folder rather than the temp folder that I used to demonstrate it. You might have noticed something there, if you're not familiar with the command line on when you press -- when you enter a code into bash like change directory and then you press tab, you get all these nice suggestions and then if you start typing and hit tab it will complier for you. This can really speed up you're experience with the command line. So the -- the code that we were just viewing is 01 underscore MVC underscore intro and I'm -- this isn't really an example of model view controller but it's maybe like a first example of how to think about model view controller. Here I edit all of the - I enter all of the content into an array and up here I define the array and then what this syntax of an array does, is it that it appends this string onto the end of the array, so each of these paragraphs is appended to the end of the array and then down here I echo the DOC TYPE, and the head, and the body and then when it comes time to actually fill up the well, they are - when it comes times to actually fill up the blog post area. Then for each paragraph, in the paragraphs array it puts p tags around that and echoes it out. And you'll see over here that we actually have 3 different blog posts and I did this just to make it look like they were lots, lots of blog posts in this blog. So today we're going to discuss maybe how to think about making a blogging application in a model view controller sort of way and this is a first attempt of how to do that. This is by no means model view controller but it's like kind of the pre version, so now I'm going to back out and go into the unfinished model view controller example. You can see that, I don't know if you can pick that up on video tape but there's one, two, three different wells where blog post material will appear but it's unfinished and the reason why is that it would give away all the secrets if we did that. If we go to the number two example, you'll see this example only has a very small amount of code, the first thing I do is define the folder where the application, the web application is actually stored. So here the web application is stored in app02 because the prefix of this file is 02, and all of the subsequent versions will have app 03, app 04 matching the version that we are looking at. The second thing I do is define where the model view controller folders are relative to the app folder, that way with - by just changing one line of code, I can change the entire directory structure and update it really easily and then finally I start the controller because as the name suggests, the controller is -- the controller of the application it's the point of entry into the application. So I'm going to open the controller which is up top, we can close this bottom one now and the -- right now the site doesn't feature an interaction, so this is going to be a really boring controller page because right now there -- you know there is nothing clickable on this page really, there's no user input that the controller is handling which is where the controller gets really interesting and I know the controller will get significantly more complex the more user interaction you decide to support. And so the very first thing I do is create a variable that's going to be passed around from the controller to the model and then from the controller to the view and as it's passed around it will be filled with data and change by each file that's included. So the only piece of data that I put in was a query, this is an associate of array, just like how David showed it, where the key query goes to this query and this is an XPath query. Has David talked it all about XPath yet and XML? In coming weeks he will - he will talk about XML and XPath. XPath is a way of navigating an XML document and an XML document consist of and then more of the same, more s. The only rule is that it has to close like this so that for every one of these there's one of these that closes it. And there are rules to XML as well like if you have you have to close before you close the parent tag. XPath is a language that's used to navigate an XML document, XML documents are used to store data and they were used especially at the end of the 90s'. So if I had on a word that I wanted to get at, that is inside of the here which is inside of the , I would refer to that an XPath like /tag/a/ and then you would -- I mean in XPath you would refer to the text in order to get the actual text of content but the basic just of XPath -- and David will explain this more in lecture is that as you descend into the XPath query, you descend into the tree of nested tags just like HTML. So for instance if you wanted to get at the title of an HTML document using XPath, you could do /html/head/title and then do the text function or you can access an attribute and the other silent feature about XPath is that if there's not just one in this case, most HTML documents only have one title but if there are multiple matches for that combination of parent-child-child, like let's say html/body/a or maybe /body anything a. This would match all anchors that are children of something that are children of the body document that are body element that are children of the HTML document. So this would return a whole array of anchor title links, you might be able to extract you know a 100 links from a document with this XPath query. The Xpath is very useful for doing what's called web scraping, where you try to scrape large amounts of data from a web page where it's encoded in HTML. So I - if you Google Xpath you can get to an XPath tutorial that'll teach you the very basics. I think that we know enough to go on with this example, with this simple example I decided to make the model store the blog data in XML since HTML is commonly written like XML. In many forms of HTML are XML, so if we open up the model which is the next thing that is included, so from here we jump up to this document. In PHP we have a built in object that lets us query XML files - before we get into that, let's just take a look at this data.xml file. The XML file is written in a format called RSS, though RSS specification actually exists here at Harvard, the Berkman Center for I think its Internet and Society, they are the ones that hosted. Basically RSS is a way of encoding blog posts, so it's a natural data storage format for a blog, if you don't need a lot of extra bells and whistles. So the specification -- let's see if they have an example, yeah -- -- well this is a -- I mean this is an example right here. The parent tag is RSS and inside RSS is channel and you can think of channel as like a blog site and then the channel, the blog site will have a blog title and a description which are - if we go back here, this MVC, that's the blog title and then this is the description. And then within that there are blog posts which in RSS are items and each item has title, author, pub date, and description. And in XML as in HTML you need to escape special characters and one of the most important characters in XML is the less than symbol and so in XML you would either need to encode this as ampersand lt; or you would need to make one of these character data section which you can see the syntax highlights in vim very nicely. If we -- if we open a character data section with that syntax it means that whatever program is processing the XML it is to ignore any special XML characters and just treat it as raw characters. So for instance this character the

I would normally have to write the open bracket like this but because I put it inside a character data section, I actually don't have to go that far, I can just interpret it that way. So here you can see intro to MVC in an and web developers call dynamic websites web applications, this is the same content as before, it's literally the same HTML as before. But it's just put inside of this data storage format that also annotates a title, an author, and a pub date to the description and those are all of the elements in an item and I put three different items in just like before, I give them three different dates in case we wanted to try to separate them out from each other later. So this function, simple XML load file it actually reads through the XML file and loads the XML as an object in PHP, so for instance if I have a variable $var equals simplexml underscore load underscore file data.xml then now I can access -- assuming that data.xml is the same as it is up there. I can go $var and then use the special hyphen greater than you know arrow descending into a sign that you use with objects in order to actually access the channel and then the -- I can then access the, you know, the title and the item, so it provides access to the data inside in a PHP variable. So, now inside of this XML variable, is all of the data that was in the XML file, but loaded into a PHP variable. So, because we're in the model, I'm going to store the "AT", of -- up here at the top of the controller, we put a query into the data variable and then here in the model, we're going to replace that query with the action of running the X path method with that query on the data. And this X path method, if you -- you'll become very familiar with it later this term because we'll be using XML in one of our assignments. It -- these methods that the simple XML element exposes are all available right here in the public documentation of the simple XML element class. So, you can see that there's a "Count" method, and there's an "X Path" method, and there's an "Add Child" method, if you wanted to add a child element of any one of those elements, you could. So, in the model, this executes a query on the data and then stores it back in the data variable and then returns to the controller, the control, and if I just comment this out now, I'm echoing out a preformatted section and recursively printing out what's inside "Data", I just save this and then go to S75 sections. Now, you can see that what's inside that data variable. You have the query key that points to an array of simple XML element objects and each one of them has title, author, pub date, and description. There's nothing inside of here apparently, but actually, the whole body of the blog post is inside that simple XML object. So, the MVC part of this is that I've separated out the model and I've modeled it using a storage format that's designed for my domain, in this case, "Blogs" and the part where I'm accessing and retrieving data, that's done by the model. And then I pass the data off to the "View". I'm going to close the model now and open the view and like David's first examples, I have the doc type and then I include a header and then I close the head and open the body and then I include some top bar and some content files. Maybe if I open up the content file, you can see that I have "for each loop", that "for each" data query as post. Then what this does is it will -- if I had more than one -- over here, I have zero, one, two different objects that are inside of the query array. So, as I loop through them with the "for each" loop, it assigns the post variable to the very first one and that includes "post.PHP" and this first simple XML object is available inside the post variable when you include it the first time. Then it loops again with the second one and assigns the post variable accordingly. So, inside "post.PHP" I can access the post just with the post variable much like David was doing with the title. I'm passing in the title. So, let me close the data and I'll open up "App02/view/post" so that you can see that the data is available here in the post variable. So, let me go down to the controller -- yeah, I already commented out that echoing of the data variable. So, we have these three wells here. What could we change inside this file in order to make just the actual description pop out or maybe even just the title? Assuming that the simple XML object is stored in the post variable which is now available right here inside post.PHP, what could we echo out? Well, the -- the answer is that we have to keep in our minds -- let's see if it's available, no that's not -- you have to keep in your minds the structure of what's inside - -- the variable. So, inside each of these variables, there's a title element available right there. So, if I do "echo post title" -- Now, I see the first post title, and the second post title, and the third post title. And the other data pieces, we could put together a little template for post right here in post.PHP using the post variable and it changes it for each post. So, let's skip ahead to the MVC with no link functionality. So, now I've gone in and made it so that only one post appears on the front page, but it's clear that the post.PHP that we were just looking at has been flushed out so that I have the post title hyperlinked nicely and the posted by and the date and the other meta data included in the post. And we'll just take a look at that, so you can see that in 03, nothing has changed except for this digit. Now, its 03 and we'll look at "post". So, we have an H2 tag with a post going to the link, and a post going to the title, and a post going to the description, and a post going to the author, and a post going to the pub date. So, that's basically all it took to create that basic functionality. If we go to the controller, you can see at the top here, we have this navigation and right now, it's broken. It doesn't do anything but you can see that's common paradigm for blog. This is where the controller will come it. It's the controller that will accept my key presses here and turn them into the desired view that the user wants to see and it's the controller that's responsible for querying the data and setting up the data and then returning it to the view to be rendered correctly. So, let's look at the controller. So, new in app03, I created a variable called "the post number to display" and this is just the number of the post in the data.XML file. So, the very first item would be the number one, the very second item would be number two, the third item would be number three and so forth. Also new in app03, inside the data variable, I've included not just one query but two queries. So, I've included the -- the very first one is the -- this is querying the item elements that are children of channel elements that are children of RSS elements and then in X path, you are able to apply what's called a "predicate" in Computer Science. A predicate is a set of true-false conditions in order to lower down the number of results that you get from a search. So, in this case, we take the array of items and we return only the ones whose position X path method equals the post number to display. So, in this case, the very default is to put the post number to display as one and if I were to change that to two and refresh this, then now, I get the second post. So, we're just kind of building the skeleton for more dynamic functionality but it's not very -- it's just displaying the newest post which is a fine default behavior. Also, there's an X path method "Count" which counts the number of elements returned by this X path query and these are things that you will have an opportunity to explore during the XML assignment, when you'll get to know X path pretty well. So, I include "model.PHP", let's see how that's changed, app03 model. So, we're still loading the file but what's new is that for every single thing in the data variable as variable name goes to X path, this is -- this might be a new construct. Has David showed this type before, each loop before with PHP? I think this might be actually new for this class. Associative arrays are arrays where one text key leads to another value and when you are looping through associative arrays, you can get access to both the key and the variable in "named variables" inside "for each loops." So, for -- what happens in this for each loop is that we have this key going to this value and this key going to this value. So, the very first time it puts the posts to display key in data equal to the result of executing this query on the XML data source and then it does the same thing with the next query. So, basically this construct, the very first part is the variable we want to store the result of the query in and the second part is "what is the X path query that we want to execute?" And after it passes through the model, then we can assume that if the RSS -- if the X path query didn't fail, that the data is stored in the appropriate keys inside the data array. So, now we just pass it on to the view. In this case, this control -- these controls up here are not linked in yet to the IDs but you can already predict how -- if this is the number one and this is post ID one, and this is number two and the next post is post ID two, you can already predict how using a "GET" parameter, you could pass things in, that the controller would be able to interpret as an action to draw different information from the database or in this case from the model. So, let's back out and go to the actual example. So, now we have a model view controller with links, you can see it shows one per page and there's a previous and next button. If you click "next", it lets you go to the next one until we get to the third one and it's greyed out and I can't click anything there. And if I go to the previous one, it gets greyed out when I get to the first one. So, this functionality is provided by the controller. This is where the user interaction design actually starts to get more rich. So, if you go into -- first of all, let's look at the controller, we'll look at app04/controller/controller. So, new in app04 is that we're taking the post number to display from a "GET" variable so you can see that if I click "next" here and then scroll way to the end, post -- I have post underscore number equals two. So, right here it's checking to see if post underscore number is set and if it is, then it sets the post number to display equal to that post number. So, I should be able to change it just by doing that and this is the third post. Finally, and this is where the controller really does some controlling. If the post number to display is less than one, it sets it to one. So, the controller's responsible for setting boundaries on things and making sure that things don't behave outside of the normal parameters that they're supposed to. And this part executes the same as in the previous example, it goes through the model. The post number to display is just controlled by the "GET" parameter. The -- in this example, I've actually included the post number to display as part of the data variable to pass to the view because these previous "next" buttons, they need to know what the current ID number is in order to know what's previous and what's next. So, if I click here, you can see that this knows that the previous link is -- has post underscore number equals two at the very end and that's because I included that information before I requested the view. So, in here, I made the -- a variable called "number of posts" that's equal to the count, which is a PHP function that counts the number of elements in an array data. The number of posts query that we issued to the model returned an array of things, an array of simple XML element objects and the count function here counts the number of elements that are in that array and assigns it to the number of posts variable in data. So, let's take a look at what this looks like in the data variable. You can see we have the posts to display query filled in with the results from the query that the model did for the controller. And then down here we have the number of posts which was assigned right here and we have the post number to display and the next post URL which is nothing in this case because the number of posts equals the post number to display. And you wouldn't want to display the next post URL because it would -- if your user clicked on it, they might get some unexpected functionality like them being able to see -- try to query a post that didn't actually exist. So, if I click "previous", you can see how this changes. Now, the post number display is two and I have both the next post URL and the previous post URL and the view is kind of dumb. All it does is take the variables from the controller because the controller is controlling the behavior. And then if I open up the "view" everything happens inside of "content". So, this goes through the -- this is the same as before -- this is not actually new. If we go inside "post", we already pretty much looked at this. The only differing content is the navigation, this stuff right here which if we actually look at the -- if we look at the content, I'll say "new in app04", now we have -- actually, I think it was app03. Now, we have a pagination of PHP and here is the logic that -- it's not even really logic. It's almost like declarative but basically, I create this phrase, "class equals disabled" and if it's -- if an element has "class equals disabled" on it, then it turns grey and becomes inaccessible. And so, I check to see if the previous post URL is -- has a string length that's less than one which basically means I checked to see if it's empty. And if it is, this is using the "Tannery" structure syntax in PHP, this right here is a -- because it has parenthesis around it, it evaluations to a Boolean true or false, and then the Tannery structure says that after the question mark, you -- if it's true, then you return what's here and if it's false, then you return what's here. So, if it's true that the string length of the previous post URL is less than one or basically if it's true that there's no previous post, then the disabled previous variable will contain this "class equals disabled." And farther down, here's a list element that provides a space for disabled previous variable to echo out this class equals disabled if it's appropriate, only if the URL is not present. And here, I'm taking the link directly from the variable that was stored in data by the controller. So, this controller has really simple functionality. It doesn't really do all that much. An example of a more expanded controller would be being able to click on a link and have it actually enter somewhere in the URL, the actual title, "Hipster Ipsum," and being able to query it from the database by title. A lot of blogs have that ability, in fact, it's called -- it's usually called the "slug" where there's a portion of the URL that refers to the actual content that's referred -- or that's queried from the database. That would be some more advanced controller functionality that you can include. In order to think about that, you would need to think about how to generate links in PHP from the database and how to echo them out. This is something David's spent a significant amount of time on but it's something for you to spend a lot of time on as you're preparing the very first assignment. Because you'll be drawing items from a database and it'll be important for those links that are generated dynamically to not pose a security threat to the user. So, let me close out of some of these and refer to -- I think its 05, yeah -- -- so, what if I wanted to make a page title called, "Correct Usage of the Pre-Element," and I wanted to have it actually appear in a link and also have it appear in a URL so that you could refer to it like this, "page title equals Correct Usage of Pre." As you can see, that looks kind of funny on its own. URLs can't have spaces. It's not enough for you to just put the title in there, so there are several different functions that you have to know about, and the way to think about it is that the dynamically created path I've stored here in this variable path and then the page title I've stored in this variable "page title" and then the page title link text. In this case, I want this link right here to actually have inside the A tag, the very same value that I'm transmitting inside the URL as the title and of course, this less than sign pre-greater than sign, that's a special HTML token. So, if you were to just write that in the page, the HTML page would interpret that as a literal "pre" which means to -- everything is preformatted after that. And so, it would mess up the encoding -- or not the encoding -- but the -- it would mess up the display of your entire page. So, the way to think about this is that the portion of your URL that is before the question mark, that is dynamically generated by PHP, that part you want to use while URL encode, which transforms all of the characters that are illegal into these hexadecimal codes and then for the portion after the question mark, for the actual parameters like page title, you want to use URL encode which does a similar thing. And here, you can see that URL encode put the plus sign inside -- instead of a space, in between the different tokens in the title and that looks more friendly on the -- as a parameter than a percent 20 or percent 32 or whatever that ask key code is. And then finally, when you link -- when you actually make the code that's going to link out to the page, you want to echo the HTML special chars of the URL and of the link text. Because the assumption here is that the next X version of the model view controller application is going to support these page titles. So, someone could enter in a title here that would then be echoed out to the screen in a link, and you want to make sure that somebody doesn't take advantage of that functionality to dynamically insert a link into your page that includes a script tag that could house some JAVA script that could steal some information and send it away to somebody else, which is a security concern. So basically, whenever you're echoing something out to the screen, you want to use HTML's special chars and you want to use URL encode for your parameters. So, that's pretty much everything I have for MVC. Do you guys have any questions about any of the MVC functionality or about anything else that David's mentioned today? This is -- model view controller is -- it's deceptively simple and there are -- there are lots of purists out there and they -- that feel righteous about their opinion about model view controller and how it should be implemented. The general theory here is that you want two things in -- to apply and this is something that we'll be looking at when we evaluate the quality of your code. We don't -- we want you to follow the DRY, the "don't repeat yourself" principle. If you're coding something more than once, you should probably figure out a way to code it once. You also want to follow the separation of concerns principle which means that for different areas of your web application that perform different types of activities, you want to keep them separated and that's good for security. It's good for mental clarity, and the maintainability of the code as well as just making it comprehensible to people that are coming across your code for the very first time. So, these are the -- these are the spiritual guiding forces behind MVC. There are many, many ways to implement it. It's a great paradigm to experiment with in this class because as soon as you're done with this class, you'll probably want to start using some model view framework or model view controller frameworks and once you're using frameworks, then it helps if you've already implemented it a few times yourself. So, I highly encourage you to implement model view controller yourself and if you're unsure how to do that, ask some things on the CS 50 help site or CS 75 help site and, you know, shoot questions off to David and the other TFs. If there are no other questions, I think that that's definitely enough. Thank you guys so much.