Check out a free preview of the full Advanced Elm course:
The "Scaling Solution" Lesson is part of the full, Advanced Elm course featured in this preview video. Here's what you'd learn in this lesson:

Richard live-codes the solution to the Scaling exercise.

Get Unlimited Access Now

Transcript from the "Scaling Solution" Lesson

[00:00:00]
>> Richard Feldman: So viewform works on something called form quite a bit. So it's a safe bet that we're gonna need that as a dependency. So let's see where viewform is being called. It's currently being called passing a model. Let's change that so that instead of taking the entire model, it's just taking the form.

[00:00:19] And so we'll delete this and replace it with, we just accept the form as an argument. And let's see what that does for us.
>> Richard Feldman: Okay, no problem. On to the settings. Sorry that is a problem. Just kidding. So the next line we immediately say Session.cred model.session. So we're still referencing model inside this function.

[00:00:48] But we're only using it to get the session cred. So there's two possibilities that we could do here. One is we could say I'm gonna accept so Session.cred.function returns a maybe session which we're immediately pattern matching on. Two possibilities, one is we can take a Maybe Session.
>> Richard Feldman: And say okay, we're going to say maybeSession right here and continue as normal.

[00:01:18] That's one way we could do it. But another possibility is we could say, you know what, all we do is we render nothing if the Session is nothing. Should that really be here in the form, or could we actually narrow our type even further and say, this needs to have been handled already?

[00:01:36] It's not this function's job to deal with the possibility that there's no session. Just don't even call me if you don't have a session. I don't wanna here it. Yeah, we can do that. So we can move that to up here and say, case, sorry, cred., no session.cred.

[00:01:54] Model.session. And now we're handling that case out here. And we're only calling viewform passing the credentials. If we already have some cred to give it. Another possibility is that we can see that a form is being used down here. If we want, we can just inline this whole thing and just say, you know what?

[00:02:23] Right here, right here in the middle of this thing, we're gonna say, if we have some cred, we're gonna render a form here, and otherwise we're not going to bother doing that at all. Any of those possibilities are perfectly reasonable. What I like about these one is that there is sort of the list in direction everything is sort of right there where it is happening.

[00:02:44] We can see right here if we have credentials we are right at the form otherwise we will not we can see what is happening at the dome without jumping somewhere else. And then the form itself, sorry the view form function itself takes the least, the most narrow types that it possibly can.

[00:03:02] It says all I want is the cred. I don't need the rest of the session. I don't need to know about the maybe, that's already been resolved for me. So when I'm scanning through I can see sort of a, I can learn the most about this function at a glance.

[00:03:14]
>> Speaker 2: Richard?
>> Richard Feldman: Yes.
>> Speaker 2: You're, aren't you already inside a block where you know you have a value?
>> Richard Feldman: Entirely possible, yeah good point [LAUGH]. Yeah, so actually that compiler error is telling me I'm shadowing this, which is a great point because at this point, we already have it.

[00:03:31] So we can do significantly better than that by doing it like this. That's much better, I don't know why I didn't think of that. [LAUGH] Questions on that?
>> Speaker 3: When you were refactoring the arguments you put the cred on the left side of the form is there-
>> Richard Feldman: Yes.

[00:03:53]
>> Speaker 3: Is that required? Or why did you choose to put it on the left versus the right?
>> Richard Feldman: That's a great question. So certainly it would work fine either way. Generally speaking, when I think about argument order, I'm thinking in terms of how will partial application be effected.

[00:04:10] Typically speaking, if I'm going to partially apply a function, usually what I'm going to do is I'm going to personally apply it with some sort of piece of information that's sort of unlikely to change among multiple invocations. So if I'm calling viewForm. Like, viewForm is kind of a silly example because I'm probably only ever going to call it one way.

[00:04:29] But let's say we're calling some other function that needed cred, like, I don't know, maybe I was displaying. What would I be displaying? Not favorites or follow buttons because that would just also just be sort of like one per, I don't know. Anyway, let's say I have three different buttons, all of which are slightly different and they all require credentials.

