 Good afternoon, everyone. Welcome to the last talk of this excellent conference. And I hope you all had a very good experience in the conference, and you learned a lot of great things about functional programming. So let's start at myself, Tamil Vengan. I work with a startup called Ajira as a lead consultant. So I would like to begin this talk by referring one of the great feet around functional programming by Michael Puthers. He says, in object-oriented programming, we encapsulate this mutating state. That's what he's mentioning as encapsulating moving pulse. Whereas in functional programming, what we do, we minimize state mutation. And this pretty much summarizes the talk I'm going to give. So we are going to see how the state management that we typically do in our application has an impact on our architecture. So when we think of state, we always think in terms of storing the state in database and getting the state from the database. Is there any other alternative perspective? Instead of mutating the state again and again in the database, can we see that from a different perspective and come out with a different paradigm? That's what we are going to explore in this talk. So throughout this example talk, I'm going to give you a walkthrough of an implementation which is going to close to real-world. It's a minimalistic web application which has the typical state management architecture that we do in a real-world application. So this app actually called fsharp cafe app. Let me show. So fsharp cafe app, as the name indicates, has been implemented using fsharp. So this cafe app is a service which is running on a cafe which helps you to operations of a particular cafe in a much better way. So as a visitor visits a cafe, he's going to select the table which is available. So let us assume that I'm taking the table one. So now I visited that cafe and took the first table. Now it is actually waiting for the order. And then the table, now the waiter comes to the table and takes the order. I'm ordering a salad and a pizza and a cook. I place the order. So if I go back to the home like the table says it is in service, that means the order has been taken. It is actually in service mode. As in a typical cafe, the food that you ordered has to be prepared first before it has to be served. So under chef, you can find all the food items that the chef has to prepare. And the waiter will be having a list of items that he has to serve. So the waiter now served the cook. So it is no longer available. By the time the chef has prepared salad as well as pizza, so he's marking as prepared. Now these two items are available for servicing. So the waiter's servicing the pizza as well as the salad. Now after some time, the visitor completed everything. So now he comes to the cashier. Where the cashier see the total amount is based on the amount of food that he had. And after the amount got paid, he just marked as paid. So you see that the table is again available. So this is the workflow that we are going to see throughout this talk. And before we see how this can be designed from a functional programming perspective, let's see how we design in the typical normal imperative data modeling. For the simplicity, I'm picking a no SQL store here. It can be any database back end. So for this particular view alone, like the table goes through different transitions. And for each transition, what we'll be having typically in the back end database, we will be having something called a document called table. And it will be having an ID as well as the status associated. Whenever the user performs some action, we go and change the status. This is how we typically develop the application. Well, there is nothing wrong with that design. And that's how we develop a lot of systems. But what I'm going to propose here is an alternative. So in order to come out with an alternative, we need to see the same problem with a different pair of files. What I say is a different perspective altogether. Let me introduce a new variable into our application called time, which we often forget when we are designing the application. So at the instant, say T0, the state of the application is idle. So after some time, say T1, when the visitor has opened the particular table by clicking that button, the system receives a command called open tab. And after some time, the system receives another command called place order. That means the order has been collected from the user. Likewise, on different instance of time, the system is receiving different commands from the user. And accordingly, at different instance of time, we are mutating the back end value. This summarizes that the state that we are persisting in a database is actually transient in nature. But we are actually hiding this concept when we are designing the database. For example, say you are defining a profile table, a name, and his company. And obviously, we switch companies. So for example, say you moved from company x to company y. Initially, the table will have company as x. After you move, the company will be, say, y. But this particular information, after some time, if I come and ask you, what are all your past employees, the database that we designed cannot answer that question. Because the x is no longer there. Because that's been mutated with y. So instead of mutating the value, let's embrace this concept that state is transient in nature. So let's use a term called tab, which tracks the user workflow in the cafe. So initially, the system is in the state called closed tab. After receiving the command open tab, it moves to the next state called opened tab. And there it receives another command called place order. It is order has been placed. It moves to the next state, where the order has been placed. It's a placed order state. There it receives commands like serve drink. Means the food he has, the drink he has ordered, has been served. So he's receiving a command called serve drink. And in case if the order contain food, it will be prepared. So during that state, the system can receive prepare food command also. Likewise, once the drink has been served, there are a few more items to serve. That means the state of the current system is the order is in progress. And when the order is in progress, the subsequent food and drinks will be served or prepared. And finally, once everything is done, the state will be served order state. And there, after it receives the closed tab, which means the amount has been paid and the cash has collected the quote, it again moves back to the initial state called closed tab. So this is what we typically call it as state transition diagram. This is something like a more decorated state transition diagram. But it is exactly what we do in a state transition diagram. So there is nothing fancy out here. But if we generalize this particular state transition, what we get is state x upon receiving a command, it moves to state y. That gives nothing but a function. Let's define this function as evolve. Evolve is a function that takes a state under command and moves to a new state. Command is something which is coming from the user. But where does this state coming from? Typically, we will be fetching the state from the database before calling this function. But what we are going to do here is we are going to derive from where this state is coming from. That's what like a mathematical theorem, we are going to find out what is state. So to derive state, we need another data. Say we start with the initial state. And after receiving some command, it moves to a different state. In a typical way of doing this transition, the outside world, we will be mutating the state. But here, what I'm telling is don't mutate the state. Then if you are not mutating the state, how does the outside world know that this particular thing has happened in the system? Yes. That's where we are going to introduce a new term called events. Events are nothing but there is the fact that happened on the system. So when this particular transition happens, the system is going to emit an event called the tab has been opened. So let's model this as a function. So we have a function called execute. It takes a state and a command. And it comes out with the list of events associated with the state transition. Say here, what we are seeing is initially the state of the system is in closed tab. Upon receiving command, it has moved to open tab. That means the tab has been opened in the system. So we are just emitting that event. So if we apply the same events on all the state transitions, we will be getting different events. Say for example, when an order has been placed, we will emit an event called order placed. This event has all its associated data with itself. Say for example, if the order has been placed, it will contain all the data, something like what are all the food items has been ordered, what are all the drinks has been ordered, to which table this particular order belongs to. All this associated information of an event is being there inside the event. So now we have the events of the entire system. Can we dare use something out of it? Events, as I said earlier, events are nothing but facts that happened on the system. So let's embrace it and introduce a new function called apply. To give an analogy, let's take an example of your bank account. Let's assume that you are having, say, $1,000 in your bank account. And you are getting an event, say, as an SMS. $50 got credited. Then what will be your balance right now? $1,050? You are actually, what you are doing is you are coming out with a new state. The earlier state, it is $1,000. Now you received an event, say, it is credit, and $50. Then what you do? You translate that fact into credit means plus. So you are adding that plus into that $50. So you are coming out with a new state called $150. In case if it is an SMS for debit, the new state will be $950. So this is what we are going to do here. We are going to take a state and an event. We are going to apply the event to the state. And obviously, we will be coming out with a new state. Fine. Now we know two things. The outside world can know about the state transition by means of events. So instead of saving the state, what we are going to do, we are going to save the events. So we are going to save the events in the order it actually emitted from the system. It's an append only data store, much like you can think of a transaction life happening in your system. So we started with the initial state. We know the initial state is the closed tab. And now we have the list of events happened in the system. And we have a function called apply, which takes a state and the event will come out with a new state. Now what we are going to do? We are going to take these two things. And we are going to fold it in such a way that we are going to arrive at what will be the last state after the tab closed event, which is the last event of the event log. So I'm going to use the same apply function for the first input closed tab. I'm going to apply the first event. And I'm coming out with the new state. Likewise, I'm going to fetch sequentially all the events. Going to apply the next state. It's something like the output of this one is the input of this one. Likewise, it's like we are applying the fold operations here, and we arrive at the final state. And we can summarize this as the operation called compute state. A function is a compute state, takes the initial state, which we know it is closed, and the past event, which we can fetch from the database. And we can apply the fold operation. What we will be getting is the state that we want. This is what we wanted. So we started with this. And now we have these three functions, which we derived. So with these three functions in place, we can rewrite the evolve function, which we were asked. We got the command from the user, but the state that we need to compute from somewhere else. That we are already having a set of functions which will replace the state, which is as a set of past events. So what we are going to do here, instead of state, we are going to use past events, which anyhow we will be getting that from the data store. So we are going to get the past events and going to call the compute state function, where we will be getting a new state. And we will be executing the incoming command against this state with the execute function. As an output, we will be getting a list of again another event. So far, we are not mutating any state at all. Everything, like this is a pure function, this is a pure function, this is a pure function. Every function has been operating on the input. That's what the tweet mentioned. Like we are functional programming, minimize the moving path here. We minimalized all the moving path here. So we started with this, and we evolved to this one. This is actually called event source, coined by Greg Young, where the current state is nothing but the fold of past events happening in the system. This is called event source. That's fine. Now we have the evolve function. But in order to make it really useful, we need to expose this as an API. So in order to expose this as an API, the command is coming from the user. In order to fetch the existing events, we need to have some database access. So let me define two more functions. Get table ID, it takes a command, and from the command, it takes the table ID. And getPostEvents is a impure function. I'm going to call that function by giving the table ID. It is going to fetch me, you know, the set of events happened on the given table. Sorry, very fast. Now I'm going to define a new function called handleCommand that takes a command and get the table ID from the command. And the pipeline is just a unique pipeline. I'm going to pass that to this getPostEvents function. Now I will be having all the events, postEvents, then I call the evolve function with the postEvents on the command. To make it simple, I'm not, you know, talking about error handling here. I will be touching upon in the later slides. Cool. Now we have handleCommand function. To expose this as an API, again, you're going to create another function. That function is going to take an HTTP request and return a HTTP response. So we are going to get the command from the HTTP request by doing some JSON deserialization. And we are going to get the command. Once we got the command, we're going to call the handleCommand method, sorry, function, and we will be getting a new event. And we will be saving the new event and then return okay response. Now we started with some function and we are, we molded it by, you know, refactoring the state with the postEvents. Now we reached a point where it has been exposed as a API. So far, we are seeing the one side of the coin. That means the command sides of an application. There is another side of an application. What is it? Exactly, queries. So in order to view all this information in the UI, we need something called queries. In other ways, we call it as reads. Commands are treating the rights of an operation. Reads, queries are nothing but the reads of the system. Before going to see from the functional perspective, let's see how we do this in a imperative data modeling. Again, I'm going back to the same document example that I had. So we mutate this particular state whenever any command is being received by the application. And we fetch the state when there is any queries. Let's apply the single responsibility principle here. Let's separate command and queries. Before separation, let's see, you know, what are all the problems that we had when we model a single data model for both write as well as read. Say for example, if we denormalize, we all know read will be much efficient. When we denormalize, write will be slow. And again, there is something called impedance mismatch. We may need, say, only two, but we store four because the command requires four. So likewise, because of your constraining to use a single model for both read and write, we make a lot of compromise. By separating these two out, our architecture is scalable. We are going to see in the next slide how it is scalable. And before I going on just this particular concept it's called command query responsibility separation. We call it a CQRS, okay? This is often going hand-in-hand with event sourcing, but it is a separate concept altogether. So what is the benefit that we are getting out of this by separating commands and queries? We saw an example like where whenever there is any state transition happened, events are getting emitted. So what we're gonna do, we're going to publish this event to a message queue. Okay, let it be rabbit MQ or zero queue or Kafka, N-Service, whatever message queue we are talking about, okay? So you are just publishing that event to the message queue. Now, we are going to listen to the message queue by a client called read model projection client. This particular component is only responsibility is, it's going to listen to the events and populate its own data store. And from this data store, we are going to create an API server and we'll be serving the data to the user. This is the first thing that we will be doing. In the beforehand, we will be doing a single thing like both write and read on a single data store. Now we totally decoupled the pieces. There is nothing fancy here, it's all the same problem. But the most beautiful thing about this kind way of design is let's say that you have rolled out this particular version. Now the client is happy and the software is doing very well and all of a sudden, the client is coming back to you and asking, hey, every now and then I'm pulling the data to see the results. Why don't you push the results in a real time? What do you need to do? Very simple, just write on another client. Let me call it as web socket client, which will again listen to the message queue and publish the result and push the results to the UI. Cool. And it goes, now the client is happy and you are also happy, the system is going live. After some time, the computation has increased. So what you need is some sort of analytics, some sort of data science into it so that you can call the brand new application or something like that. So you need to introduce data science into it. All you need to do is just listen and write on another client, which will listen again to the events and it is going to populate its own database. Say for example, the database that you are using for your real application may not be a good fit for the data science or data analytics that you want to run. Say for example, you want to use Cassandra or maybe even some other system, all you need is just use those database which will be relevant to the particular task and populate that as simple as that. Once you populate that, let the data scientist rock as simple as that. And again, if there is the latest bus word called IOT, everything needs IOT on the place. So what we can do even if you want to introduce IOT here, all you need another client, which will listen to the event whenever any high-calorie food got ordered, they will send a notification. So it will smart watch, will get a notification that you are ordering a high-calorie food as simple as that. So this is the scalability that we are getting out of here. And the way that we can scale is totally depends on the business requirements. That is most, most important thing here. There is another important aspect in this way of designing things is the data is unidirectional. Have you seen that? There is no criss-craft, and no tangling of data flow here. Everything is uniform, like whenever you are going to push something, you're going to click something here and it is going directly to the comment side of the application. And again, it means no sequential. And this particular way of thinking has influenced Redex Flex, we call it as unidirectional data flow. It is the concept which derives out of this kind of design. Cool. So how the read model projection work? Now we got refuted even. There it is again similar to the imperative stuff. Like there will be a similar document, but instead of receiving a command, we are receiving an event and populating the field which are relevant to this one. Let me introduce error handling. So in an object-oriented way, like whenever we introduce error handling, our code will get tangled, like full of tri-cans, chiefs, all the things will come into the picture and makes our job very harder. But in functional way of thinking, all we need is a type. That's why yesterday, Debashisha had a good talk around no modeling things using algebraic data types. That's what here, like we are going to come out with a new type called result, which is a nothing but a choice type. Whenever you do any operation, it's going to be either a success or it's going to be an error. In case of success, you will get the result of the outcome, the operation of the outcome. In case of error, you are going to contain what is the error details. That is what this T and E is all about. They're nothing but genetics. So let me introduce the error handling to the existing function. Let me take one use case, because I cannot go through all the error cases here. So I just take one example. It can be easily extended to the other side. The command open tab should applicable only when the state is in closed tab. If the state is in different state, like maybe the order is in progress or it is being served in different state. That means this command is irrelevant. That means there is a, we need to handle it in our case. So what we do, I'm just doing a pattern matching here. If the command is open tab and the state is closed tab, it is a success. If it is not, this is a wild character which match all other state and it says the tab has been already opened. So the change here is earlier we were returning event list. Now it is a result of event list or a string. It means it can be either success or a error. In case of error, it will be having an error message. We can extend this same concept in other functions, like evolve functions instead of returning an event result, it will be returning a result of event list and return result of string. So now we have come to the end where we are exposing this as an API, right? So there it is very simple. We are going to do a pattern matching. We are going to call the handle command function. If it returns success, we are going to say return okay response and save all the events. In case of error, we are going to return a bad request with a message. You see here we are applying the functional thing throughout the end. The only impurity is happening in the database side as well as the fetching side. So we can likewise, we can extend like other functionalities like fetching events may fail. You can model the same way. So we can model the same thing in other functionality like fetching events may fail, serving events may fail. And there was a very interesting blog article called Railway Oriented Programming. You can find that in fsharp for fundandprofit.com which it talks more in detail about error handling. Often I get this question when I talk about event sourcing. The concept that I'm demonstrating here is the real system that I built in one of my projects. So often people come to me and ask this question like, see everything is fine, but in order to compute state, I need to go and fetch all the events and it may cause the performance issue. The answer is yes and no. It depends on how you design your, what is the root of your event, what is the common aggregate you are using to generate the event. See if you design it correctly, typically you will be getting some five to 12, or in the range of 10s, 20s, something like that. But in case if you still had problems, like in the model, the domain that you are working on cannot coming out with a better design and you need to store all the events, there is a concept called Snapshots. Snapshots is kind of similar to Git tree base. You can go back and squash all the history and you can start from somewhere else. Let's assume with the bank analogy that I told you earlier. Say assume that tomorrow you are getting a mail from a particular bank that says that like we will be giving only past six months statements. If you are asking for before past six months, there is no answer from our end. So in that case, the typical back end of the bank application will be, they will be maintaining only six months transaction data. Like if you ask for more than that, like they will be having a initial balance in the before sixth month. Say for example, at the end of sixth month, your account balance is $100. From here on, your initial state is $100, not $0. So likewise you can create Snapshots that again applicable to the business context that you are working on. You can create Snapshots so that you do not need to fetch all the events to recreate the state. And this particular solution is not, by designing this way, by any chance, like it does not going to solve your concurrency issues. The concurrency issue is still here. That means say for example, at any point of time, you can receive two different events at the same instance of time. So how do you, you know, prioritize which event to process and which to leave? That's where you're going back to the again, the traditional technique of row version in optimistic locking. So typically whenever the update any row, we update the row version. So likewise we can do by all the events we can put version to it. That will be incremental nature so that if you receive an odd, you know, even which is not in the order, we just ignore it saying that the data has been updated. This event is no longer relevant to the system. When, okay, everything is cool. Now you are all set to use this in your real-time applications. But you need to consider certain things before going ahead with this particular design. This is not a silver bullet. Okay, it solves a set of problems which is associated with wherever you need tracking of what are the events happened in the system, transactions, and all those security aspects. It is a very good solution. But if you are working on a cred-based application, this is an overkill. You don't need to get user change the password, you know, user edited his email. Those information and all, if those events are relevant to the problem that you are working on, you can use this event sourcing. But in case, if those things, you are not that all going to use, better go ahead with the traditional cred-based design that we are having, okay? And the most important thing is this CQRS and event sourcing are not top-level architecture. So designing an entire system based on this way of thing is the anti-pattern. So you need to think of a slice in your entire problem domain. And for that particular slice, use this particular way of design. And finally, the last part of the talk is around F-sharp, because we implemented this everything in the F-sharp. So let's showcase some sort of F-sharp code, which I personally love. Before I get started with the out-scale F-sharp, I just want to quote some of the testimonials around F-sharp, okay? A lot of thought works are yes, sir. I just picked these thought works from the credit 2012. They mentioned that F-sharp is very great in expressing the business and domain logic. You are going to see the code and you will find that out. And one of the most interesting testimonials is this one. I have just delivered three business critical projects in F-sharp, I'm still waiting for the first bus. It's the same case for myself. The application that I wrote, it's in production for the last seven months. I'm also waiting for the first production bus. And another good testimonial is jet.com, which is an e-commerce startup in US. Recently it got acquired by Walmart for $3 billion. Their entire tech stack is around F-sharp. So it's in production. You can find a lot of testimonials in the website. Okay, let me show some of the awesomeness of F-sharp. The first awesomeness is I'm not using Visual Studio. I'm using something called Visual Studio code. But again, I can use Autom Editor, but that's not different. The difference is there is an extension called Ionite, which driven by the F-sharp community that provide all intelligence, typical ID that required for developing your application. So let me start with the domain. So I'm just defining something called tab, which models the state, item, food, drink, all two liners, three liners. There is no public class, getters, et cetera. All those noise is not there. I'm just defining the domain here. And once I define the domain, if you see here, you are getting something called, I'm not, these things, the signature of a function is actually coming from the Ionite plugin that I talked about, which is one of the cool thing that come into the F-sharp community in recent days. You know, you just define a function, the signature will automatically pop as a code length feature. So you can say, in a typical functional programming, whenever we do any sort of application, we are more interested in the signature of a function that is being there. So I defined all the things. Let me show the events. We told different events, right? All the events can be modeled using something called discriminated union. Again, it's a choice data type. An event can be either tab open, order placed, drink served, whatever we saw in that diagram has been equivalent in the code, which is very, very shorter lines. And the equivalent commands is in the present tense. The command, if it is an open tab, in the event, it will be tab open. If it is a place order command, event is order placed. This present tense, past tense, spare will be there. Cool. And let me show you another awesomeness where F-sharp is really shining. Okay. Let me take this behavior. When you serve a food, it has to undergo this kind of validation, like the food that you are serving has to be part of the order in the first place. Then it should be prepared. Otherwise, you cannot serve the food. And you should not serve the food again. And the final thing is sometimes, if that is the last item, that means the order has been closed. So if you model all these things in the same way that we do a typical object, we end up with this kind of nested effects. So how can we resolve this? This is very bad code, right? So nobody wants to write this kind of code or nobody wants to read or work in this kind of code. So how can we refactor this particular thing from a functional perspective? In the morning talk, we had the clue. Write a function. Write a function that models this if condition. How can you write a function? So what I did, I created a set of functions. This is, those fancy brackets, and I'll just leave that, that is part of the syntax in F-sharp. So what I did, I created functions which do only one thing. If it is a non-ordered, just do check the first function, non-ordered food, we'll check whether the food is ordered or not. Likewise, unprepared food, served food completes, are you order, already served food, all the things, I write it as a separate, separate function. Now anybody can check this validity of this function. Now what I need to do, I can just use the pattern matching out here. See, if the food is non-ordered food, throw an error. Say I cannot serve the non-ordered food. If the food is already served food, cannot serve the already served food. See, the code is very, very, very readable. There is no e-spells. And the beauty of here is anybody can, even the business analyst can read this code and say, hey, you are missing this case. And even if you are missing some case, you will get, no, no, okay, what will happen when this particular state happens? So you are getting more intuitiveness to the domain that you are working on, which is very, very powerful. That's why TechRadar, ThoughtWorker has mentioned that F-sharp is very good at expressing the business domain. So, we got 10 more minutes, so I can show a little more awesomeness. In the morning talk, who were there in Ankit's F-sharp in production? Okay, cool. So he talks about type providers, how it helped in solving the clear text problem. And that type providers is a generic concept. We can take it and applicably, not only when we are fetching the data, we can apply it in other scenarios also. One of the scenarios is, what I find it very helpful for me is, so the commands, right, whatever we have saw in that slide, it's nothing but the JSON request coming from the user. So this is the command, JSON request coming from the user to close the tab, where he is mentioning what is the tab ID and what is the amount. This is the JSON format that you are expecting from the frontend. And what I do, I just do a, again, I'm using a type address. I'm just parsing this payload and I'm converting that to a equivalent type, which will contain tab ID and amount. The beauty of this type providers is, let us assume that you are coming out with a new schema for your JSON. Say instead of amount, you are putting something called price. See, I'm getting a compiler error. There is no price. So if I rename that to price and you can see that I'm getting the intelligence also. Even if I change the price to amount, again, I will get a compiler error. Change that to amount. This is a concept called type providers, which is there in Yafshap. And Yafshap has a lot of cool libraries and one of the libraries, my personal favorite is a library called Swap. Yep, yep, yes, yes, yes, yes. Cool. So the library that I mentioned is Swap, which will help you to do web applications in Yafshap. So the beauty of Swap is the way, the API it provides to develop a web application. I show you a HTTP endpoint, which deals with the queries. If you see, everything is readable. Like if it is a get request, I'm going to choose all this get request, slash table, slash table, to dos dot chef, to dos dot writer. And this pipeline is the monodic operator that we don't want to get into that. So basically what we are getting is a lightweight without no ceremonies. There is no controller though it's known. There is nothing like we just create a function. The first function matches this particular path. If this function matches, then this particular handler is getting called. So without putting a lot of mental load to your brain, you just simply write by following the synthetic sugar, which has been offered by the language as well as by the library. And the next another library, which is available in Yafshap is, so how many of you love the new Yon coming into the JavaScript world? The alternative for NPM. Have you Yon, another package managed? Yeah, Facebook will combination. What Yon does to NPM is what exactly packet has done to new gate. Yeah, it's on top of this, but it's going to solve certain problems like dependency management, all those things. Exactly, that's the same thing pocket is also doing. Packet is already.net environment has a package manager called a new gate. So instead of replacing that packet, adding what Yon adding it to NPM, it just make it very simpler so that like these are my entire dependencies. My entire application, of my entire application. And if I want to know what is, say for example, I'm using a library project called persistence. What is the dependency of this particular library? I can just go and do pocket references and then I find any event store is the only dependency. I can query the same thing in my command prompt also. So whenever I want to do what are my dependencies and all these things, this packet manager, no saves the day. And another awesome thing around FShop is a build library called fake. It's very similar to rake, in rake make, it's fake in FShop, okay? So you can write your build script in FShop. Since FShop and CShop can interrupt together for your existing CShop projects, you can use FShop and write the build script. So that's much easier and I am like, is anybody here worked on MS build XML files? Okay, I don't know going to give you any comments, just see what I did here. This is cleaning, I'm just mentioning, this clean this directive, build up, build these projects under release mode and output the log to this particular place, build the test, run the test, and I can integrate with my NPM local task. I'm just creating a new target called client where I'm calling NPM to do the NPM install NPM build and all I need to do to define the order, I just need to use this DSL. This is my build order and I can mention what is that run target or default. It is, if I didn't specify any target when I running this script, it will take client by default or I can specify all the scripts out here. So writing a build script in a language which is type save all the, now you can do a function in your build script. That's the beauty of this particular library. And a lot of people talking about containers, dockers, and all those things. With the help of mono, you can, this is a Docker file where I'm using mono to run this F sharp application. You can put that into a container and you can scale horizontally or vertically whatever you want to do. Or like recently Microsoft came out with dotnet code. So if this particular project can be ported to dotnet code also, again it will be run inside a Docker container. So, and this cyanide plug-in initial studio code. I just want to say, a lot of people have a feeling that it is another Microsoft product. All the things commercial and all those things will do. Is it a open source? In the morning I had a discussion with one of the person over here. I was talking about, when you say Xerox, now everybody talking about taking a printout or taking the photocopy. The word photocopy has been totally, you know, overshadowed by the word Xerox. But Xerox is not the actual photocopier. Like it's just a, you know, company which come out with the concept very first time. But now the concept itself has been rebranded as the company name. Likewise, everybody has their own assumptions around the Microsoft server and all these things. But let me clear out one thing, that F-sharp is being totally driven by the community. And if you don't like something in F-sharp, F-sharp compiler code out there in GitHub, go change it, write a pull request. If it really making sense, it will get updated at no time. That's the guarantee that I can give. Because recently, Elm has a very good support for compiler errors. You can get a lot of good quality compiler errors. One person in F-sharp community saw this particular thing which we find it really useful. But compared with F-sharp compiler, it was showing some bad error messages. What he did is just created a pull request. Now in the latest F-sharp version, the compiler is more like beautiful and elegant in the way that Elm shows the error. So it's been totally driven by the community. So if you're thinking of trying out a functional programming language, F-sharp is one of the best out there in the market. I won't say that it is the language, it is one of the best. And from my perspective, I have been working with F-sharp for almost four years now. Personally, I get the same productivity which when I work with Python. And the type safety from Haskell has been inherited. It is again, F-sharp is from ML family. So 80% of the type play that we do with Haskell and you can apply that in Haskell also. Sorry, in F-sharp also. And it's fun to play with F-sharp. So that's it about F-sharp. I just, the last slide of my presentation is this. I have written a book called F-sharp applied which is to demystify the concept around functional programming. A lot of people think functional programming is around academic stuff. We cannot do something to a full-fledged solution. There is a lot of misconceptions there in the market. So I wrote this and self-published this book recently. And this particular book where I talked about, it's a practical guide of doing web development in F-sharp. And I use the library which I mentioned in the slides, like Suav. And the completes, the code that I've shared here is available in my GitHub repo. And if you like F-sharp, the community is available there in F-sharp.org, you can go and check out all the great things happening in the F-sharp ecosystem and you can be a member and start contributing to the F-sharp site. Okay, that's it. Thank you. Yeah, sure. So I'm going to start off using the Snapshot approach. Can you just tell a few cases where you think, like you talked about scaling it, right? And making it distributed. So can you just elaborate on that, how it will come? Snapshot is something like, typically, when you do a rebase in GitHub. Okay, fine. Basically, sorry, Snapshot is, you just go ahead with the first initial implementation. You don't need to apply Snapshot in the very first place. Like, otherwise, it will be called as premature optimization. We don't want to get into that. So let's start with the first thing. When you feel that this particular fetching, the events are growing like anything, you need to ask yourself two questions. Whether the aggregate of the event, like under which category all these events are coming in. Is it modeled correctly? If that is modeled correctly, you won't get set of events. Say, for example, if you are modeling an account, so all the transaction will be a log under this thing. One way of creating a Snapshot will be, you can create a Snapshot per month. And say, account slash colon, account ID colon, this month, this year. So you can do optimization at this level, and you can create Snapshots. And whenever you want, when you are creating a Snapshot, when you are fetching the events, you need to check whether the Snapshot is available or not. If it is available, you need to do fetch that and do the changes out here. So there are two databases right now in the market which get us the event sourcing. One is EventStore, which is an open source as well as commercial support is available. And then there is another database called Datomic, which is also, the database itself is based on this event sourcing and CQRF. So we can leverage those two libraries. And in .NET, we have this library called N-EventStore, which is an abstraction on top of any database system. So by using this library, I can point to any database to get this event streaming on Snapshot and everything. This is similar to modifying state, like let's say we have one event, and we take a Snapshot and we overwrite it, and again we have one event, and again we overwrite it. So isn't it like modifying some state, like having a global variable and modifying the state? Is it similar, I mean, modifying state and taking a Snapshot? Okay. So there is something called, in the git where we use something called direct cyclic graph or something, bag, we say. So everything is an immutable thing. So likewise in the EventStore also, every event is immutable. Say for example, you just think of a set of lists. If you are creating a Snapshot, what you do, you compute everything and create and put that into a new place. And from your, when the new event comes, you will be starting from where you computed and aggregated and stored. Like you won't modify the existing events. Whatever you persisted as the events will be always be there as immutable. So you can always go back and transaction, do the apply the transaction and come back. So you are not mutating the state here. You are computing the new state and putting that into a new place. Swab. The web library is a swab. Okay. So you showed us where you refactored it into a maybe option type in F sharp. Sorry, I couldn't get it. You had an if, else condition, right? Ah, ah, ah. You refactored into the option type. Not an option type, as a function. I refactored that if as a function. Option type, option type, yeah. Is there anything like monad I heard there are computations, that could easily solve this? Yeah, we can write another computation expression to solve the same problem. Okay, monadic is another way of solving the same problem. Here, it's a very simple thing that I come up with. So one of the great thing about F sharp is they won't use any term of the functions, applicative and all those things. Yes, so, but like you can, this construct is solved one, like this is the same problem. This can be solved with computation expression also. But I didn't used here, but it can be solved in that way also. Basic objective is hide the ugly code, make it more readable and maintainable. I have just one point when you were talking about CQRS as caveats or some concerns you mentioned performance. Sorry? The CQRS as caveats or the consensual. Yeah, yeah, things to consider. Yeah, things to consider. I think one other thing also is the CQRS will always give eventual consistency. Yes. So that also is one thing to keep in mind. Correct. So what happens if your application updates, like if it's evolving, you have new events coming in, new types of actions happening, or some type of events are no longer valid? Okay, that's a very good question. That is the thing that we need to look for when we are deriving events. So when a new event comes, that means the new field is added to the event. For your past events will not contain this entry. And there is no migration, database migration, like what we do in events. So because everything is immutable, you cannot go back and change the history. So what we do, that's where your application code will become. That you need to handle that in your application. Say for example, in the bank analogy, like when you are doing third party transfer, earlier you are not tracking from whom the money is coming from. Thus, this is how the bank works so far. After some time they decided it is a security plot. So they added this event, say, all the third party transfer event should contain the other party. So in this case, now your domain, when you are processing an event, now you need to consider two things. The third party date, in the third, all the third party transaction, the sender may be there, they may not be there. You need to include this particular logic in your application code. Sorry? So if some specific feature or some event is no longer applicable, but you need to keep it around throughout the application history. Because it's... Yes, like there are N number of ways to solve this problem. One is what I mentioned, your application code. It's similar to what we do in versioning. Like we provide backward compatibility, add different versions. See, in an event also we can add versions to it. And probably if this version handles this kind of things. So it's the typical API versioning, database versioning, that's the same thing here. But only thing is, we won't do database migration, something like, we won't go back and change history. When it happened, it happened. If you are not capturing something, that's the design flaw. Here we don't need to do migration in the first place. Because everything is just a transaction log. You are just appending. Yeah, data mix has, all this concept has been embedded into the database itself. So it solved the problem in a way. Okay, it seems that there is a timeout, like I will be there out, so if you have any questions feel free to contact me and I'm very happy to help you. Thank you.