 Okay, let's do this. Hello everyone. That's me again. Well, if you haven't been here, I've been doing also talking in the morning. This time it will be about reinventing MVC pattern for F-sharp web programming, which is kind of interesting topic because usually, when you think about MVC pattern, you think about object-oriented programming, and here I will try to show you how we attempt to re-implement this pattern with functional programming principles. So my name is Chris. You can find me on Twitter. I'm active member of F-sharp open-source community. You may know me from some of those projects from the photography. If you are a dotnet developer and you're on Twitter, you may know me from talking a lot of not nice stuff about Microsoft, which is false Microsoft is super cool. So why this talk? The idea is really simple. Web is functional. You basically can model any HTTP server as a blockbox as a function that takes HTTP request, and after some time, it returns HTTP response, which means that it seems as a perfect fit for the functional programming. Functional programming is all about taking some input, doing some magic inside the function, and returning some output. Currently, in F-sharp, there exist two frameworks that attempts to use this principle of just there is a request and there is response to model the behavior of the web server, and they're called SWAF and Giraffe. SWAF is standard loan implementation. It implements also its own web server. Giraffe is implementation built on top of ASP.NET Core. They are basically the same in terms of like abstractions they use. There is just this one small difference. So the abstractions. Let's imagine this is F-sharp code, but it should be fairly simple. It's almost like pseudo code. So I hope that it will be clear. Let's imagine that we have type HTTP context that contains three elements. It's incoming HTTP request, it's current state of HTTP response, and it's some additional info about server, environment, and so on. Then we have a function that takes HTTP context and potentially, so optionally in the future, so it's asynchronous operation, can return a new HTTP context. Why optionally? Because maybe we want to stop processing at some point at the time we don't want to follow the path of operations that we will create. We have this really nice Star Wars operator, rocket operator, whatever you want to call it, this arrow thingy. It actually has serious name in like category theory but let's go into that part. It takes two web parts and combines them together into third web part. Here is sample of usage. One more thing. Usually, there are two kinds of web parts. One kind is doing some type of tests. Is this request get request? Is this request something else has given value in the header? The other kind of web parts are web parts that are modifying response. Let's write hello world to the content of the response. So here is really simple example. Firstly, we check if the request is get, then we check if it was on the dash slash test path, and then if that was all true, then we put hello world in the content and return to user. So that's one function really important. The second really important function is choose function. It takes list of web parts and combines them together. What it does, it's one by one executes web parts to the moment when it actually finds the web part that is fully successful. So it goes to the end. So if request is coming here, it goes to this first web part, it checks if it's ping. If it's not ping, then this whole operation returns nothing. It goes to the second and so on, so on, so on. This is just simple example. If it is ping, it goes here, this just returns response to the user. So this is fairly simple model, and what's really nice about it, it's really composable and it enables you developers to model a decision tree about what's happening inside your web server. So this is basically decision tree. The first decision is what kind of the request it is, get, post, or something else, then if it goes to the next decision, so on, so on, so on. So it is flexible model. It is really powerful model because you can model with the decision tree, you can model on the behavior. Unfortunately, and don't get me wrong, like I will say some negative points of this model in a moment. This is really model that I've used to introduce web programming in general to many people that have not been not doing web programming before, and it's easy to understand, it's easy to use, but it has problems. First of all, it doesn't scale, and by that I mean it's not by performance, but it just doesn't scale with the size of the application. You can imagine that this decision tree is growing and growing and growing. If you have application with 50 endpoints, 50 rest-ish endpoints, every rest-ish endpoint is like six verbs or something like that. You can imagine that, oh, this decision tree is massive. It is thoroughly low level, so you need to check everything manually, do all checks on your own in code, and it doesn't provide structure or guidance and what I want to say with that is that because everything is web part, you can combine those web parts in any possible way that exists. And because of that, it's really easy to make a mistake. So for example, doing some check that takes time because it calls to database in some place, oh, this is, you accidentally plugged this check at the beginning of your decision tree, so it's running for every possible path in your application and you didn't want to do that. And this is a huge problem, especially with new people to those two libraries, Swap and Giraffe, that it's kind of difficult to explain them how they need to combine those web parts so they create actually efficient applications and don't make mistakes. On the other hand, on the other part of the world, we have MVC pattern. MVC pattern is lovely, it has some model, some classes, it has view, it has viewer, some more classes and controller, classes, classes, classes. Don't get me wrong, like, oh, I mean, I'm a functional programming developer. When I see classes, I'm kind of like disgust, but MVC frameworks have really good parts and I really like some of the MVC frameworks, they're really good. It's high-level model, they handle a lot of stuff for you. Usually when you use some kind of ASP.NET MVC, Ruby on Rails, whatever other MVC framework, you kind of just, most of the time you spend writing your actual business code and not modeling your decision tree about web server and paths of the code. It provides structure, so if you want to add new view, you exactly know what to do, you click, generate new controller in Visual Studio and it will be on Rails, you run something from the command line. And because it provides structure and everything is like maybe convention-based, maybe, but even if it's not really convention-based, there is still some structured way of building your application. It's really easy to build tooling about that. I have also like, I talk about web programming in fShop, but also I care a lot about building developer tooling and this is like really important point for me. But MVC frameworks have their problems. If there were problem less, I wouldn't stand here and talk some silly stuff. So my main problem with MVC framework is that it's usually really difficult to fall back to lower level. If the magic fails, if the magic of the framework fails, it's really hard to do something with that. So in ASP.NET, it's like over, like implementing some interfaces that only ASP.NET team understands and stuff like that. Too much magic, so magic is good. Well, maybe otherwise. Handling stuff for the users is good, but magic that's not extendable and not really easy to understand is bad. So stuff like attributes in ASP.NET MVC where you can only use reflection to get access to them under if you are building your framework or extension to the framework. This is bad. Conventions, they may be good, they may be bad, but if they are failing, something may go wrong. And of course, classes, yeah, you know. So the question is, can we do better? And I guess, yes, we can. So imagine this ideal world where we will follow some kind of functional programming principles with bit of pragmatism because like, I'm after developer, so I like pragmatic choice. I make pragmatic choices. So model is immutable model with F-sharp records, F-sharp discriminated unions and some set of pure functions that operates on this model or maybe not so pure because they can do logging and stuff. View is a function that takes model and returns some output, HTML, JSON, whatever. View actually in this idealistic model is kind of like if you were on my talk in the morning, I was talking about model view update pattern and then view in this model view update pattern look exactly like the view here. So it was a function that takes model and output stuff. And then controller is a function that takes set of handlers and puts them together into some kind of opinionated routing or something like that. And here I want to, okay. I've missed one thing. MVC framework serve one more problem really important. I mean ASP.NET MVC is great framework especially ASP.NET core, but it's kind of like built with C-sharp in mind and as a F-sharp developer, I'm not really fond of that. I mean it's usable from F-sharp but it's just not really idiomatic F-sharp experience. So Saturn. Saturn is a F-sharp web framework that we've created. It's built on top of Giraffe, one of those libraries I've mentioned before and that's really important point. As a result it's built on top of ASP.NET core, which means that you get all great performance fixes that are accessible thanks to ASP.NET core like Castrol is like crazily fast. And actually Giraffe and Saturn in benchmarks are faster than MVC, which means that, okay, that's fast enough for most applications. It integrates well with existing ecosystems. So of course ASP.NET MVC is not only stuff provided by Microsoft, it's also a huge set of third-party libraries, things like Google authentication as identity servers and all these things. It tries to provide tooling, for example scaffolding tooling, diagnostic tooling, debugging additional debugging tooling. This is mostly work in progress but as I've mentioned, I care about tooling a lot. So yes, that's definitely something we focus on. It provides sets of high-level abstractions that I will present in a moment but at the same time, it really easily allows you to fall back to this lower level of just putting web parts together because the interesting fact about those higher-level abstractions is that they are not really abstraction in understanding of some class or whatever above. Those higher-level building blocks that I will show in a moment actually all compiles down or transforms down to the same web part abstraction that I was talking before. So that's really, really good and I will explain that in a moment. So first of all, Saturn, as I've mentioned, has access to normal to the rest of the ecosystem, especially it has access to all features that Giraffe provides and Giraffe provides a really huge set of HTTP handlers, web parts that can do different things. For example, write the JSON and things like that. This is, again, not going into details. We don't have time for details but that's just like overview. So yes, this access to the all stuff. Secondly, there is first abstraction that I've created. It's called Pipeline and another point, every abstraction I will introduce here in a moment is using a feature of F-Sharp called Computation Expression. Computation expressions originally were used for modeling a thing await in F-Sharp in a bit different way than async await is modeled in C-Sharp or in TypeScript but there are like way more than just that. Basically, computation expressions and computation expression is this name and those curly braces and the code between. So computation expressions change a way this code between is executed in F-Sharp which is a bit, whoa, that was difficult to see. What's really important about that is they allow you not only to create stuff like async await or promises in JavaScript but they also basically using couple of tricks let us to create really nice custom domain specific language inside our language inside F-Sharp. So here, all this stuff that's like first parts of set header, set header, plug. Those are custom keywords of the language that are available only in context of this computation expression. Basically you can treat them as a custom functions. What this, what my computation expression do is they execute keyword after keyword with parameters that were passed to it and then they build some internal state of this operation and then they transform it down to the web part HTTP handler that I've mentioned before. So additionally to the stuff that Giraffe provides out of the box we also provide really huge set of those custom keywords like set header, set cookie content and like oh, oh, like there was just like 60 or 70 helper functions, whatever. The second part is the second abstraction that we've introduced is router abstraction and router as name suggests it's taking care of the routing of your application. Here the important part is that in Giraffe in this decision tree sample I've shown briefly the thing that's happening here so those like my pipelines and the routing was mixed. Here in Saturn we decided to split those two things into two separate abstractions because I believe that those are two separate things to take care and not necessarily mix them together randomly. So I guess that's the simplest abstraction is just oh, there are those custom keywords for get, post, put, so on, so on, so on. They take path or path with format with parameter and then they execute some kind of web handler and of course the nice thing is that everything is composable so I can have second router that's using my API router and some browser router that's not here but you can imagine that it looks similarly. And again this is compiled down to the web handler so you can imagine that you have some router and then you use it here in this abstraction if you really need to but it's not defined in one place but if you need to have this composition you can do that but you don't define all those different things in one place. And the third thing, third abstraction is highly opinionated abstraction, controller abstraction that's used for creating rest-ish kind of controllers so index action goes to the get request for the slash and should return the list of all elements. Show action goes to slash ID and it's get request and it should display the single element. It's kind of following this like rest convention so there is whole set of those index at show edit and other functions that you can implement. What it does, it's under the hood, automatically creates all the routing for you so it enables you to just start writing code really often especially for boring line of business applications we just create rest endpoints. That's what ASP.net MVC tooling is about with scaffolding controllers that what Ruby on Rails tooling is about about scaffolding controllers and here we have just some small abstraction that takes away from you any decisions that you make about routing, you just do the stuff. It also have some advanced features especially something called subcontrollers so putting two controllers together because you can imagine in normal rest case you have first controller that returns block posts and so if you want to go to particular block post it's blocks slash ID one and then on the slash comments you can have comments for this particular post. This is again following normal, normal typical rest is convention. Second thing is the automatic versioning that's built-in in framework so versioning is really hard thing to do. Troy Hunt has written really good article about versioning of your HTTP endpoints where he says that oh there are three possible options and all three sucks. So yeah, versioning is hard. This is using for versioning special header field in request header and it's checking whether this field is equals one. It has something called plugs which allows you to plug particular action for some subset of the actions and this is trying to reply stuff that in ASP.NET MVC you get from attributes. So for example when you have ASP.NET MVC controller and you want to have authentication only on some actions from this controller you put some magical attribute and this is basically trying to achieve similar mechanism but more general without magic of the attributes. And there are a couple of more controller features. So yes, it basically generate optionated routing in REST-ish style. It has not found and error handlers so not found is executed when path is not found and error handlers handler is executed when the action your implementation throws unhandled exception. So this is a way to kind of add general exception handler for your controller if you haven't handled exception correctly in your action. It has subcontroller as I mentioned plugs. It has automatic conversions of data. So here you see that I use something called controller.text and this is returning normal text and it sets the content correctly and things like that. But you also with automatic conversions you can just return this part of text and it automatically will recognize that this is string. So probably you wanted to return this as a content text. If you return object, C-sharp class or F-sharp record it will automatically try to serialize that to JSON or XML basing on the accept header of the request. It supports versioning and it automatically supports dependency injection that actually is working progress so I'm not going to show that. And the last abstraction is application and with application is different because it doesn't compile to web part. It's not really connected to this programming model that I've shown. What I try to do with application is to replace all the like imperative configuration of ASP.NET MVC. If you've ever configured ASP.NET MVC core application then you know you need to register services, you need to do something, some magic that I don't really understand. And because I don't really understand I've written a framework that replies that stuff. So the application computation expression application abstraction attempts to replace all this imperative configuration with just feature of flux. Basically with feature of flux saying oh I want to use zip compression. So I just use this zip compression and this is enabled on my application. And then you run application with just one line of code. What's going to come to Saturn? First of all, I want to investigate and there is actually pull request with work in progress version of that. Sock channels which will be like real-time web socket subtraction for real-time communication. I want to add some utilities for testing and for diagnostics and I will, as always, focus on tooling. And I need to mention one more thing. It's called SafeStack. SafeStack is about building full end-to-end F-sharp web applications. So using F-sharp both on the back end and on the front end. On the front end with Fable that I've presented in the morning on the back end with Saturn or with Giraffe depending on what you want to use. The acronym comes from Saturn Azure Fable Elmish. Yeah, but you can replace basically and maybe first two parts are really easy to being replaceable. It focus on types of communication. So for example, you define that your server returns integer and you automatically gets client in the Fable generated. Oh, this is the endpoint indeed. It returns integer. It focuses a lot on developer experience so additional tooling.net new templates, documentation and this initiative also was originally created by the couple of consulting companies doing F-sharp. We provide also commercial support which I think is really important factor in choosing the technology for use in your business project. Those are the links to the SafeStack and to the Saturn framework. And yes, that would be all. Ask me anything, any questions? Do we have time for questions? We don't probably. So my name was Chris. You can find me in all those weird places and thank you.