 Hi, I'm Stephen Goldbaum from Morgan Stanley. I'm here with Adam Hurwitz from Microsoft. We're here to talk about greatly increasing development efficiency with a combination of two powerful open source projects. Morpher, which is a finalized project, recently contributed by Morgan Stanley and Dapper, which is a Microsoft open source project. So application development. This is really where the developer provides real value and what does it do? They take complex business concepts and they turn them into complex computer concepts. That's really the bulk of what the value is that a developer does in an application development environment. Of course, and then we need to make it run. So that's the most important thing is that it needs to run. And so that's what we think of as the core developer value in the process of developing applications. Then we hit the enterprise and we find out that that's just a small fraction of what we need to do in terms of coding. All of a sudden, we go to the enterprise and we find out that there's probably some standard frameworks that we need to support. We've got regulations, we've got blueprints, standards. We need to register data here. We need to register lineage. There's all kinds of stuff that we need to do. And it actually takes up probably the majority of the development time. So what we consider as developer value is not what most developers spend most of their time on. And that also has consequences in terms of, well, it's not that efficient anymore. And it's risky because some studies show that for every thousand lines of computer code that a developer writes, there's 10 bucks. And so with all that code that we're writing on top of the business code, we're just adding more bucks. And so that's a risk issue. And so naturally you might think, well, what if? What if we could go back to just concentrating on what's important back to turning the business concepts into computer concepts? And we could do something else with all these other things. We can't make them disappear because they're important, they need to be done. There's a couple of ways that you can deal with it. You can try to put it all behind frameworks. That puts a lot of pressure on frameworks. Or maybe, and this is what we try to do, you can automate a lot of that. And that's where Morpher comes in. So at its core, Morpher is a set of tools aimed at logic interchange. And what that means is that we can define a set of logic, put it into a data format. In this case, it's the Morpher intermediary language or IR, and once it's in a data format, then we can do all kinds of things with it, just like any other data. So we can use that data format to generate other code that runs in different runtime contexts or generate configuration and setup to the database and all these other kind of definitions that we might need. We don't have to stop there. We can generate full applications. So we don't have to just concentrate on the code. We can get into everything else that makes an application. And that's what we were really talking about in the enterprise. And on top of that, we can do things like generate documentation, generate lineage, generate all these other things that the enterprise asked us to do. Morpher project has a number of goals. The primary goal is to make business logic a first class asset, something that's protected and stored separately from the rest of the application. Once it's in that format, then we can do things like share it, which is important if we wanted to run in different contexts or maybe we want the same logic to run across different teams or maybe even different firms when we're talking about something like regulations. We want to be able to translate it because we want it to run in different environments. And in order to do that, we need to translate it into different languages, maybe different platforms, documentation. So we want to be able to take that logic and translate it into other tools. We want to be able to store it because it is an asset, right? We don't want the, we don't want to have to risk rewriting it every time we want to change technologies. And we all know that business evolves different than the technologies and they should be able to evolve independently. And we want to be able to visualize it. We want to give as much knowledge as possible. We want new developers to be able to really understand the system without piecing through and diving into all kinds of hard to read code because it's mixed in with all the persistence and messaging and all these other things that go into an application. And some other goals that we have are that we want to increase efficiency with automation. And that's a primary thing of what Morpher does is that once you've got it in the stored format, you can automate a whole lot of things, not just code, but documentation, regulations, audit, all kinds of stuff. We want to make sure it's correct. So this is vital. It's difficult to make sure that an application is correct and that it's doing the right thing when the logic is all over the place or when the logic is mixed in with things like persistence and messaging and loading. And so by consolidating on a model, we're able to make it more correct. And by consolidating on a functional model, we're even able to do more than just look at it and see that it's correct. We're able to apply powerful tools to ensure that the model is more correct than we would usually be able to do with other programming languages. It's important to note that bugs are a symptom. They're a symptom of the code being wrong. And testing and unit testing are great ways to handle that symptom. It still means that we want to be able to take care of the cause. And the cause is we need to get the code right. And so we want to be able to provide tools that enable us to do that. We want to build knowledge. As I said before, we want new developers to be able to understand the system. We also want the business users to understand the system and have confidence in the system and understand that what we have developed is actually what they wanted to do. And there are a lot of things that we can do in terms of automating tools that allow the business users to have that confidence either in terms of showing data flow through the system and why it's making decisions. So not just that the data is going through the system and it's making decisions, but why did they make that decision? And those are important things for both the business and the technology. Finally, we want a community. We want to build a community. We've realized that once people start to use more for an understanding, then they get a lot of creative solutions. And some of those solutions always come back and everybody can take advantage of them. And it just builds a much stronger and stronger ecosystem. And that was part of the motivation of open sourcing it was that we felt that we could build a really, really strong ecosystem around this. All right, so what is the flow of developing a more for application? So the first thing you're going to want to do is get your business logic sound into the more for format. So the first thing you do is work with the business closely and come up with what the business model design is. So we're going to design the model. Once we had that model, then we're going to want to generate something. So we probably want to generate documentation. We probably want to generate some kind of registration into whatever systems our enterprise use. And most importantly, we want to generate onto the platform that this thing is going to run on or maybe multiple platforms, so we want to generate that. So imagine that it's running in a microservice environment. We want to be able to generate the code that actually runs that microservice. And then once we have that code, obviously we need to run it. And so that's basically the more for flow. Design the business logic, generate the application, run the application. So what does that look like in the bigger scheme of software development? So probably right now you have something like the top flow where you work with the business to come up with the business specifications. You architect a solution for that particular problem. Then you code up the business logic into that particular solution that you've architected. And then you've got the regular build, test and deploy cycle. So the first three steps here are very manual in the current flow. What we want to do is move that so that we minimize as much manual effort as possible. And we can do that by getting the business specs together. And that's the only manual process. And we think about it, that should be the only manual process. And then everything else after that we can automate. So let's dig in and take a look at what that actually looks like. We're going to take a sample common application. So I think about a microservice or any kind of service that takes a request and does something with it. So in this case, we're going to have a small microservice sample called books and records that takes a request to book a deal and run some logic to see whether we should book that deal. And if so, it books it. And if not, it rejects it for some reason. So standard microservice architecture application. So the thing we realize with a microservice is that, this is actually a business process. And it's a business process that follows a very standard pattern of it takes some input, it runs some logic, and then it produces some results. And whenever we have a pattern like that, that's a good case for automation. And so let's look at that. So in this case, the request, the input is that we either create a deal in which case we're trying to book it into our booking system, or we close a deal in which case we're trying to remove it from our booking system in one way or the other. And so how we model that. So more for it, as I said before, it's using an open source programming language called Elm. And in Elm, that looks like this. And it really reads as you're defining a union type where either of these could be a command, you can have a command that either says open the deal with all the parameters that are required or close the deal. So similarly, we want to see the results, right? And so the specifications say that a client would want to see the results. Maybe there's somebody else that wants to receive the results. So maybe we should do something with that as well. But in the end, the pattern is that we need to see a result. And what that looks like in Morpher is again, another union type of here's the possible things that the outcomes that we could have are the inputs that we have. So we can either open the deal and say that, yeah, it was successfully opened or closed or something was wrong and the request was invalid in which case we want to let them know that as well. Most microservices have some kind of state in between calls. So this is common. Still a business model, business model says that we want to keep some state. And in this case, the state is a bunch of deals or a list of deals. And so in the deal, these are the parameters that we want to store. Again, we work out with the business. This is how we would model it in Elm. And in this case, this is a record type which is standard data structure. And then finally, and not the least is the logic. So when we get a request, what do we need to do with it? In our case, we want to check that the price and the quantity are valid. So there's no specification on there that says that these are, they can only be less than zero or greater than zero. And so that's what our business logic's doing. So we kept it very simple for the example. Obviously most applications have much more complex business logic. But that's it. And so it's a standard pattern. It's a request, response state and then the logic for processing it. All right, so let's take a look at this code in an IDE. So one of the things I want to point out is that with Morpher, we're really focused on domain-driven development or domain-driven design. And one of the principles of that is that we use the business language when we make our technology. So we want to use terms like price and quantity, especially when we're talking with the business, we would never say things like float or rent to the business. And so we want to capture that in our model and we do this with the Elm type aliases. So that's very important. And we see all the rest here, the commands and the inputs and the outputs in the state and in the business logic. And that's it. That's the entire application. So you'll notice nothing in here says that this is restful or using a message queue or if it's event sourced or using regular OLTP and database transactions or any of that stuff. None of that is in there. And what that does is it makes it very easy to understand the code. So we can see that this service is really, here's the inputs and outputs. It's very easy to understand. And it's often very difficult to do when you look at enterprise software because the code is scattered throughout different parts of the system. And it's some of the codes in the database and some of the codes in UI code and some of the codes in the service. And so if we can model it like this as the system gets bigger and more complex, it's really nice to be able to look at the thing holistically and really understand what's going on without being distracted with, oh, it's gotta save something here or it's loading stuff from the database there or any of that stuff that makes it difficult to understand. And so that's a really important concept. And so what we're gonna do here is we're gonna take this model and we're gonna basically turn it into the more for IR. Again, we're using Elm in this case to do the modeling. And so what we're doing is we're parsing Elm into the more for IR. And just as a reminder, that Elm is not the only language we can do this with. And so this is often interesting in terms of enterprises because often an enterprise has a lot of little bespoke DSLs, domain languages, and little expression languages that pepper throughout the entire enterprise. And they've kind of end of life. Nobody's really keeping them up but they're still making the application run. And so nobody really knows what to do with that. And so more for is an interesting way of dealing with that. And if you can parse those languages into the more for IR then you can take advantage of the more for tools which means that you can transpile them into Scala, into Elm, into some other language. And that gives a lifeline to those languages. They're no longer stuck in a bespoke DSL. And so the next thing we're gonna do is once we've got that IR, we still wanna make this thing run. And what we're gonna do is we're gonna say, well, this time we want this to run in dapper. So our output target is a dapper application. And so we'll see that it's generating all this code. It generated it over here. And one of the things we notice here is that it's generating the Maven as well. So it's not just generating code, it's generating the entire application. And so we can look at the code and we can see that everything that was in the model is now in case classes in Scala. So it's all there. The logic is here. So the logic is translated to. And then all the dapper stuff is in there as well. So all the things that we would normally write by hand we are now generating. And that is advantageous because it saves time and it saves bugs as we mentioned before. The less human code is written, the less bugs will be produced. So it saves us from possible bugs. And it also makes things kind of future proof and evolution proof. So if we wanted to do something like change the messaging format from Jackson and Jason to GRPC, we could do that. And we wouldn't have to go back to the developers and tell them to do that. Or if we wanted to make this run, dapper is a great runtime, but a lot of this logic might need to run somewhere else, like in the database, if we're running reports. And if we wanna be able to replace something and see why it came to a conclusion, why did it reject this thing? Well, we can do things like make that run in the browser and make that run in a different system at a different time using different technologies and know that we get consistent results. And that's obviously important too. And we can also think about other ways we can use this. So let's take something like contract-driven development where a contract-driven development is basically a way to do REST API testing where the server doesn't have to be running. You should be able to have some confidence that the client code you're writing is gonna get some certain results from the server without making the server be running. And the way to do that is that you have these mock clients or mock servers that the clients call. Well, imagine that if we could take the entire set of business logic that's in the server that the server's running and make that run on that mock or in the browser. So then we could type in things and test our clients and immediately know the full range of results that we're gonna get, which is a lot more meaningful than just a couple of test cases that contract-driven development does now. So there's a whole lot of things that we can do with this. And so in summary, what have we done? We've taken a pattern that's common in the business world, inputs, outputs, some state. We've converted that into computer concepts, high-level computer concepts, not how are these things gonna run, but computer concepts. And then we've automated turning that into a running application. And that application is on Dapper. So we've automated the code, the JSON bindings, the persistence, the event mechanism, and most importantly, the Dapper code. And with that, I'm gonna pass this to Adam and he's gonna explain Dapper and its advantages and how it works. Hey, Adam Hurwitz here with Microsoft. I'm an Azure specialist in the financial services organization. And you just heard from Stephen Goldbaum from Morgan Stanley about the Morpher project. And the first thing I wanna do is I just wanna commend Morgan Stanley absolutely in terms of open sourcing this project and taking their years of experience in IP and sharing it with the community. I think there's a lot of benefit that other companies are gonna get from this. And we're definitely excited to see how this project develops as an open source project. What I'm here to talk about is Dapper. You would have heard about that just now from Stephen. That the Morpher project can work well in combination with Dapper. Dapper is a Microsoft open source project. And so this is what we wanna explore right now. Go a little deeper, make sure you understand what this tool is and the basics of how it works. So let me just switch over here. So Dapper, it's a cute name, open source projects, all have to have cute names now, D-A-P-R. And it's a distributed application runtime. It's available, you should go check it out, Dapper.io. It's an open source project, it's in GitHub. So this will click through to various repos that we have in GitHub. And a distributed application runtime, the focus here is you're a developer and you are creating services that are part of a distributed application. So many applications now are distributed. Certainly all the significant applications being built now, the kind of complexity they have, the number of people they have, have a microservice architecture distributed out, such that multiple teams are working on this. So Dapper provides building blocks for you to use as a developer to build your application and do it in an easier fashion without having to worry about how those building blocks are implemented exactly and how they're provided to you. And I'll get into some more detail, what I mean by that. First I want to just say some of the high level goals here, okay? So we have a developer, wants to build a distributed application into a team. So they're gonna decide to use Dapper. They want to have best practice building blocks around building the application. They want to use any language or framework. This is an interesting point I just want to touch on because certainly in large systems, there's multiple teams, lots of teams, maybe there's some legacy code as well for certain functionality, perhaps. And they're using different languages, they're using different text acts. And so it's very important that that is supported for a distributed application. As I just talked about, it's open source. We want the community to be involved and have it use standards and be open in terms of the API and consistent. Agnostic to cloud platform is important and edge. This should not be tied to one cloud platform. It should be something that you can run on-premise cloud really anywhere for it to really be usable in terms of your distributed application because that's what we're seeing. We're seeing people who want to make sure that they have their application running in multiple places often. And then of course, extensible and pluggable. It's out, you know, pluggable gets into in a second. It'll be a little more clear what we mean by that. These building blocks, these services that you're using in your application for it to work, there should be different ways to plug in different implementations essentially. And extensible, you know, instead of others, other companies, other developers wanting to work on the core functionality, they should be able to add in other components and extend the implementation of the system really. So let's start at the bottom here, these building blocks I'm talking about. What are, you know, let's talk about some of them. You know, at a high level, I think they're relatively straightforward if you've been working on any distributed applications. Of course, you know, let's just start this simple. And I'm gonna go through all of these, but the, you know, service to service invocation, obvious, you know, initial problem to deal with and solve. You have multiple microservices that are operating as part of your system. How do they talk to each other? How do they call each other? So that service to service, invoking a function on a different service is something that Dapper can provide. That's one of these building blocks, which is incredibly useful. State management, of course, another, you know, foundational need for your application. You need to save state and et cetera. You can see across these different building blocks that, you know, we feel are generally the ones that, you know, that you need when you're building your application. Now we're gonna be adding to these. You can pick and choose which ones make sense to you. You know, one here, for instance, actors, you know, is that a programming model that you use? You know, if so, then this is great. Some people do. Many people don't. So that's just not, you know, a building block that you make use of. Now what's really important here to point out and notice is the API. So I talked about, let's do standards, let's do open, let's do portable, let's do consistent. Well, look, you know, you have, look at how the APIs are talking. It's HTTP, it's GRPC. You know, anybody, any system, any application code, text that can speak HTTP at this point, certainly. And, you know, they have GRPC implementations certainly as well, but HTTP, by and large, you know, allows us to say across the board, any code or framework that you wanna use, that you wanna bring. So that is how your code calls into Dapper, into the Dapper system, into these building blocks is through that API. And just to give you a little flavor here, you know, this are some standard calls that you're gonna make. I'll get a little deeper into this now. You know, the architecture in general is a sidecar architecture. This is becoming more popular. It's certainly something more people have been, you know, thinking about talking about in the last, I don't know, a few years or so. And so you can see here now in this, you know, description of a system that uses Dapper, it's built with Dapper, you know, you have two applications, two services, two microservices, service code A, service code B that make up your application. And then of course there's a sidecar with each, which is Dapper, right? So there's a Dapper demon running that associated with each one. And the service code interacts with that sidecar and that's how they interact with the rest of the of the Dapper system. That might be calling each other, right? And that's secure communication with MTLS. There were, you know, as I pointed out before, state store, PubSub. Now you'll see with the state store, for instance, you'll see a number of technologies there that are outlined as implementations of the state store that are used as the service that is being used as a state store. So for the service code, the application that you're writing, you know that you need a state store. You know you need to store something in state, retrieve it. But as a developer, you know, you don't care what store maybe is being used. It's not necessarily something that you're thinking about. You need to put it in, you need to get it out and make use of it. And so for the administrator, for the operator of the system, they're going to determine what is the best state store and they're going to plug it in. They're going to configure Dapper to make use of that storage service. In this case, certainly, you know, Redis, Azure Cosmos DB, Cassandra. And this is where some of the extensibility comes in because there are some that are there, where there are, you know, connectors into these storage services. But of course, this is an open source project and there are those who are, you know, they want to use a certain storage service here and they're writing that connector and that component to make sure that they can use it as a state store. And we're seeing quite a bit of that at this point, which is great. PubSub, same thing, you know, as you can see listed here. And so this is another level of detail of how the system works. Let me go, you know, a touch deeper now into hosting. So right now you're saying, well, what can you run this? How do you run this? So you can run it locally. What happens is you're going to get a Dapper CLI, you're going to install and run. You can run locally, mainly for development. And then the primary target at this point is Kubernetes. Kubernetes certainly has become, you know, the way in which enterprises, certainly lots of companies, lots of startups as well, are choosing to abstract infrastructure and manage infrastructure essentially and manage their containers running on top of that infrastructure. And so that is our target, primarily for hosting. And so what happens is you install some pods, Dapper pods into Kubernetes. And those are the guts of the system, if you will. And they do a variety of things, including sidecar injector. There's an operator there. There's a pod that manages the security. And so in Kubernetes, as you can see, and if you know, I mean, it has that interesting concept of the pod, which can be one or more containers, which is an interesting aspect of the service and of the system. And so when you deploy your application into a Dapper enabled, a Dapper aware cluster, and you say that this is using Dapper, the sidecar injector will put the Dapper container, the sidecar container into your pod. And then your container can talk to it and it can interact through the configuration that you have done on the cluster with the other services, the other services, the other building blocks, you know, for instance, if we've been talking about Pub, Sub, State Store, certainly distributed tracing. One thing that's interesting about the system I'll just mention is observability. You know, everything is running through Dapper, then certainly that gives you a very interesting way to observe what's happening in the system. And so it connects with known logging, open telemetry, Prometheus Grafana, Azure Monitor for you to understand what's happening in your system, which is a real big benefit as well. And certainly Kubernetes, it's Kubernetes, whatever cloud on-prem, et cetera. And so that is very useful for people Let me show just a little bit of code before I close out here, just so you get a flavor of, again, another level lower in terms of what I'm talking about. So what I have here quickly is a YAML file to deploy. So just so you know, so you have your container with your application, you deploy it into Kubernetes. You can see here, I mean, it's Books and Records, which is one of the examples that's part of Morpher. And you know, this is just a real vanilla, simple example, you can see it's just a, there's a service, there's a deployment. And you can see here, there's an annotation, right? So the annotation here lets the system know this is Dapper enabled, right? The name of your service, a port to call it on. And there it is, we're gonna call it Books and Record. And it's part of Dapper, so that sidecar is gonna get injected. And then, you know, otherwise, again, it's just your container, this one happens to be an Azure Container Registry, you know, deploying to Kubernetes. Your app, very simple example, could look like this. This is just a flask, Python, you know, few liner where there's an add function, right? There's an add, there's a route for add, which is post, it's not returning anything, it's only returning a string right now. But that could be your service. And another service wanting to call it, you know, the call would just look like this. So what this call would be from, let's say, Service B, or some client, perhaps, of the Books and Record application service would be, you know, local host, right? So it's gonna be hitting its own Dapper sidecar on a port. It's going to be invoking, this is service invocation, and then Books and Records is the ID that we had in the YAML for that container, and then the method it's gonna call is add, and this happens to be a post, dash x, this was part of a curl command to call that service. So that's how it's gonna look. For get state, let's start with save state. So with save state, you have your key value pairs, formatted in this situation, and you're just making a request of your Dapper sidecar, HTTP on the port, and this one is a state request. And then to get that out, just, you know, you're now doing a get, and for that key that you defined of where your state is being stored under as in the state store, and then you get it back. The last thing I just wanna show here quickly is in Morpher. This is integrated, Steven would have talked about this a bit, but you know, there's a stateful app that is defined, for instance, and you can see in this Elm code that Morpher uses, it just says it's a stateful app. So that any interaction with state, what is so interesting that they have done that the Morpher team, Steven, and Attila, and so on have done is that it is gonna generate out that Dapper code for you, so that when you've modeled your application, and then it will implement it in whichever language you choose, Java, .NET, et cetera, and will have the Dapper code there so that when you deploy it into a cluster, you know, it will be able to interact with the system. However, it's configured for whichever state store, PubSub, et cetera. And that's what I wanted to just go over. I hope you're excited about Dapper. It's a, we're very excited about it. It's being received well by the community. I think it has about 8,000 likes on GitHub, sorry, Stars on GitHub, plenty of forks, a lot of community involvement. There's regular community meetings that you can join. I encourage you to check it out. And of course, I encourage you to check out Morpher, part of FINOS right now, and consider it for your project. And thank you for listening. Okay, thank you, Adam. And so there we have it, the combination of Dapper and Morpher. With Dapper, you get a powerful runtime. It does a lot of the heavy lifting that we would normally have to do, you know, with pulling in our own components. And it does the job of making this all work in an effective and efficient runtime. And then we have Morpher. And Morpher enshrines the business knowledge into a data format so that it's protected from technology evolution. It makes it evolution ready and that we can take that same business logic and make it run in different technologies as technology evolves. It gives us the capabilities that are things that are outside of the runtime, like documentation, live documentation, maybe interactive documentation even, so that you can audit, and how did the system come to this conclusion at this particular time? So there's a lot of things you can do that are outside of a runtime that we can still do with automation once we have that business logic. For example, we can use it to generate the full lineage so we can see that these inputs and these outputs and the calculation, you know, here's the results that we got and here's exactly why we got those results. So it's more than just watching the data flow. It's watching the data flow with the whole reason that we got it. And finally it makes the logic portable. So, you know, logic is often used throughout the system or even across projects and even across firms in the case of something like regulations. And so being able to define that logic in a common format that doesn't dictate a technology means that we can run it across projects, across technologies and across firms. So with that, we have actually successfully done what we set out to do. We've moved all of that manual process into just one manual step and the rest is automated. What we didn't show you was that we've actually done it so that when you, we tied into the GitHub pipeline so that when a developer checks in the business model, the pure business model, it kicks off the entire process. Does the build, the testing and then the deployment. So think of it as like one touch, write your pure business logic, check it in, do a merge and it ends up in production in a running system. So what's next? Both of these projects are by developers and for developers. And so both would love the contribution of the development community. So anybody who's interested, please go to morpher.finos.org for the Morpher project and dapper.io for the dapper project. Thank you for listening.