[00:04:50] I'm much more likely to say, view button with credentials equals view button cred, and partially apply that, than I am the rest of the arguments because they're more likely to change. Credentials very unlikely to change, so whenever I have arguments that I think no matter how many different times I call this.

[00:05:05] This is the least likely to ever change, I tend to wanna put those up front so they're more partial application friendly. So that settings taken care of that's the first of our three to do's. Let's take a look at home next. So once again we have a function that's sort of taking too much view tabs takes the model when it really doesn't need to be.

[00:05:24] And the reason I know that it doesn't need to is that immediately what we do is we say model.feedTab of. And once again, we're in a situation where we have one argument, and then we also have, we're looking at cred in the session, and that's basically all we're using the model for.

[00:05:39] We certainly don't be need to be using it for all that. So we can certainly take feedTab as an argument instead of model.feedtab. So this is specifying which of the three tabs on the home screen are you potentially viewing, which is to say either YourFeed, GlobalFeed, or TagFeed.

[00:05:59] And so that's one of our arguments, but then the other one that we still need is the model.session, which we're currently only using for cred, we're using it in two different places. Now, unlike the previous case, here we actually do do something slightly different if we don't have cred.

[00:06:16] So it's not gonna work out to say, this function requires cred and we will rely on other things to take care of it ahead of time. It's actually quite important that we do get maybe cred here because we need to do something different in the event that we get.

[00:06:31] In the event that we have access to cred or not, which is to say we've rendered different tabs depending on whether you are logged out or logged in. If you're logged in we will render your feed, but if you are logged out we will not render your feed.

[00:06:43] So in both of these nothing branches you don't see your feed appearing in there. Okay, so we will take maybe cred has an argument.
>> Richard Feldman: And that's a significantly narrower argument than all of this.
>> Richard Feldman: I think I'm gonna do the same thing over here.
>> Richard Feldman: Okay, and finally we need to actually pass that into viewTabs.

[00:07:11] I'll do that with saying viewTabs and passing that as the first argument and then model.feedTab as the other. I think that's correct. Let's see.
>> Richard Feldman: Great, success. Questions?
>> Richard Feldman: Yeah.
>> Speaker 2: Could you have just passed the Session in and left that logic in there, or are you just kind of cleaning it up?

[00:07:43]
>> Richard Feldman: I'm doing it this way because this is even narrower. So the Session holds onto the cred, but also other stuff. And I don't want a tab access to that if it doesn't need it. So this is sort of the narrowest possible type I can give it to where it can still do its job.

[00:07:58] The narrower the better. That's a general default. Let's move on to the last one which is the profile page. So this one's taking the model. It also needs to take some other arguments. But let's see if we can get that model down to as little as possible. So here, we're calling currentUsername and the model.

[00:08:17] We're also once again, getting cred off the model. And it looks like the one other place that we pass it is in feed.init, and feed.init actually does want to take model.session. So here, we have a case where we can't get away with cred, because this needs more than that.

[00:08:35] We also can't even get away with maybeCred, because really what we need is we just actually need to pass a real session to feed.init. So if we look here in feed, the init function just takes a plain old Session, no maybe involved, and so there's really no way of avoiding, yeah, we just gotta actually have a real session in here.

[00:08:55] Having said that, we can pull our cred off of it separately, so that's fine. So session and the one other thing that we're using the model is that we're casting it to get, sorry, to current user name to extract the current user name from it. But we can just say, what just go ahead and pass that username in.

[00:09:16]
>> Richard Feldman: Sorry, username. Okay, so now over here in the feed, we're gonna pass model.session as the first argument and model dot, no, it was currentUsernmae. That's not spelled correctly at all. There we go. Also, nope, nope, model. Okay, and something is wrong. Okay, wow, that's a lot of stuff that's wrong.

[00:09:47] [INAUDIBLE] fetchFeed session username, that's a session, that looks like the username, correct feed tab, correct page. Are we calling this in multiple places? We sure are. Okay, that explains it. All right, so let's fix it in the other places too. So this one's also going to need a model.session, and also currentUsername model and

[00:10:24]
>> Richard Feldman: Let's do that again, let's try that again. There we go, okay.