 So that might be a little bit small But we're actually so seeing you know these these functions sort of get state get lens This kind of thing are actually so saying right they are implying that you know you're passing the state in And you know this this kind of stuff. So if we look at this get lens partial What we're actually saying is you know it takes this This this function this this lens And then applies it to the state that we've got from this get state kind of thing It's not the clearest and this is not the simplest computation expression under the hood But basically if you assume that sort of computation expressions have some sort of context or have something going on extra behind the scenes So either just making something a sink or threading some sort of state through That's a reasonable assumption for now They're probably enough you know computation expressions and how they work and why it's probably a good to our talk, but it's But that it's you can use them and sort of expect what they do they they're all going to obey some rules so Yeah Yeah Yeah Yes, it absolutely is so let underscore It's pretty much identical to saying you know it's console.readline pipe to ignore In this case it purely is a stylistic thing Honestly, it's actually sad enough that I just like lining underscores up So it's I have a kind of I have really really specific kind of yeah You'll notice that if you ever dive through the core of something like Freya and there's a lot of it But if you ever do you'll find that it has an almost worrying attention to things like that. So yeah My apologies for that you could do that other ways Let's see if we can go back to okay, so The first half of this might have been sort of we've got everyone back or I'm missing. Oh wait Nearly everyone back. There's always one Wow, yeah, that's just just a small minor question Um, yeah, yeah, I guess I've got a second I don't know. I mean, it's like a lot of functional program languages I mean I People for years have been making these kind of arguments that it's really great for math So it's really great for scientific computing or it's really great for X. I'm not actually a big fan of that kind of argument I think that actually functional programming done well is good for anything F sharp in particular Honestly, I would say that sort of it's probably quite good for anywhere that you're currently using.net purely because There are some things which it might not be great for In some senses sort of there are some but that's mainly to do with the kind of API you're using So if you want to write really idiosyncratic F sharp and you're using an API Which relies heavily on kind of pointers and mutation and low-level access and all the rest of it Are you gonna get a great deal out of it? I don't know you might not So if you're sort of doing things like some really low-level sort of direct X access or something else I don't know whether it's gonna be a great deal better than Then C sharp is really gonna look a lot like it really where you just sort of modifying pointers to something crazy in memory somewhere But I would say it's an extra sort of general purpose language. I mean, it's I'm not sure. There's a yes or no as to when to when you'd use it Most of the people or sort of companies I've know that have had any objections to using it is mainly around People and you know people have got to learn it I'm not a massive fan of companies that sort of want to stop people learning things and sort of I've always had this a problem with people saying You know, are we what are we gonna do because all our staff would have to learn this thing? It's like that doesn't seem like the worst thing in the world, but it's Yeah Well, exactly right, you know, it's sort of anyone that sort comes up with that example So, you know, we don't want to train our staff. We don't grow them Okay, but I don't think I can really help you in a general sense then because that's just not a good plan so I Think the barriers to to sort of adopting F sharp in most organizations are probably a lot smaller than people really Really think They're usually much more about sort of politics and control and sort of perceived issues with hiring and this kind of thing Which actually if you look at things differently kind of go away I would have said for example at the moment that sort of people's ideas around so, you know We couldn't hire F sharp developers A you probably could because loads of people would actually like to get paid to do it and be a lot of people that are currently not doing F sharp We're probably quite like to learn if you actually ask them. So I don't know Yeah Oh Totally, I mean it's definitely a world where you know provided you're at least slightly sensible about what you exposed from your F sharp code You know interrupt between C sharp and F sharp can work perfectly. Well, you know, you don't Yeah, yeah, I've definitely seen it work well where people have you know sort of had mixed code bases And transitioned over time or sort of written said, okay We're going to write so this part of our code base this kind of nasty sort of grungy bit over here in C sharp because it's really good for it We're going to write domain logic over here in F sharp because it's really expressive Yeah, it depends what works of people really All right, so the second part of this and I was unconscious. We've got about 50 minutes. We'll see how far we can get Introduces kind of the next little abstraction up in in Freya, which is Freya machine There isn't really other than Freya as far as I'm aware and equivalent to this in the net well but there definitely is in the Erlang world with web machine, which is kind of really a Sort of the front-runner of this probably one of the earliest implementations I would say probably the earliest implementation of this style of web programming Closure has its own kind of world to the liberator framework. I suspect that probably others in other places. There are others in Haskell There is a framework called LEM machine in Haskell, which takes this Insanely far and actually tries to make sure that all of these are actually provable assertions They've got as far as modeling all of HTTP 1.0. They haven't managed to prove 1.1 yet, but good luck to them Having written all the passes for HTTP 1.1. They're going to be there a while So the machine style framework essentially says right we're going to stop Sort of actually sort of imperatively sort of writing our Responses to request we're going to stop sort of saying okay, right? I've got this in is it this or I'm going to write this Head or I'm going to do this thing You know someone's asked for this does that exist? I'll go and find it all right I couldn't find it. I'm going to send a 404 back and have a little branching logic And it says okay Can we actually write this as essentially a state machine under the hood? So someone else provides the state machine which represents an HTTP request and you essentially provide Information about the resource that you've got So we can actually sort of say right we're going to provide some some answers to questions About what's actually happening So I can say alright does my resource exist here's a function which will tell you whether my resource exists or not It returns true or false Here's a function which tells you whether my resource has been modified since This particular time or date it returns true or false So we can just provide some functions which are decisions We can also provide potentially some configuration to say you know this this resource you can have it in Jason You can have it in XML But I'm not actually going to tell you how that happens. I was going to tell you what can happen I'm going to describe my resource rather than programming it And underneath that what's going to happen as we're going to run Essentially a state machine which we sort of represent as a graph And that graph at each node that gonna graph it's depending where it is It's going to run a specific function which you might have provided if you didn't provide it It's going to use some default value So it assumes that a function a resource exists for example if you don't give it a function which says yes or no and It's going to do all of that sort of underlying logic first of you know alright the the response processing for HTTP And actually valid HTTP and going through all that things like content negotiation You know sort of working out whether the resource is kind of valid whether it's at the ETags and all this kind of stuff Whether it's changed It's going to handle that stuff just by asking you a few questions about your resource which you may or may not choose to answer You'll be unsurprised to learn that we have another computation expression. I'm very very sorry for that We have the Freya machine expression and this is kind of one of the the largest sort of bits of code in Freya Freya machine gives you quite a lot of ways to Sort of extend and configure what it's doing It does actually go a little bit further than things like web machine and liberator in terms of giving you Sort of I'm going to go with unprecedented and possibly unwanted power You don't actually need to use all of it so you can you can definitely ignore quite a bit Actually, you just want to do HTTP But you can do some crazy things with it if you particularly want to so we're going to build that to do back end We've got sort of 12 step kind of thing in here We've already got now about three minutes per step So we've already just skip over a few things Feel free to kind of follow along I think expecting people to actually kind of start typing stuff out and doing things at this point more exercises is probably Pushing it a bit much but sort of follow through the stages as we go and that might be kind of sensible I'm going to drop out of the slides in a second You might want to sort of wander into the sort of project part of that solution Find stage one They were actually yeah You're also going to want to go and find to do back end dot com that URL is probably going to be useful If you fire up stage one and hit that URL what it's actually going to do it's going to run a kind of JavaScript based in browser tests against the the Service you're pointing it to and say does it comply with this to do back ends back It's not going to comply. We're going to fix that So I'm going to drop out of the slides for a bit Dive into Visual Studio and the browser and hope that things work well So first things first, that's not working is it? Oh, it is. Well, that's that's almost miraculous Okay First things first. We've got a little domain model in the back end Which is our to-do list? To do back end just expect us to have a few things it expects us to be able to create new to-dos Which have a sort of a title and an order and whether you've done it or not that kind of thing And it expects to be able to sort of create new ones and modify existing ones and delete them and get a list of them And that kind of thing. It's exactly what you'd expect from a really naughty to-do list So we've created a little domain model for that in the back end If you remember I talked about a Jason computation expression, we've got that here I'm not going to go into this library for now suffice to say that these to-do to-do create and all the rest of it types are Sort of you know where we can see that this is from Jason You can sort of take Jason and get a to-do update you can take Jason get a to-do create You can turn a to-do into some Jason The mechanics of that we'll gloss over for now If anyone wants to talk about that later feel free And then we actually have basically a little to-do store Again, we'll kind of gloss over a little bit about what this is doing but basically it's Gonna expose an API which gives us a bunch of async functions that will take these these types that we've got and Do something relatively sane with them So this is the API which you're actually going to care about Exposing sort of via our API So we're going to want to have an HTTP API which essentially maps to this in some way Hopefully that bit's relatively clear All right We'll forget our domain for a little bit. We'll go take a look at stage one. We'll set this as a startup project and We'll see what we've got in there So the first thing to note is we've got a to-do store. We've got a little instance of that up here It is just a you know, basically a static instance. We're not going to worry too much about You know nice kind of dependency inversion and anything else or anything at this point This is a naughty example We have a Freya machine Which does nothing right now and we're also going to have To-do backend which is a router Which has one resource in it. You'll notice that that's not a root anymore If we're using a Freya machine and we open up Freya machine router We get some extensions to the syntax of that Freya router Basically a resource is a root which responds to all methods. It is literally shorthand for that. It's just neater and What you've said is so we've got our to-dos function Which is a Freya machine That's going to represent a resource and we're going to turn that into a pipeline And we're going to mount that at the URI slash just the root URI Now we're going to fire that up and then we're going to hit it with To-do backend and it's going to monadus and it does and it's going to monadus because There's no cause support anyone that's had Fun working with a spinet web API will will know this one if you want cause support It's wandering off into a web.config and doing horrible things and adding cause support in and this kind of stuff Calls support for those that aren't aware of cause is basically sort of our browser wants to know that it's allowed to make a Request to a different domain cross-origin all this kind of stuff. It's a pain you need to support in HTTP We can do that in Freya So the first thing we're going to do is add in our cause support That's going to look like this so To support cause we need to tell Freya which headers we're going to let people use from a cross-origin request We're going to let people then need to tell it which origins to allow a request to come from in this case We're going to allow it from any These types incidentally are all the strongly typed RFC standards So we actually have sort of strongly type representations of all the RFCs around HTTP and the w3 cause specs And we're also going to need to let it know which methods we're going to accept Both for cause and for this resource in general One of the other things we're also going to need to do is say that we're going to use cause in this resource So these using statements are a little bit interesting so the Freya machine and this is one of the places where we differ a little bit from web machine so what we have in the Freya world As I said we we work with this kind of thing as a decision graph So we represent that response to HTTP is asking a bunch of questions and running a bunch of decisions Out of the box the Freya decision graph looks a bit like this Which isn't great So it's not very HTTP compliant because we've told it to do nothing so far. So We actually in Freya. We let you define your own graph If you want to do so we provide an HTTP graph We provide some extensions to this and when you actually write your own graph or write your own extension to a graph What you're actually going to do is you're going to go in and say okay add a node connect it to this Or remove this edge and reconnect it over here So where we can see that we've got using HTTP what that's done is added a load of nodes into my default graph If I didn't have using HTTP or using cause it would literally do that We would start a request we would end a request and we would get a blank request back Because I said it's using HTTP When this Freya machine gets compiled or when it gets turned into a pipeline It's going to go through and it's going to modify that graph. It's going to add all the nodes in which represent HTTP And then it's going to compile it's going to turn into a graph that it can execute But if I want cause support I Also want to use HTTP cause and what that does is it says okay I expect to be run after someone has added HTTP support to the graph So I have a dependency on HTTP And I'm going to remove a few edges from the HTTP graph And I'm going to put some more nodes and edges in there to handle the logic for cause So if you wanted to do things like supporting web sockets or Supporting web DAV or other bits and pieces what you could actually do is you could write those as a graph extension So you can actually say okay right there are some new decisions need to go in here I want to extend this in a different way If you wanted to say actually we never do content negotiation I don't care about that anymore as an optimization I never want to even try and run this you could run it You're something which actually removed content negotiation from the graph So you just completely skip that step and you never run it and it's quicker now so It's kind of useful. It's definitely a power feature It's definitely something which you don't want to be using much of the time and HTTP and HTTP cause will get you 99 point at least an Erlang like five nines level of what you want But if you do need to do something Well, yeah, I've built things with with nine fives. Unfortunately. Yeah So by doing this and adding HTTP and HTTP cause we've now got our graph which supports HTTP And it supports the right things for cause too It's going to look for those cause headers in the request and it's going to ask the right questions about us when we process it So we need to tell it which headers we support for cause which methods we support which origins we support We've done that here You'll notice there's a lot of custom grammar in this So this computation expression actually has a lot of custom keywords We actually do things very declaratively. This is just about defining what our resources We also say that this this to-dos resource supports Get an options to start with as well That's actually the default I think I might be getting head I think if you if you don't tell it which methods it will support it I'll assume you just want to get results But we might as well be explicit about it here. That's kind of handy So hopefully now if we run at stage two We might see and feel free to follow along in your code or run things if you wish We might see that we get perhaps if we're lucky different errors Yeah, we did okay, so It tried to get it cause headers are cool But if you can read those errors that though, which you probably can't kind of make this any bigger I Can a little if you can read those errors, it's gonna say, okay, right? Well, we made that request, but we got a 406 back. We we kind of you know, it wasn't acceptable Well, that's because it's expecting Jason. It's expecting that so, you know, it's gonna say You know, I want to get Jason back from this and we haven't told our resource that actually, you know You can respond with Jason In fact, we haven't told it anything and by default it assumes that you can't respond with anything or it's just plain text So if we want to actually tell it yet, you can deal with that. That's okay We do something very similar. We'll go ahead and we'll add something in So we will say that to do is media types supported Are over here and we will say that we support Jason and we'll go ahead and add that into our to-dos Machine down here. So I can say all right. So now it's gonna support Jason So we should that's actually gonna handle all of the content negotiation that we might need So now it we've told Freya and Freya machine enough to know that yeah, okay No, no in this case so ordering in this doesn't matter at all So these are literally just declaratively specifying you can group these order them However, you want to do however it makes sense in your You know in your thing you might find later on that sort of grouping common sort of bits of configuration together is useful that kind of thing But order doesn't matter. Yeah So One of the things that you'll start to note that at this point and this is another area where We go a little bit further than some implementations of things like sort of machine style frameworks Is that you'll notice that these functions are actually Freya functions So When I'm saying sort of the media type supported. I'm not hard coding this or at least I'm not setting this at compile time as such It's actually going to evaluate this function at runtime So I can actually put logic in there if I want to all of the configuration and all of these types of things Wherever I'm setting this stuff up. I can actually change the answer to these questions at runtime if I wanted to You usually won't again, but sometimes this might be handy. Let's say You've got two versions of your API or you know, you've got a version of your API Which has got a standard and enterprise version and you want to say, okay So the standard version only supports Jason the enterprise version supports Jason and XML because they're masochists So, okay, that's cool The media type supported in that case you might say right Well the enterprise version they're going to come in with a specific header, you know Or some sort of bit of authentication or something else which they're going to have set So you might say in this media type supported you might say, okay, let's let's match on that header if this header exists We're going to say that the media type supported adjacent XML if this has a dozen exist. We're going to say it's just Jason So actually not only if you sort of you know, you've implemented that switch in that logic But your HTTP responses are now going to be correct based on the caller So when someone does some of my options or they do a head request or anything else the content negotiation is going to be Right. You don't need to hard code this You can actually do all of these things dynamically The same even the same with saying what methods you support. These are all dynamics You can say, okay for the enterprise clients we actually or you know for these clients We let you modify this request we use support posts for these people but not for these It's almost impossible to anything like that with someone like web API, which is kind of fun You can even do things like saying, okay, right. So we will support Obviously, we're doing this on a per resource basis too at the moment. So you can say right, okay We're only going to support cause on these particularly your eyes of these types of resources for this person There's no way you can do that with anything like web API or anything else, but As I say, it's not something you always need But if you want to be really accurate and precise and actually define an API which you're completely in control of This is the way to do it Unless you want to go very low level All right, so hopefully we've now told it that it can deal with Jason. So let's see what it's going to Find now. Let's see in which particularly exciting way it crashes and burns at this particular point So we've failed before we're gonna fail in the same way. Ah, we actually did respond to a get we passed our first test Which is always a nice moment Cause had a set up It could deal with Jason the content negotiation works. It was great. I Didn't respond to a post. In fact, it said no it failed cause again It just didn't get there And indeed it probably actually tried to send an option request and it would have wanted to get back post But we haven't told it that it can support post Let's take a look at stage four All right stage four Well, we've taken opportunity to do something a little bit different in this step because we were starting to get You know quite a lot of things in our one resource and we know that actually they're going to be common for all of the resources We have Everything we do here is going to support Jason. It's all going to use HTTP. It's all going to use cause We're going to support the same Origins and and media types and headers Across all of our resources. So we pull those out into This common for a machine here So we're going to reuse that and we're going to say right now out to do's We just include common And we can do that as much as we want. So if we have something for example So we have some specific sets of authentication logic or security that we want applied to all of our Resources we can pull those out into a common machine definition and just include those in the resources where it applies If we wanted to be a little bit clever than that, we could say okay We're always going to have a security Sort of module or a security function, which we can call but maybe we want that to be parameterized Well, we can do that too. We could actually say right Okay, this this common takes a parameter and then we include it with a parameter in different resources You could say, you know, the security model takes a high or low And it will have logic in there which will which will look for that kind of thing It's all composable. We can build it all down into small little chunks and reuse them But for now, we've just pulled out kind of the stuff which is going to apply to everything We've we've got our HTTP and cause graphs. We've got our cause headers now media types We've renamed them a little bit just so that we know they're common We've sort of pulled them out a little just so we can start to distinguish between the things which are resource-specific and the things which are not so The methods are going to be resource-specific. We've left them there and so out to do is resource now just looks like This common to do is methods etc. So because those are the only things that apply to only this result You'll notice that we haven't actually changed this yet. We'll do that now in stage five So I'm going to set that as the startup project We'll come back in there. We find we've got the same stuff and We support post now if we're going to support post though We're actually going to need to do something with that data as it comes in And again, that's again about supplying the kind of function which our resource might need to handle a post So in this case, we will say we need to implement do post in our machine And we're going to give that a function Which is just another Freya function in this case it can just be a Freya function of unit We don't expect this to actually return anything We just want to know that when we actually have a post request comes in we need to run this function So this is going to get a little bit more involved just for a moment. We'll see what that looks like This bit you're going to need to take a little bit on face So We've got the request body coming in which is going to have a new to do to be created So we're going to have a function a Freya function which actually reads this And we say okay, I want to get the request body And then I want to read that request body into This this string of data. So hopefully what I'm going to get in at this point is a big Jason string And I'm going to use my Jason library to try and turn that into an actual object of some type Now what you'll notice from this is a it's in line and be I'm not specifying what type of object This is actually going to return Because I don't know this this function is actually going to use static type inference to work it out So later on wherever I ask for read It's going to try and infer what read should return Based on what I'm about to do it. So we're going to use the F sharp type inference To actually make this this multi-purpose read function Which can just give me a type of t or a or whatever we want to call it depending on how askly we're feeling Based on my need at that time Actually, it's going to return an a option because I don't know that I can convert it from Jason But it's hopefully we're going to get one so I Gonna create this function called to do's add And I know that what I'm actually going to want to call is that to do store function to add a new to do That's what my post is going to be So I'm going to need to create. I'm going to need it to do create Type or to do create instance at that point because I want to pass it to do store dot add And I can just call read because the type inference is actually going to say yeah, okay You needed to do create here Because you're passing it to this And I'm going to use this Freya from async function, which is if you're on a sort of more Haskly world is essentially lift this essentially takes an async function and Means that we can call it from Freya So I'm going to create so Freya from async to do store dot add With my to do create which came in as the body So this read function reads the body of a request and turns it into whatever I need hopefully And that might seem kind of unpleasant But the useful thing to note about that is that you only need these once per sort of well app really You know, this is really generic reusable code You could actually probably do the same thing to XML if you probably if you needed to do so This is going to basically to say right, okay, wherever I want to read the body Just do it for me So we'll note that we've got this function down here. So this is going to take To create from the body It's going to add it to the to do store and what's that your turn? Well that to do store function returns a to do Which is going to be useful so We've got our to do's Add do and actually I've just called this function here Because in my do post function, I don't actually care about the result. I Just need that to be unit. I'm not going to care what that looks like So I do to do that. I throw the result away and I return unit and That's what I call in my machine So we'll see what happens. Ah, I still failed. Well, like it's happily I expected to But the reason I failed is different now So yeah, I support post and it did a post but it didn't get the to do back which was passed to it in This case to do back end actually wants us to respond to a post with the to do item. We just created Which is a bit weird, but you know, it's but it's fine. We can deal with that What we'll do is we'll say, yeah, that's fine. I've handled the actual posting But now I need to handle what the response looks like when I've created a new object. So Still got my to do add still got my to do's add do Now I've got my to do's add handle and down here. I've said, right. Okay. So handle created. So this is going to get called When I've created new objects. So 204 or something like that some of my graphs This is going to get called when everything's happened or needed to actually send a response all of these functions like handle something are all about Sending response back to the client Default one which we'll see in a moment. It's just handle. Okay. If we just get a 200 if you just do a get handle Okay, we'll tell you what you're actually going to send back All right. So to do that handle. It's a little bit more complicated again. It's the last bit of little bit more complicated. I promise In this case, I actually do care about sending that to do back again But I know that my to do's add function actually gives me the to do I want So I'll just go and grab that to do from the to do's add function up here and Write it back to the to the client. I'll write it back to the body two things about this one right is kind of Interesting and it's very much like our read earlier It'll take any object and it will write it back to the body And it will actually write it back and it'll say it's utf8 and it's Jason and it's in English and this kind of stuff I'll come back to that a little bit later because that's about how you respond to content negotiation in This particular case. It's not a big deal because we only support Jason. We're not really doing any negotiation I can hard code this But I'll just mention a little bit later about what's happening. We're actually supporting more The eagle-eyed and eagle-brained however will obviously have noted that I've called to do's add twice In this approach and that's probably not really what I want So I've handled that post and I've added it to do And then here I'm running it again to get my to do back again So I'm actually gonna have added this to do twice if I'm not careful and that's while that's rubbish so We have this little chunk on the end here called Freya memo Freya memo is literally a memoization function which will take any Freya function and Will make sure that you only run it at most once per request So it'll memorize the result of that function and bung into the environment state So whenever you call it more than once he'll say have I already got this. Yes, I have I'm not gonna run it again Give it back to me so now I can just say right, okay, I'm gonna create this to do's add function and It's safe, you know, I it's gonna call add to this to do once it's gonna return this to do once So now wherever I care about what the result of that was I can just call it as many times as I like But I know that's that's that's cool now. I can I can deal with that So I call this in two places, but I run it once And also I can be sure that the ordering doesn't matter because I need to do this somewhere And even if someone changes the order of my graph Well, it's not a problem if someone calls handle created before they call do post Well, the same result is going to happen. It's idempote So hopefully stage six Should give us Yeah, you posted something and you got it to do back. Let's see Yeah Fantastic So I'm handling my get I'm handling my post. It's all working. Well, I'm not deleting it That's not brilliant. We can probably all guess what's going to come now. I Need to handle a few more methods Simple as this simple as saying right. I'm gonna handle. I'm gonna add delete to the methods I support on this resource and I'm going to add a do delete which is the function which I want to call when someone actually Sends a delete verb up to this resource And for that, I'm going to want to call the clear function on my to-do store So this is actually the root of this API. So this is delete the whole collection to do is not a single to do So I'm going to want to clear my to-do store And again, I only really want this to happen once per request. So I'm going to just memorize that function And then I'm going to have my to-do is clear do function Which takes the result of that which is actually probably unit anyway, but just for For fun here and just to make sure it's really clear and take the result of that straight away return unit Now I support delete I hope let's see Yeah But my get response didn't work. Well, that's fine. I haven't actually implemented my get response Get responses are simple though. So we just need to handle the okay case And this is going to be even simpler than before So this is actually to-dos list So this is get me my my collection of to-dos I wrap my to-do store.list in my frayer from async I only ever want to do that once I handle this thing. I grab my list of to-dos I write it back And I do handle okay So at this point I'm handling all of the things which I probably need to do on this resource But we will find out So handle okay is just the the handler function for A get request basically so if your get request was successful So you got all the way through to a 200 you didn't sort of bomb out it was found it existed all this kind of jazz If you've got things like if it happens to a 404 You can give it something like handle not found or handle not acceptable You can override all of those things by default though. They will actually do something sensible They'll return the correct headers. They'll return all of the right negotiation that happened That 406 not acceptable that we saw earlier on Actually did return a proper 406 correct status correct headers correct negotiation You know here are the things you can actually do It's just wired in if I wanted to override that I could do that by handling handle not acceptable But I don't care generally most of the time if I'm just writing an api in which I'm expecting some client to consume I don't need to make it pretty. This is going to do it for me So stage eight where do we get to? Cool. So prerequisites of working We've got a few more tests for free, which is always nice. So adding a new to-do worked Uh to-dos had a URL New to-dos weren't completed. This is all great. This is all coming from our domain model. That's all fine They do have a url Which is just a good Uh And it should return us to do but it doesn't because I don't have a resource which represents an individual to do at this point Let's go create one and wire it up So I've I've still got my common stuff. I've still got my to-dos And now I'm going to write a new A new little resource called to-do I'm going to include my common stuff and it's going to have get and options Uh, and I'm going to wire it up in this router down here. I'm going to say it's just a slash id so That's probably going to fail right now I'm not even going to bother running that because we know that we haven't actually implemented anything Which it might want to do and we know from what we're talking about just now that actually if I'm going to need to respond to You know get to that id url I'm going to need to at least implement handle. Okay Because it's going to expect to get it to do if I hit that url So I'll move on to stage 10 And we'll see how that looks It's going to look very very similar Okay There's one interesting bit here, which is actually fun enough what you were talking about earlier on Which is that now actually we need something out of the root, which isn't just a string Our api expects us to have a good um, in this case we do it quite shamefully So we actually just go right. Okay. I'm going to assume this is a good I could be a little bit clever about that. I could actually try and pass this into good I could actually allow for the fact that might not be a good because I haven't enforced that in any way But maybe we could do all that later on if we wanted to For now I'm just going to go right. Okay. I'm going to assume this is a good It's the id atom from my root So this to-do id function is a function which will give me uh, the GUID That I that I care about So I'm going to write my to-do get function And I'm going to memoize it and it's just going to be right. Here's the id of the to-do that I want I'm going to pass this to to-do store dot get And I'm going to go okay, and here's the handler function I'm going to write that to do and I'm going to handle okay with my to-do get handle And if I run this we should find Do we get exactly what we expect? Which is that yeah, it now has a url and it returns us to do and that's great And now I fail on patch All right, that's cool. Let's go in our patch support. We're nearly there We will find that actually that's just as simple as saying right. Okay. I need to call the update method now on my uh On my to-do store. This is the first one. We're actually combining a little bit of data So we're saying the id of the to-do that I care about is that to-do id which I'm reusing from earlier The the update type that I need to send it is the body and the uh, I'm going to call to-do store to update and I'm going to pass it this little tuple of data and Again, I'm going to actually need to handle this patch case, which you would expect. Yeah Yep, you're right. We don't need it right now. We don't need it By default I tend to do this so if I've got something which is mutating something Sorry Yeah, it is a little bit of overhead in this case. I could remove that if I came back to this program I thought right, okay I'm going to put this in production. Let's go through and make sure we're not doing anything crazy I could remove this because we can actually be pretty confident that we only ever call this once Yeah Pretty much. Yeah It's one of those sorts of things where you're you're rarely going to go wrong sort of adding it If you don't need it in the sense that you know, you probably do actually logically only ever want to call this once Um, the overhead is there. It's not zero. It's pretty small, but it's not zero If you get to the point where that's an issue and you can say, okay, actually I've looked through this I'm never going to call this more than once cool. Yeah, go ahead and remove it You may find that, you know, if someone comes long later and adds another You know handled this function then it might have some unexpected side effects But that's just code and refactoring for you But yeah, in this case, we don't need it So I've handled my patch method. Uh, you'll notice that the, uh Method I've had to add here is actually a custom method patch is not in the http rfc It's an extension rfc, which I haven't added the type support for in this project But I can actually if I want to support any custom verbs, I can just have, you know, custom custom method here Yeah Yeah, and the reason that we need to be able to do that is because they're obviously so if you want to Start supporting things like webdav or or any of these kinds of things or if we wanted to create our own API vocabulary on top of http And this is where we get into that sort of really off in the weasel abstraction It's often quite valid the moment and say yes, I do actually want to create my own http verb You know, I have an api where that makes sense. I'm going to create my own verb and I'm going to extend this machine I'm going to create a new graph extension I'm going to create a new verb and here's how I'm going to handle that And now any of my my devs or any of the people working in my team as long as they just use these resources You know that now handles our version of http Yep, you could do either way Yeah Obviously sort of there are standards which require sort of more verbs than plain http That's exciting It's because I'm on a different network go away Wow Okay, I'll be back. Yes, we are I promise this isn't a dodgy version of windows. It's just because it's normally in boot camp and now it's uh I haven't ever seen license. I swear Um, I wish I didn't but I do So We've got this we've supported patch If we fire this up, we should see that that works Final thing we can't actually delete a single to do Uh, we're passing every test for that one. Let's just make sure we support delete Stage 12 We'll be there Okay, so at the final thing to add was just this uh, this delete support And then I added delete support my to do so Let's just make sure we at least pass everything before we start to have one more fun things Yes Yes, we do so we've got a complete api. We've met that back end. We've met it really accurately Uh, we've met it. We're complete control over what we're doing Um, but you might have noticed there are a few things in there which are potentially a little dangerous Uh, and you might be tempted to address these in uh specific ways in more f-shot ways But there are ways you can do this with the machine So let's take an example So where we've got out to do here We don't have Anything which says, you know, we've assumed that our handle. Okay. Actually returns are to do If someone sends me something which is a good which does not exist as to do what am I going to do at this point? Well You know, I could go into my to do get function and sort of do You know, maybe some kind of Kind of match statement on my to-do store.get and this kind of thing in my to-do handle I could you know try and well I could write the headers out manually and send a 404 back or something like that But I don't really want to do that And the good thing about this graph approach and about the machine approach is that actually it's just another question I need to answer on my resource So the to-do back end doesn't actually mandate it doesn't run any tests which try to get you know a non-existent to do And actually Sort of do something sensible with that It should probably if you're actually going to write a good test suite It's really tested actually get a sensible result back when this fails at the moment We'll get a runtime exception. That's probably not brilliant So what we could do is we just need to answer another question about my to-do So I'm going to add that here and what I want to know is does this to do exist? And again, it's just a question I need to answer. So I need a Freya function, which returns a bool Now I know that I've actually got my function which is to-do get which I can run as many times as I like and it returns us to Do option So I can actually just write a quick new function For something like to-do exists And I could say That might to do Equals to do get A return Option dot is sum To do All right So now I've got that decision function. I can say, yeah, okay, just uh Somewhere in the graph before you actually go and try and sort of send them this to do check it exists first So now if I actually get that I get 404 support for free now So wherever I want to do this In this case, I'm doing this in a way which just uses my actual to-do But if I wanted to write a really large api and I wanted to design performance or I was on working on a facebook scale Actually, we probably want to make things like existence checks a lot more optimized than this If we don't want to go and get some expensive resource, which is you know Takes time to go to a dp We might actually want to say that actually We want to check that as it all exists just in a local catch or we have a redis store of you know, id to exist And now what I can say is right, okay Well, I'm going to implement this function over here, which just goes and checks in my existence cache I might then decide to say that okay. Well I'm going to do that for every resource I have Uh, so I'm going to have a read through cache which says, you know, does this a resource exist? Uh, so I might then decide to say right. Okay. Well this existence check Uh, it's going to go up here And I'm going to say that that existence check actually is A resource exists some fictional function, which I haven't done and now all of the resources I have Have 404 support properly optimized, etc. And I can do that in one place There's lots more you can do like that And there's lots more that you can start saying, okay, right Well, we can control a lot more about what we do on a resource by resource basis Uh When I don't need to think about, you know, what my framework's doing in a specific way I only need to answer the questions I care about There's a lot of questions I can answer. I can answer lots of questions about, you know If I give this a function which returns an e-tag Or something like that, now I get, uh, you know, some negotiation around Live-ness for free If I give this a function which gives me a last modified date Now I support all of those things and I'll automatically send the correct headers so that clients never actually You know request data they've already got All I need to do is just give it a function which returns a date When was your thing last modified or a function which returns a hash for an e-tag? It's all strongly typed. Incidentally, I need to return an e-tag type but It's there So that's kind of the very basic Machine usage and you can start building up really complex apis very easily Uh and start pulling out more and more functions and building this lots of reusable little building blocks that you can create to actually build Big complex apis was only writing one piece of code once There's a couple of little things on our roadmap which also might be fun Let's see where I can find When I talked earlier about levels of abstraction Machine is obviously a chunk art from just working with Freya and working with the request and response directly It's Has a lot of things which are kind of useful If you want to start supporting things which are actually hypermedia Then you can build a layer of abstraction on top of machine So you're gonna have to forgive the fact that this is in the monadic syntax Not the other one. This is Freya Hal Jason See how zoomed in we are If we have a look down the bottom here, we see that we have a resource which is actually defined as a Hal Jason resort It has state. It has embedded links. It has embedded resources All of these are strongly types We have a type system which embodies Hal Jason Uh, we can run this a runtime. This actually compiles to a Freya machine And it compiles to a Freya machine with metadata. So it automatically generates the swagger documentation for api So it gets kind of interesting This is an example of we can say right, okay The right level of abstraction for my company or for my api or for my project that i'm doing is here I'm going to work at that level of abstraction. I'm going to build a new one We have some interesting projects going on to sort of push out new Hypermedia standards. We're going to planning on supporting things like Jason ld Jason hypermedia some of the new stuff that's coming out Uh, and you'll be able to do that. Just say, okay. Yeah, I'm just going to give you Just my type and here are the links and here's the rails and here's the uris and here's the stuff Which actually make up the logic of my api I don't want to care about how you send it. I don't want to care about how you serialize it I don't care any of this stuff I want to describe my api to you in this strongly tight way And I want you to deal with all of that stuff and it will This will give you a full jason Howl jason typed resource of proper hypermedia standards just by defining What are the actual parts of this thing? You know here is an author. It has books and publishers in it. Here is the uris for those Here's how you develop a link We're even doing things like saying, okay, so the uh, the URI for an author we use within the representation of an author We use it in here We also use that We also use that URI Exactly the same thing We use the URI to wire it up in the router So now if we actually change the URI for anything in our system, all of the URIs will update and we can automatically get this So our hypermedia api Automatically relinks itself. We homes itself. Everything is now relative to each other and we have a strongly typed way of dealing with that Version for free to Back to slides if I can make the project work very briefly Okay, we had a worked example Hopefully it was reasonably clear in terms of how we started to build things up There's a lot more documentation and interesting things you can do with freya It's a lot more powerful than Some more traditional approaches to building things it gives you a lot of extension points and hooks a lot of fun things to do with it I hope you go and play with it and if you've got any questions Can we give me a shout like now or after I'll be wandering around? We are Bang on or one minute past never mind close. We were pretty close to time. So Probably not enough time too much for q&a But if people want to hang around afterwards or find me later or lunch or anything else, that'd be cool And thanks for coming along