Video details

Implementing Event-Driven Microservices architecture in Functional lang - Nikhil Barthwal #FnConf 22

Microservices
04.06.2022
English

Web services are typically stateless entities, that need to operate at scale at large. Functional paradigm can be used to model these web services work and offer several benefits like scalability, productivity, and correctness. This talk describes how to implement Event-Driven Microservices in functional programming languages with examples in F#.
Immutability allows infinite scalability as it eliminates the need to worry about a mutex, a lock, or a race. As functional code is much more terse compared to object-oriented code, it provides productivity benefits. Its strict typing makes writing correct code easy as mismatches of types are caught at compile time.
The objective of the talk is to show how to create a scalable & highly distributed web service in F#, and demonstrate how various characteristics of functional paradigm captures the behavior of such services architecture very naturally.
More details: https://confengine.com/conferences/functional-conf-2022/proposal/16347
Conference Link: https://www.functionalconf.com

Transcript

Hello and warm welcome to everyone joining this session today. Now we have Nikhil with us to talk about implementing event driven microservices architecture and functional language. Thanks a lot, Nikhil, for making the time for us without any further detail. Over to you, Nikhil. All right, thanks a lot for the lovely introduction. Let me share my screen, please. Hi, everyone. So my talk is about implementing even driven microservices in a functional language. And the way I've structured this talk is that my code samples, et cetera, is kind of an F sharp. But generally the talk is very much general functional language. So if you're not from an Fsharp.net background still like probably 80, 90% of the material still will be relevant to you because I understand that not every people have different preferences for languages, right? Some are coming from Scala, coming from Haskell. So I've tried to make it as general as possible. And predominantly I have two objectives for this talk. So my first objective is that I want to explain why functional programming in general is a great paradigm for implementing event driven microservices. And I'll explain a little bit about microservices, a little bit about what I mean by vendor and micro services. And secondly, now that we understand why functional programming is a great paradigm, I want to actually go and how would we implement certain constructs using common programming language constructs that practically all functional programming languages have? So these are two objectives. But before I start there, I'll start with a little bit way back on monolithic, right? This is the old school approach that we had in the good old days. We have a simple web service connected to database. Multiple clients are connecting to it. Everything is very easy, easy to test, easy to deploy, et cetera. But it has its own challenges. So it's easy to develop and test. But it doesn't scale. And the reason why it doesn't scale is that when you have a large code base, the development gets slower, it takes more time to test, it takes more time to deploy. And there's a lot of team interdependencies, right. That you have only one services. And there are n number of teams that are working on this one service. So what team one does will affect team two? What team two does will affect team three? And if team one has to deploy, but team two is not ready, it has to wait. So in a large organization, these monolithic models don't really work. And that's the reason why we come back to micro service. So what are micro services? Basic stuff. Microservices are small autonomous services, right? So instead of having a system consist of one big service, you divide it into smaller set of services that communicate with each other using lightweight mechanism. Right. Typically rest API. So that's what a micro services is. Micro services is a big topic. I can't cover anything more because of lack of time, but I have some excellent resources on microservices. In fact, there are conferences delegated specifically to micro services, but that's the gist of it. There are several advantages to micro services. Independent releaseability, right? Each team owns one particular service, and they can release that service. They have full control about it. Also, it provides the better scaling properties. For example, let's say a certain part of your system is overloaded. You can scale up that services, but you don't really have to scale everything up. You can only selectively scale up the parts that are heavily in use as opposed to monolithic, because there is one service. When you scale, you scale everything, right? Or you scale down everything here, you can selectively scale. So a lot better efficient utilization of your resources. There's a technology heterogeneity, right? There are different services. Somebody can use Sala, somebody can use Java, somebody can use, I don't know, C Plus Plus, other people can use net. You don't really have to stick with one set of technologies because microservices communicate with each other using lightweight protocol. There's a lot of resilience built in. If one particular service fails, that service fails, but the rest of the services are still working, right, because failures happen at scale, whereas monolithic. If your service fails, that's it, you're done. If there is one exception in one part of the code, it will bring down the entire system. Whereas in microservices, you have one small exception in one service, at best, it actually brings down that particular service. And typically organizations have like hundreds, thousands of services also, ease of migration, right? If you want to migrate, and this is a very common and probably I'll say single most useful purpose for micro service, the technology stack gets rewritten. So let's say you want to migrate the services, you can just migrate them one by one as opposed to migrating all of them together. So that gives you less risk of migration. There's an interesting story about it that Facebook started programming its services in PHP, and then they realized that PHP doesn't scale, but they didn't have a micro services architecture. They had a monolithic. So if you have to now migrate to something more than PHP, you just can't because you're basically literally rewriting the entire PHP, which is not feasible. So their solution was little different. They kind of said, okay, fine, we can't really migrate off PHP, but let's just make PHP faster. And they came up with their own language called Hack and Hiphop virtual Machine, et cetera. But the point I'm making is, have they used micro service architecture? This problem wouldn't have happened in the first place. This is actually a very real problem. So coming back to functional programming from a functional programming point of view, what is a micro services or what is a service in general? Actually, when you think about a service mathematically, a service is a function, takes an input, gives you an output, right? And I'll cover this in details. But let's say if you're using pure functional programming languages, most of these functions don't have side effects, right? So you don't really have a state. And typically when you implement services, the general rule of thumb is that most of the services, it's always a good idea to implement them. Seo services for several reasons. They're easy to develop, easy to test, etc. Etc. But there will be services that would not basically be pure. They will have some attached database because you do have a persistence layer. So in these services, we don't really have side effects except logging. Logging, we don't really consider it as a side effect. So even if you have print statements, it's okay because logging does not alter your state. Services don't have States. So that's why logging as a side effect is okay. But I O in general is not. So that's the functional view of a micro services. That said, there are services that are somewhat non functional. They will have attached databases, right? You will have services with database. So you can think of database as a state. There what you have is you have an input and you have an output. So a service would manipulate that state. So it's a function that takes the input and takes the state. Okay. And then gives you an output and alters a new state. So that's the nonmpro service, which is usually the minority, all the side effects IO, etc. For writing to database, with the exception of logging, will fall in this category. So that's the kind of functional view. And what we try to do is when we have these bunch of services, typically organizations have hundreds, sometimes thousands of services. I know Uber has about 7000 micro services, so quite a lot, as you can imagine. And this was like a few years ago. I don't know what they have it now, although I think they themselves somewhere I read themselves real like that. They have way two services and they were talking about merging some of those services. So the number might have come down. But again, my information is a little bit old here. That's a functional view of microservice and it maps very well to functional programming because at the end, functional programming is all about functions and you can think of functions as micro service. And we'll talk about this mapping in a short while. But the question is what's wrong with object oriented programming? Why should we not use object oriented programming? What makes functional programming so good? When you look at object oriented programming models, right? It models an application as an object with state. So you have classes, you have private functions, you have public functions, and then you have private members and you just modify that. Essentially what you're doing is modifying States. But when you think about services, most of the services don't have state. So it's kind of contradictory. Why would you have object oriented programming. I think most of the time it's just because object oriented programming becomes kind of a de facto. It's prevalent in the industry. So everybody thinks this is the way to do it. It's just prevalent really, people don't think about it. It's just the de facto way of doing it. But I would argue that this is not the best way of doing it. Functional programming is far suited for implementing such services, although most of the modern object oriented programming these days implement a lot of functional programming. So the line between what is if you look at C Sharp, Java, they have like Lambda functions. They have a lot of stuff. Now, CSA particularly is very functional in nature. So there's always a line between what is object oriented and what is functional and that's kind of bearing. But nevertheless, that's the problem with object oriented programming. Object oriented programming comes from imperative programming, and imperative programming was basically invented to interact with Van Newman hardware. Right. But when you think about it, microservices, most of the services are hosted on a cloud or some kind of platform like Kubernetes, et cetera. They don't actually interact with hardware. They almost always run on some kind of intermediate virtual machine or something like that. That's why it's kind of contradictory. It doesn't make sense to use object oriented programming or imperative programming to use these services. And one of the key aspects that people would justify why they would use object only programming like Javascriptp is that they are mainstream languages. They have a very good ecosystem. The argument itself is not wrong. It is correct. I mean, the number of libraries, the Java or Csharp, particularly Java, would have a huge, enormous. So that part yes. However, most of the languages, not more. But some of these languages, like F Sharp, Scala, they can interpret with C Sharp or Java seamlessly. So even if you use functional programming to implement these services, you're not being siloed in. You can still use the excellent ecosystem of languages that you have in the object oriented world. So the question is, how do we model them? I'll just minimize this. How do I model them? I've already kind of talked about service as a function. So when you think about service that services in the world, you're talking about basically functions in the functional programming language, there's pretty much a one on one mapping there, and we'll talk about events. What is event modeling a little later. But when you think about events, think of them as triggers, information that goes in the service or the input for effects. Right? These events, these events can be modeled with Alzheimer's data types. So every language has Alzheimer's data types. F Sharp has disconnected unions. Scala has type classes. Sorry, not type classes. Case classes. Depending on the language you use, every language will have its own. But basically, this is one of the hallmark of functional programming that you do have algebraic data types that can be used to model these events very effectively. And these events generally tend to be immutable because it's an event that happened, something happened. You can't go back in time and change it. Right. And when you think about functional programming, it's very much based on immutability for most parts. Right. I mean, Haskell languages like Haskell with pure programming and we talked about mostly stateless services. Most of the services don't have state to manipulate with, which also maps very well with functional programming that most of the code with your skill function programmer would write is actually pure code. There's no side effects. So the point I'm trying to make is that functional programming basically captures the behavior of service architecture very naturally. So you have the physical model of how services are, and you have the model of how programming languages. And there is a near one on one mapping where you can translate everything from the service model to the functional programming model very easily. So here's an example. And again, examples are in FHA, but you can rewrite the examples in pretty much every state you have an input by imagine you have some kind of merchant service item name items you have like an output. You're checking an inventory. You're talking about an inventory service. So I have some item and I have some name of that item or I have some reference number SKU screw, basically. And I want to check if the item is in inventory. If it is, how many quantities do I have there? If item is not in inventory, when can I expect it? So there's a date and time or the item is not sold. So I can model these input and output very nicely using discriminated unions or shop. And for Scala folks, they can use case process and then essentially a catalog search function simply becomes a function with input and output. In fact, when you look at the practical implementation of how people implement these services and functional programming languages, what they basically do is they would write all the inputs and all the outputs for different services and their code then simply becomes a transformation from one input to another output. Even in object oriented programming, you do something like that, knowingly or unknowingly, you would have all the classes and you would do this object modeling, right? You have all the classes and you write the skeleton and you write the private and the public members of the function and then you later on implement them. So in functional programming, conceptually, you kind of do the same thing and you can model asynchronous workflow also like shipping order, right? I have the stock service, so I get the request, I acknowledge that request and then I send an Async request to shipping. So it's more scalable here. So you can even model async workflow very easily. And one of the hallmarks of micro service architecture is that you have this loose coupling and typically each service will have its own database. That's actually a pattern that you have to follow because if you're doing micro services, you don't really want services to share database. And the reason why the services don't share databases, because then the schema gets tied to multiple services. And the whole idea of microservices to have loose couplings. Why do you have loose couplings? You have loose couplings because then it reduces team interdependence. And team interdependence means faster innovation. That's the reason why you went to micro service in the first place. But the problem with loose coupling, when you have one database per service is that you have distributed data. And we'll talk about distributed data in a while. Also, let's talk about contracts right now. Services are interacting with each other. We saw these contracts. I think of these as contracts like input and output. How do you model these contracts? Turns out, and we talked about it that reading and writing F Sharp provides something wonderful called type providers. Right. Where contracts are defined as snippets on accommodation, Justin. And you can just quickly read them and write them. So you basically have live examples. And then typically when you basically code, you will have these in some kind of common repository or common shared location where all the services can actually reference. But even if you're not using F Sharp, you have other options like your Google protobuff and Apache Drift, right? You define your contracts and then it can generate all the classes that serialize and deserialize. Because when the services are interacting, they often might want to send sometimes they just send raw Jason. Sometimes they want to send binary data. So you have a way of serializing these data. That's how contract management becomes very easy in functional programming if you use type providers. But even if you don't have type providers, you still have an option. And as I said, protobuk would support Java that you can readily consume in Scala. Same is true for Apache Thrift. And I'll digress a little bit and I'll come back to the problem of distributed data. But I want to at this point introduce domain driven design. And domain driven design again is one of the topics, which is pretty big. So I'll be scratching the surface of it. But essentially what it is is an approach of software development where you connect the implementation to the evolving model and you have various entities. And there is excellent references both in functional and non functional world of how you would implement domain driven design. I'm not going to go into details of a domain driven design by itself will just scratch the surface here. But one of the elements of domain driven design is aggregates. And what an aggregate is. It's a cluster of domain objects that can be treated as a single unit. Usually you have a reference root and then all the references refer to this root aggregate route. An example is you're placing an order on Amazon. You have an order. So you have an order ID. And that order consists of, okay, I'm going to buy some shampoo, toothpaste, toothbrush, whatever the items are. So you have a list of items and you have a quantity. Right. But you would reference that as an order. That order consists of different objects. But for you, order is one entity that you refer as an order ID. Right. And then you can think about your software as nothing but a collection of aggregates. The entire domain model of your software is nothing but a collection of aggregates. Now, why is aggregating important? What's the relevance of DDD? We talked about implementing a system as set of services. What we haven't really talked about is how do you partition these services? Right? How do I take this system and how do I divide it into services? I believe I want to go to micro service architecture. Great. But my question is that how do I divide that functionality into different services? And this is where domain driven design actually helps. So more specifically, aggregates, because what happens is aggregates provide the boundaries for partition. So this is the way I can actually partition my functionality into different services now. So here I have an example of an order service. I have a customer service, I have a product service. And the way I have partition. Now, mind you, there is no unique way of partitioning, right? You can fine grain it as much as you want or you can cost grain it. And there are pros and cons on both sides. And that itself is a big topic. But here, for example, I could have order service and product service as one service and customer service as second service. I could do that. Generally, you don't want to fine grain it too much because you'll end up having too many services. But then you don't want to coast grain it too much. Because if you have one big service, then you're basically not taking advantages of micro service. Right? The truth is, somewhere in middle. And sometimes partnershiping is more of an art than a science, actually, because there's no unique way of doing it. You have to rely on your intuition somewhat to do that. But moving on, domain driven design usually has an architecture, right? So you have different layers, like layered architecture, you have user interface, and then you have application layer, which is where transactions would happen. And then you have the domain layer, your objects. Actually, the domain objects like order would be one product would be customer. These are all different domain objects. And then you have the infrastructure layer, which is the layer where your persistence layer is where you have connection to database. So this is where all the Imperial services would run. Ddd says that domain layer is where you should have the bulk of the code. And DDD advocates that domain objects are basically immutable and they are basically data classes with attached member functions. So if you don't have attached member function, they are called anemic domain model, which is an anti pattern in the micro service architecture. Now here when we come back to functional programming and we kind of saw that as examples, I'm actually now exclusively calling it out that you can model these domain objects in form of F Sharp discriminated unions. Or for folks from Scala, you could have Scala case classes. And what that becomes is that when you have all of these, you basically have an executable specification that actually can be checked at runtime because your design is basically an executable design that I can actually compile because it's all raw F Sharp code or Scala code. And that is a big advantage in itself because you can then eliminate the model code gap. Now what is the model code gap? You will see it often that there is some wonderful software architect which would draw a nice little diagram and they will have good documentation on how the software is and then the software is implemented and that documentation is some Word document. One note whatever documentation system you have or Wiki mostly. And then you have the source code and the source code is implemented, but it's not exactly matching because source code evolves, evolves and document stays where it is. So over a period of time your document would say one thing and the code would say something else. That's the model code gap. But when you have your contracts in an executable specification, you compile them. You could check there's a compilation error. So there will not be like your documentation says something and reality is something else. They'll always be aligned in sync with each other. So that's advantage that you have. But now coming back, I flagged about this issue that we have a problem of distributed data. What is that problem? Well, the problem that we have is that we have distributed data. How do we keep the data consistent? Right. And also how do we queries data? Now, why consistency is a problem? Because usually you have multiple databases and what you can have is one database might imply something and another database might have something else. For example, I have an inventory service and I order something. Let's say a product inventory service should keep account on how many products are there on the services. Great. And then I put in a customer. But what happens is when I sell it, I forgot because of a bug or whatever reason to actually reduce the amount of the product that I'm checking out. So if I look at all the products that I've purchased, all the products I have sold, and it's a practical difference, I should have what is in my inventory. But because of this bug, the data is inconsistent. Now when you have one database representing everything, you will not have a problem because you will immediately cache this inconsistency problem. But when you have data scattered, you now have a problem. Your second problem is how do you query scattered data, which is a problem. And both of them are rather problematic situations. So we'll look at the solution here. We can't use asset transactions because look at this simple query, right? In a monolithic you can use it, but in a microservice you have a customer service. So this database is private to customer and this is private to product service. And the micro services architecture do not give you access to database directly. So every service has its own database. You can only interact with that data from the interface. So you really cannot actually just customer service cannot just go to the product service. Right? So if I want to run this query, I actually cannot run a SQL one. I can't even do something like a two phase commit because it guarantees consistency, which is great, but it has its own problem. Coordinator is a point of failure. It's very chatty locks will decrease throughput in a fast moving service, I can't have all of that. So two phase commits is usually not an option that I have. So what do I do then? Well, my Cap theorem says that I can't have all three of them. Consistency, Availability, and Partitioning Right now, in a highly available system, availability is something that I really cannot compromise because imagine if a service is down for 1 minute, the amount of business that you're going to lose, right? Availability translates to money. So you can't sacrifice availability. Given that you're running a distributed system by default, you can't have partition problems, right? Need you to have this partition network also network resellancy. But what can you sacrifice? Consistency to a little bit extent. And this is where we come back to eventual consistency. Now, what is eventual consistency? Eventual consistency says that my system will not be immediately consistent. But if I give a little bit of time, it will eventually achieve consistency. And when I say eventually, eventually often means few milliseconds, basically that the human eye would not really be noticed. So even though your system is not immediately consistent, it actually will not make a difference because your consistency eventually within a few milliseconds, the system will become consistent. So for user it would not make a difference. And this is where event driven micro service architecture is. So now I use these terms events and I kind of briefly described it. So now I'm just going to pull all of them together. What is event driven micro service architecture? So event driven micro service architecture is basically an architecture where you have events. Events occur when there's a change in the system, right. And when there's a change in the system, events happen and all the listeners get notified and relevant people would take actions. And generally it's a very loosely coupled, highly distributed system in the sense that when a sender sends an event, it actually does not know who are the people who are going to listen. Right. It just sends an event. It doesn't care. It's an asynchronous way of communication, basically asynchronous flow. And it might appear fancy event driven architecture and all those things. When you think about it in your everyday life, a lot of these distributed systems concepts you have been actually using since always. For example, my favorite metaphor is that every time you go to an airport, you're using an event driven architecture. Why? Think of every human on the airport as a service and think of the person who's broadcasting as another service that is sending an event. So it says Flight ABC is about to depart in 510 minutes. If you are on this flight, please immediately go to gate three. Okay? It's an asynchronous information. The sender just emits event. Some event is happening. I'm just broadcasting that event. It does not know who are the listeners or will they take any action whosoever have listened or ignored that on the ground, you have thousands of these passengers, and some of them who are on that flight would immediately listen hopefully and rush towards the gate. So they get this event, they take an action. People who are not in this flight, they just keep ignoring, I don't care what's happening. So that's a very practical example of what an event driven architecture is. You're using kind of the same thing in distributed systems. We have message interfaces like Kafka, which basically does all that, sorry, does all that stuff for you, right? You have these message bus where you're putting these messages and sending these events. So that's how it happens in the distributed system world. And we'll look little bit briefly in the communication patterns. But when you have events, how do you build the state? So there's a pattern called event sourcing that builds the state of a system as a sequence of events. So basically what it does is it actually stores the events and every time it has to build the state, it actually combines these events and build the state. So advantage of this is that you can roll back in the history and you can see how my state changed over a period of time. So it gives you that auditing and it enables creating future workflows. Why does it create us? Well, you have an event, you have thought of some use cases, you just implement them. Great. But later on you think about, oh, there's another use case for it, and I want to have new service. Imagine you're using Kafka. You can just plug this service into Kafka bus and you have the topic and messages are broadcasted to the topic. Anybody interested in the topic will just read that message. The sender does not have to know who the listeners are. That's the hallmark of event driven architecture. So I don't need to plan ahead. Who are the people I need to cater to? If an event I think is important, I'll just broadcast it. People who think they need to know this will listen. Those who don't would ignore in future, there are more services that might need this event. They would listen. So that's the reason why it enables creating future workflows. And like everything else, you realize that you have been using event sourcing in some form or another in your everyday life. For example, bank ledger is an event. You open up a bank account, you have zero balance. You put some money, you withdraw some money, you put some money, you withdraw some. There's an event happening. What is a state? A state is basically the total amount that you have in your bank account. Right. Total balance. And what is it? It's some total of all the events that is happening. That's event sourcing. Every time I deposit, let's say plus $5 plus five. Every time I withdraw, it's minus three, I can add all of these numbers together and I get the total balance. So all of these are events. I'm doing event sourcing and I'm building the state by just replaying these events and I can go back in history and see how my bank balance was at some particular time. Another example is get version control, right? Your state is your source code. Every time you make a commit, every time there's a Delta, that's an event. What is your final source code? Nothing but a sum of all the deltas. If I sum every commit that I have made in my history, that's what my source code at any given point of time and I can roll back. And another thing, with event sources, I can actually take these events and break them, combine them, recombine them. Like, let's say in a Bank I detect there is a fraud that happened. I want to take that transaction out. If I have all of these transactions as events, I can just roll back in history, remove that one event, and then play it back. So there's an advantage that event sourcing has. How do you implement event sourcing in functional language? And this is another example of where realize that there's a very good mapping between distributed systems and functional programming. And that is fold function. If you were to model every event, event sourcing is nothing but a list fold. It's a state aggregator function that you have. You take an initial state and you just fold it with caveats that sometimes what you want is sometimes you want to do some intermediate caching for performance. For example, even in bank account, if you have a bank account for like 30 years, all the transactions you have done, it takes a lot of time, sometimes to build. So the bank would basically every end of the day, every end of the week, I'll have like a closing weekly balance. And then if it has to build that state. It may not go all the way back 30 years. It will just go back to the last week because it cached that state. So it's basically implementing event sources is as simple as implementing a fold function in functional programming languages. But you sometimes want to have snapshot of performance. There are benefits. You have auditing, you have temporal Kelly's applications can have same events but create multiple views. We've already talked about it, but obviously there's no strict consistency. It adds complexity and longer boot times. Here we are talking about Saga. What is the Saga? Sometimes you have long running compensating actions for the failure. So you have a transaction, right? You move to a new transaction because remember, in a services you have distributed functionality. What if something fails? How do you handle that? You have distributed data. So let's say you were to move to the next transaction, but this failed. You create a rollback. For example, I'm actually talking about sending money to, let's say, somebody else. So there's $100 that gets deducted from my account and will go to $100 to, let's say, somebody nourished account. But it can be the case that I don't even have $100 in my account, in which case the transaction fails. Right. The other example is you're transferring money and let's say the account closes. So you can't really transfer that money to a closed account. So it failed and it came back. There's a rollback transaction. So that's how you implement Sagas. There are two communication patterns we'll cover very briefly because I'm actually running a little bit low on time. I'll just keep check. Okay, so we have communication patterns, request response, right. This is like most common and most simple, easier implementation, better control, but increases the coupling and difficult to scale. Right. Because every time we talked about event driven, this isn't exactly I mean, it is event driven, but you don't really have a message bus. It's not asynchronous. And then you have the standard Kafka message broker, which has its own advantage. But you're talking about a broker. And typically you break your services in three tiers. So the customer facing ones almost always will be request response. Why? They can't be asynchronous because the customer wants a response. I place an order. I need an acknowledgement. I need to know. I can't just wait and say, oh my God, I don't know what's happening to my order. So that's how the implementation pattern is. This is usually request response. And these would be event driven. Now, I briefly talked about querying the States. Right. We know how to build a state. We talked about fold functions. So typically if you have to query a distributed state, what you have is you build us using the fold functions and then you have this one big state that you can query. And sometimes in a larger system, you don't really don't have one state to have multiple such fold functions because not everybody is interested in all the data. Right. Some people might have some aspects that they may be interested. So you could have services with multiple full functions. In fact, there's a pattern called CQR estimate, query responsibilities, segregation and distributed systems that kind of deals with that. In the interest of time, I can't unfortunately cover that, although I'll add it to my slides when I submit it. So for those who are interested, they can go through it. But yeah, now we talk about testing microservices. So we have talked about the development and we now understand why functional programming is really good for development. What are the advantages? But we really haven't talked about testing. So let's actually get to that subject. So we mentioned that most of the services that we have are pure functions. And testing a pure function is actually pretty damn easy. And the reason why it's actually easy is because pure services are pure. They are very predictable. They can be tested exhaustively. I have set of inputs. I know there are nothing, no side effects. I can just test it exhaustively. So that's the reason why the majority of these services generally tend to be pure services, the ones that are impure, the ones that are connected to databases. This is where testing gets very tricky. For example, if you're testing your credit card payment service, every time you test, you're actually making a transaction on credit card, although I think you can still fake it. But due to unpredictable external state, it kind of gets a little bit tricky to test it. Now in the functional programming world, particularly F Sharp, you actually have wonderful tools. Like I think there's a property based testing library for F sharp. I think it's called FS check property based testing in F Sharp. If you Google, you will get that library link. I think it's called FST that can be used. Haskell World has also similar libraries. Cubic is commercial libraries where you can beautifully describe your system and then we'll generate exhaustively millions and millions of test cases. There's an excellent talk. It's a little bit old but still very relevant by John Hughes. I think he presented it in the functional conference, but I think it was a few years ago. But having your services implemented as pure functions in a functional programming language point makes it very easy to test for event driven. You have to do a little bit of trickiness in the sense that you have a message broker. You have a test driver and a test interpreter because you don't really have a request response pattern. So you inject a test message and then you read the service bus. Now what about static analysis? And this is another beautiful reason why you should use functional programming is because pure functions in function programming are very easy to analyze and reason about. So static analysis generally tend to be very effective. Yeah. Scott Heaven, actually talks about this. Also, Scott Heaven and I actually work [email protected], so I know him pretty well. So static analysis is a very effective way to detect issues in the code. An example is you can test when I [email protected] which was using F Sharp for these services, actually I implemented this that we had a set of Nt patterns, and then we could pass the F Shop code into AST and then test these patterns. And in fact, F Shop particularly has a parser. But even if you're using other languages, Antler is a wonderful parser, and grammars are available basically for a lot of languages now running low on time. So let's briefly talk about some of the advantages we have. Scalability, right. It's infinitely scalable because you have Immutability. You don't really have to worry about lock, race conditions, all those things. That's one of the major benefits that you can just scale them. It allows you to literally scale them from thousands to millions. Haskell has green threads. I mean, scalable parallelism is like one of the stark great things about Haskell. But even otherwise, using pure functional and functional programming, scalability is a big advantage. You also have productivity. Like a Sharp word is much more concise. That's actually true across the functional programming domain that your code is actually very concise. So with few lines of code, you can actually have a lot of functionality. And conciseness and clarity means lower maintenance. Simple code means reduced time. We all know the benefits of having less code. Code is a liability, not an asset. Fyi, everybody understands that. And then you have the code, correctness, right? Functional programming. Basically the code you have strict typing, you have Immutability that makes the elimination of States, eliminates a large class of bugs. Typing will make it very easy. And then you can have exhausting pattern matching at compile time. Right. If you're missing a use case, basically the compiler will catch it at the compile time. So that's a big advantage that you have with functional programming code. Correctness. And then type system obviously makes it illegal. States unrepresentable. Right. A very famous problem is like null pointer. We all know how horrible null pointers are, but in F Shop you have these option types. Kala also has. Or you can even create your own discomitted unions. You could create like one of my favorite construct, actually, is that response. Okay. Response or error something. Right? So either there's a response or there's an error and I have some information on the error. So I don't really have to worry about all the try catch headaches that exceptions might come, exceptions might slip. I can just Pat and match on mine. So that gives me a lot of the silence in my services and case study. Twitter actually originally started as a Ruby rail, but they moved to Scala. I have a link here. It's a rather old link, but still very relevant of why Twitter uses Scala. They have so huge benefits. They have Scala. As one of the dominating languages. Not the only one. They do have Java also I'm almost out of time. Functional programming is great. We talked about it micro service enables faster infection model events using ADT pure functions are great for services and FPS several benefits. We all talked about it. This is my contact information. If you have any comments questions please feel to email me that's my web page it has all my details my Twitter handle with that. Thank you very much for attending. I will stop the video now. Yes thanks for your wonderful session especially considering that it's pretty late your part of the world so we are very grateful that you could make time for us.