A farewell to soul-crushing code
CC Attribution 4.0 International:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Sperber, Mike
Rauch, Nicole
A major part of software development is maintenance, i.e. tinkering with software that should already be completed but still somehow does not work as it should. Software developed by tinkering is the antithesis to resilient technology, and a growing threat to our profession and our lives. Working on this kind of software crushes the soul. Yet this is exactly how most IoT devices (and computers in general) are programmed these days. We need to replace the dead technology-oriented objects of the past with supple models enriching our domains and our souls. This talk shows how it is done.
 So, our first talk is going to be presented by two speakers, Michael Schreber and Nicole Well. Michael is the CEO of Active Group. He's been developing software and teaching programming for over 30 years. And Nicole is an independent software developer focusing on domain-driven design and event streaming. And she's been organizing software craftsmanship conferences. So please give them a big round of applause for this talk. Good morning everyone. This thing is on. Hey, it works. Excellent. Cool. So, sole crossing code. I think before we say farewell, we should think about what it actually is. And so I thought I'd maybe get a presentation first. There we go. So, okay. So first maybe we should talk a little bit about what sole crossing code is. And so I brought something for you, for your entertainment. And here we go. This is some code I found in an eclipse tutorial. If you know a little bit about eclipse, you can see this by looking at this eye thing here. Yeah. And this actually, I mean, I have no idea what this does. You know, you have this adapter factory, which is really like okay. And then we get an adapter and there's lots of stuff going on. But what actually is this doing? So there's to do, okay, this gives a hunch that this might be this famous to do example. But then I have no idea what's happening here. But maybe that's just eclipse, right? And eclipse, everything is an adapter for everything to do something else. Okay. Maybe. So, okay. I had expected you to say something like this. So I thought I'd bring another example. And this actually is from an open source project. And this actually is a native query interpreter initiator. I also want an interpreter initiator. Who doesn't? And also it's a session factory service initiator. Wow. I'm getting impressed. So, and then it also does lots of stuff. And then, okay, we have initiate service. And then we have another initiate service. And then at the end, wow, we have this get service initiated. Wow. Okay. So, fine. But I mean, that's just a bunch of kids doing open source software, right? Yeah, this is those are all hobbyists, right? So, I mean, what would you expect from something like that? Right? Okay, fair enough. I brought I brought a professional example. Oh, I see. Okay. Everybody stand back. So here's a here's a professional example. So this is from a system that does queries of some sort. I think there's a shape and translation from German to French to English and me or somewhere. So you can see that it does either full text search or it does non full text search or something like that. And so obviously in the initialization of some C++ class, it checks that flag and it instantiates some object either to the full text variant or the non full text variant, right? And you would think this is object oriented design, you just go and call methods. Yeah, that one instance variable that you have there. If an else is so object oriented. Yeah, well, that's just the constructor, right? This is not the bad part. The bad part is that every single method that actually does something like this one looks like this, right? It checks that flag again. And it either calls full text research, which is I guess also has something to do with full text search. You can see that there's lines commented out and nobody nobody remembered to leave leave a comment as to why it's commented out. And you can see that this code is really fragile, right? If you want to maintain that kind of code, every method looks like this. You always need to remember to check that flag before you do anything to be sure that, oh, I'm here or I'm there. Okay. Yeah, so I mean, okay, so the fact that somebody uses an object oriented programming language does not necessarily imply they actually understand what object orientation is all about, right? So maybe they are just crappy programmers. Okay, so they happen to use this and then they mess it up on the way, you know, but non crappy programmers can produce crappy code. And now you're getting me confused. I think you I have you have another example. Yes, I have a much better example here. A real object oriented example. So this is finance finance, right? So here we have options. In this case, just call options. And so the the financial guys want to talk about those options, but there are so many different kinds of options. So they cannot talk about each of them individually. And so they want to group them together. In something they call a basket. So up here, you can see this basket. And it contains Google and Facebook because they are sort of like the same, you know, so they just group them together in this basket. And then they want to talk about properties of this basket of all those options that are contained in it. And for example, here, they implement this market data. And so this is standard object oriented business, like everything is a class, right? And there we have two methods in there because that's also standard object oriented business. We have a class and then we have methods in there. And one of the first method get spot just gives us the spot price. So all of these options have a number in the real world. And that's why they number this here. And for the fun, they call this sick of them. I've no idea why this seems to be a French word for I don't know what it means. But yeah, just go with this. So this maturity thing, that's the date at which point the option expires. Yeah, so that's for the volatility. So you get the volatility for an option. An option is defined by the underlying asset. And by the date, it's due and also by the price it's supposed to have them. And that's what is encoded here. So we have the option with this long and then we have the maturity, which is a point in time. So we can properly use a double for this, I think. And then we have the strike, which is a price. And probably some of you know that it's not a very good idea to deal with money in terms of doubles. But on the other hand, it's fairly common in banking. So let's do this here as well. Okay. Fine. So yeah, that's it. Yeah. And then what they actually want to do, so they don't only want to look at the world as it is, but you know, those guys with the suspenders, you know, they want to analyze and see what might happen if something would happen, you know. So they want to play what if games. And for this what if game here, they take the spot price, and they actually want to shift it. So they want to say, what if the spot price were different? And what would happen then with my options, right? And here they just, you know, so if you want to modify something in object orientation, you write a derived class. And this is the derived class, spot shifted market data. And this derived class overrides the get spot method. And it takes the value of the parent class and then multiplies it with a factor. Okay. Sounds straightforward so far. And then of course, they don't only want to multiply this with a factor, but they also want to do other modifications. And they want to be able to do all these modifications without recompiling. So they want to play around with these and they don't want to recompile their code every time they change something. So they want to have a dynamically configurable code base, so to speak, or dynamically configurable market data. And if you look this up in the object oriented literature, you come up with the decorator pattern. And so the decorator pattern is something that allows you to dynamically modify your code. So you have a component and then you derive a decorator and the decorator as a delegate to something else you want to plug in basically. And this is how they implemented the delegate. So they wrote the decorator as a derived class and then they have their, they have the real object in there. And for the get spot method, here they just ask the get spot method of the underlying object. Fair enough. And now, going back to the baskets where I started out initially. So what they did in this one derived modification here, they multiplied with a factor. And now in the basket, they get here, they get a bunch of options, say, or a bunch of assets. And now they want to calculate this for all of them. And they go into this recursively. And it's very hard to see here, but what actually happens is they go into this recursively. And do this modified operation for all of them. And because of late binding, it happens that they keep getting through this upper method again and again. So adding the factor again and again. And of course, they did not figure this out by looking at the code because, like I said, really hard to understand. And of course, this is all just small snippets of the code, but this is the essence. But they found this because the values were incorrect, right? And so what they did is they compensated for this. And for example, here is the most interesting part, I think, does the first market data derive from the second one? So they check whether they have this chain going on and then they do something differently. Well, I mean, this is production code, right? And this is still in operation. And probably this method by now is like hundreds of lines long because they have so many edge cases they need to compensate for. Well. Yeah. I can imagine that. But I mean, it's obvious they just shouldn't have done this in C++ or using object-oriented programming, right? So do you have a better suggestion? Oh, absolutely. We have slides on this. You have slides. So people should have used functional programming, right? Which is great because... Oh, how could I forget this? Of course, you would say that. I'm a functional programming person here on stage. So functional programming has all these advantages, right? You can have immutable data. Immutable data means you have less coupling. You don't have these complicated effects going on that you saw earlier, maybe. You can... Functional programming is very close to mathematics. So you can apply formal verification. Isn't that scary? Yeah. And you can use all these great mathematical things in there. You can have catamorphisms. You can have bifuncters. That's my new favorite thing. Monats. Monatic profuncters is also something that we've been using lately. That's great. Clice the arrows. There's all these wonderful things in functional programming and they solve all of these problems, right? Yes. I could... Why are you laughing? Who's laughing? I should have imagined you saying something like this. But have you ever considered that you're tackling the problem from the wrong angle? I mean, you and your horrid of IT tech nerd, you're sitting in your cave, hacking away, having your hood over your head and just sitting there and hacking and hacking. So that problem solved. And I mean, really, just throwing tech at the problem is not a solution. It's actually part of the problem. But we're a producing software. We're producing tech, right? Have you gone through this thing here? There's tech outside everywhere. How do you make that? Probably not by sitting in the corner and just writing, hacking away. Okay. Have you considered that there is more to it? That it's not only just tech that you need to talk to each other? Mm-hmm. Yesterday, I saw this robot walking around in a circle and it said, I need new code. Please talk to me, right? This is something like this. Okay. So we need to talk to each other. It's not only tech. Tech is nice and everything. So where's... Do you have a pattern manual for that? A pattern manual. Yes, of course. There are talking patterns, actually, for people like you. Okay. So, go ahead. So... Educate me. Okay. So, I mean, there were many approaches over the years, right? Some approaches were, for example, looking at agile software development, you know? And it says individual and interactions over processes and tools. Tools. Tech. Okay. So, let's talk together and let's figure out things. Okay. Well, but it does say working software also, right? One of four, you know, says working software because, of course, we also want working software, right? Yeah. I mean, just talking and no coding is also not the answer. Yeah. Anyway, so last year we were at this conference, right? And you were probably talking to somebody, but I actually attended the keynote and it was by somebody who talked about what worked and what were the ongoing problems in software engineering. And this was an agile company, right? They do everything in an agile manner. So, supposedly, they communicate all the time. But still, when they look at where they spend all of their time and all of their work and effort, they say that they still spend 53% on maintenance and complexity and not on new features or... I have no idea what that professionalization thing is, actually, but it takes up 18%. Looks nice. So, let's get back to the technical problem, shall we? Yeah. So, I mean, we already saw this, right? In the market data example. I think much of this maintenance and complexity problems is caused that we are in a world consisting of objects and so everybody jumps on this object-oriented bandwagon, right? And what they actually end up with is something like this. Okay. And this is sort of... Like, not helpful. So maybe... But I would like to explain this maybe in a different way. So, modern object-oriented programming... Well, you can all laugh at that slide before, but we really need to understand the problem, right? The technical problem. Is this, right? So, at the heart of modern object-oriented programming, something called imperative programming, where all these objects that you showed on the previous slides, they have what's called encapsulated state. Okay? There's some state in there. And what happens is the world progresses by all these objects sending messages to each other. And as a result of a message, some code gets executed that modifies that encapsulated state. Now, the thing was... I mean, object-oriented programming was originally developed to support simulations of the real world. And the problem is that the real world just does not work like that. The real world is not a bunch of objects sending messages to each other. So, one simple example that maybe can help explain that is there is an elephant... Speaking of elephants, right? Yes. A great elephant slide. So, there's an elephant, and the elephant comes in from the jungle and walks into some kind of room, right? And the object-oriented model for this is, well, all the entities get models, get objects. So, the elephant has an object, the jungle has an object, and the room that the elephant enters has an object that represents them. And you have the sequence of method calls or message sends that tries to reproduce that sequence as well. You know, the elephant exits the jungle, and the elephant enters the room, right? The problem is that the exiting of the jungle and the entering of the room are one and the same act. So, the real world has dependencies. It's not just a bunch of isolated entities that are sending messages to each other. Things hang together in the real world. So, I think a more useful model for thinking about programs and how programs should model the real world has to do with... It should really go through the way that we perceive things. So, if you watch a soccer game these days, there's lots of objects that you see, right? So, you see 22 players, maybe. You see a ball. You see the referees. And you see lots of people in the audience, and they all move. Now, so they all change their internal state if that's the model that you use. Now, if you want to know what's going on in the football field, you need to observe all of these changes. But do you know what the object-oriented model is for observing changes? Something called the observer pattern, which means that you register each of these objects and tell them, well, if anything changes with you, send me a message. You know, do your ball, send me a message. If you move, you know, you do that with all the players. Supposedly, you do that with all the 20,000 audience members. And so, and of course, when you leave the stadium, you all send the messages, oh, no, I'm no longer interested in what you're doing, right? The world doesn't work like that. It has another problem is that all these messages will arrive in some sort of sequential order. And that also would mean that with all of these objects moving around, we would observe inconsistencies all the time the same way that we observed it with the elephants going into the room, right? If you remember, there was an inconsistent state in the middle here, which was that after the first step, the elephant is, for a brief amount of time, is nowhere. It has exited the jungle, but it has not entered the room yet. And the same is true, of course, if we have many moving objects, but yet we never observe, like, one person getting up and suddenly appearing in another place or two people appearing in the same place at the same time. And that's because our perceptive apparatus creates consistent snapshots of what we observe, right? We look at something and it gets stored in memory and we can think about it for a little amount of time and analyze what's going on. And so, and of course, you know, we remember things that were in the past, which is also something that an object-oriented model cannot do. So, I think there's fundamental problems with this object-oriented model of programming, and that's one of the fundamental things that leads to that sole crushing code that we've been talking about. Yeah, that actually reminds me of a very interesting thing that lots of people are using, and that's in the UI, and it's called the MVC pattern or model view controller. And if you have ever worked with this, you can see here that this all goes in circles and you can go in any direction and then you end up here again or you go this way around or anything or follow this dashed line and so you can go from anywhere to everywhere. And this leads to the obvious problem that if you have changes in the model and changes in the view, they need to hopefully be corresponding or maybe not. And what do you do about this? So, what you end up with if you do this enough and if you aren't very, very careful, you end up with this, right? Certainly my MVC programs have always looked like that, right? Yes. So, it feels really familiar, doesn't it? Yeah, yeah, it does. And I think that's also what Alan Kay was talking about back in the day. So, this is a quote from 1996, but I think the paper just appeared then, but the original quote is much older. And so, he said, okay, OOP had those motivations that we described here, but eventually we need to overcome this model and we need to find something better and eliminate it altogether is what he says here. Okay, but that never happened, right? No, I don't think so. It never happened. So, if these days if you look for examples of how object-oriented programming works, it always is about encapsulated state that Alan Kay wanted to get rid of. So, I think that's the first thing when I searched for object-oriented examples was something with students and you can immediately see that a lot of attributes that you have there go through some kind of, some method that modifies them. My favorite one is that you have the student and you can set the grade point average of the student. So, you can just, yeah, so if you're not happy with the grades that your kid is getting, you just send the object a message. You know, get a perfect GPA there. So, and let me reiterate, Nicole, of course people should have used functional programming, which has all these simple languages. Yes. That's complexity, higher productivity, less bugs. You know, we have all these powerful type systems. We can do property-based testing. We can do, well, it goes on and on. We get more predictable behavior. Generally, testing is easier because we don't set up and tear down methods. You get lower couplings. You have fewer dependency cycles. So, I didn't even say monad, right, here in this list. So, you get all these concrete, you get all these concrete advantages from doing functional programming, right? So, that's what people should do to solve those problems. So, do you remember Fred Brooks? He said, there is no silver bullet. Okay. So, what do you say about that? Fred Brooks is an old guy, right? Yes. And what about you? Yeah, I guess I am too. I'm getting there. Yeah, well, so, Fred Brooks said that, but he's an old guy. So, let me get you one example of why that maybe is not true. So, in the early 90s, actually, there was a big study conducted by the US Navy on the effectiveness of different programming languages. And they had one set problem that was about determining the regions of influence of warships. And they had different teams write solutions for their problem in different languages. And what they ended up doing is also, is they gave that also to people who were using functional programming specifically in the Haskell programming language, which was still pretty young back then. And you can see, well, the solution in Haskell is much shorter than the solution, you know, C++, definitely less than 10 times as short than the C++ solution. I think Java wasn't as big then. But I think the factor would also be around between 3 and 10 somewhere. Also, what's maybe interesting is that there are two Haskell solutions, one at the top and one at the bottom. Probably they just split the code so the numbers look nice. Yeah, yeah, you would need to add them up. That would be interesting. But what they did is they had a Haskell expert write a solution. And then they also gave the solution to a student, I think, who learned Haskell for two or three weeks, and who also wrote a solution. And if you look at development time, so somebody took 10 hours and somebody took 8 hours. And the 8 hours is the student. That's because the Haskell expert tried to put many interesting flourishes and super cool programming techniques into the program. But the student was actually doing pretty well. So if that is not a silver, if that's not what a silver bullet looks like, I don't know what would. Okay, so the Yale study, right? Yeah. They got a fixed set of instructions, and they just had to code those instructions. Do I remember that correctly? Yeah. Okay. So do you ever experience that in the real world, getting a fixed set of instructions from your client, and then just implementing this? And they never change their mind. They never come up with new ideas. They never, like, say, oh, I forgot something. I actually don't experience this. Let me think about it. Maybe you can move on. That's what we need to consider as well, coming back to the elephant, right? Okay. Talking to each other. Everybody has different ideas. Now, you can start with that agile stuff again. Everybody has different ideas when they look at something, and everybody describes things differently. And so what we need to do is to figure this out together, coding a bit, talking a bit, talking a bit, coding a bit. And so this needs to go hand in hand. And this is sort of agile. Agile doesn't mean scrum, and standing in a circle every day or something. Relax, okay? So personally, I like to communicate with code. Yeah. You can do that, too. So that makes me think of an example that we were working on in our project. Oh, cool. A semiconductor factory. Wow. So real stuff. This was serious business. I see. Anyway, so when we started this, I don't know, you all know this, right? When we started this, I thought, well, a semiconductor, the way it gets made, there's a big machine. You put in a piece of silicone, and you go like this, and junk, and out comes a microprocessor. And it doesn't really work that way. One of the reasons is just that a modern, the modern chip consists of many layers. Another one is that there's just many different production steps that are necessary for making even a single layer. And some of the machines that make a layer are so expensive that you can't just make an assembly line. And also a lot of things break all the time in a semiconductor factory. So it makes no sense to just have an assembly line and push things through that, but things just move around among the different machines in a semiconductor factory, right? And so what's important is that each chip or each wafer undergoes a sequence of steps in the factory, and that needs to be managed. And those steps, it's typically for big microprocessors that might be like a thousand steps. So you need to manage something that's called a route, which is, well, just a sequence of operations. And now here's a bunch of Haskell code. Haskell is great because the programs are so short that they fit on slides. But if there's something unclear about that code, then I invite you to interrupt me and ask. So first of all, you can read that declaration at the beginning, says data operation. And that's just a simplified data type that describes what an operation would be. And it says, and you can read that vertical bar as or. So it says an operation is either track in or process or track out. And tracking in just means putting a wafer into a machine and processes. You do something inside the machine and track out as you take it out of the machine. And then the next thing is that a route is just a sequence of operations. And these brackets that you see there, they mean list off. So what it says is a route is a list of operations. And down here, you have an example for a route, for a very simple route that says, well, one route, route number one, might be a list of the following operations. You put a wafer into a machine. You process it. You process it some more. And then you take it out again. There so far? Everybody nod? Everybody who's still awake nod? Okay. So don't be afraid to ask. So one thing that you do is when you have data types, as you just saw, is you define functions on them that describe some aspect of what happens in a FAB, in a semiconductor factory. So in a FAB, what happens, of course, is you need to execute the next step, the next operation that happens as part of making a semiconductor. And for that, we're making a function called route head, the head of the route. And what you do is you write a type signature. And type signatures are very good for communication, actually. So you put in a route and you get out a single operation. And then you write equations that describe what that function would do on different aspects or different classes of input. So in this case, you remember a route was a list of operations. And lists, there are two different kinds of lists. One type of list is the empty list. And the other kind of list is a list that has what's called a head or a first element and a rest. And because there's two kinds of lists, you write two equations. And so that's why you see two things where it says route had something equals to something else. And the first equation is for the empty list. This is why you have these two empty brackets. And the second one that says, well, it's a non-empty list. And the first thing in that list is some operation op. So this is something called pattern matching. You match this onto the actual list that you see. And op then gets bound to that first operation. And we don't really care about what comes after that first operation. And so the second equation is pretty clear. If you want the head of a route that is not empty, you just take the first element of that list. OK, so far? And the other equation says, well, what do we do with an empty list? An empty list does not have an operation. So you are saying you're into the second slide of your beautiful Haskell code and you already don't know what to write there? Well, so we're communicating, right? OK, OK. So you're talking, you're talking to some of the expert and you say, well, you have got an empty route. What's the first operation of an empty route? And he says, well, empty routes, they don't really have a first operation. They only maybe have an operation. And sometimes they don't. So for that, we can create a data type that says that something might sometimes be there and sometimes it's not. And we'll just call it option. Are there any Haskell programmers in this room? Oh, OK. So this is built in, of course, as the maybe type. But I'm just making a separate type called the option type. And that says, well, the A says it can be anything, right? Anything in option A means it can either be there or not. And for that, it has two constructors or two different classes of maybe objects. And one are called the sum objects and the other one are called the none objects. Maybe we'll start with none. So anything can be a none. It just says that anything is not there, right? So anything can be of type option of A. And it means that something is not there. And that is the type of that particular constructor. The other constructor says, well, that thing actually is there. And so the constructor has to accept something of type A and then give us something of type option of A. OK? So you're saying it wraps this object? Yeah, it wraps the object. And so if you're not a Haskell programmer, but maybe an F-sharp programmer or an ML programmer, then that is what it looks like there. And I believe it's even built into Java these days, something called optional. So and now that means we can change our route head function a little bit because our first attempt didn't work out. And instead of saying, route arrow operation, we write route arrow option operation. It may seem trivial to you, but it already communicates a tiny little bit of something. So and then we can write, route head of the empty list is none. So there's no head of the empty route. Or if we have an operation coming out, we just write some in front. And so if we use that example route that you saw earlier, where R1 was track in, process, process, track out. What we get is sum track in. So that type communicates a little bit of what we do. Because always, it's already calling the shots. Very good. The next thing that we might want to do is we don't want to always know only the first operation. We also want to know what happens after that. So we can use that option. And we already know that, of course, an empty route will not have something coming after that first operation. So we could write another function called route advance. And it takes a route as input. That's to the left of the arrow. And it gives us both an operation and a route. That's why there's these two things in parentheses with a comma in between. So that's a tuple. So it gives us an operation and a route. But only sometimes when that actually exists, which is why there's an option wrapped around that. So what we want to do is if we take our route number one, we want to split it into that first operation and a list of the rest. So it should split out the track in and then give us a list of the remaining or a route of the remaining operations that are in there. OK, so far? So it gets technical. Don't be, does anybody have a question? OK. So don't hesitate to ask. I'm looking at the clock. So and then this is actually pretty easy to write now. Again we need to make two equations because a route is a list and lists always need two equations. So we can say route advance of the empty list is none and route advance of up and the rest is we just return a sum of up and the rest because the list already splits exactly along the line that we wanted to between the first and the remaining elements. So this is just very simple code or at least a short code that communicates what routes are. Right? I see. So if I remember correctly, I mean you said you put the wafer into the machine and then it processes it. If I remember correctly, some of these processing steps can be chemical reactions or something. And so it might be the case that they must happen in a certain amount of time or something, if that's true? Yeah. OK. So what we could actually do is we could model something like this. Yeah, I sneaked at your part of the slide so I chucked this in. So what we actually could do is we could model something like those three steps here need to happen together in a set period of time or something. Yeah, so the chemical reactions mean that your wafer might go bad. Yeah. If you start the sequence of steps and you don't finish on time, then your wafer goes bad. Like etching and washing for example. If you etch too much then. Yeah. OK. That's always a problem in existing systems. Oh, is it? OK. Ah, so. Oh, so maybe I can try and see how I can model this into your existing code. OK. Cool. So let's have a look. So what we first need is we have this route element here with this operation, right? And now we need another representation for a route element. And let's call this route QT zone for Q time zone. And there of course we have the duration. That means the amount of time. This step needs to be finished in or this sequence of steps needs to be finished in. And then we have this list of operations here. We saw this before, right? The list of the operations. And then what this gives us is of course again a route element. So we can combine like ordinary steps like putting the wafer into the machine. Doesn't matter how long it takes. Maybe it blocks the machine. But other than that, no issues come from that. But if we do the etching and the washing, for example, we would need to have a Q time zone because we need to restrict the time that this takes in conjunction. Right? Is that correct so far? Yeah. Good. And then if we look at our example, this is the previous example we had here. We could create another example. Where is my there? R2. And here we have a route Q time zone. Say it may only take five, whatever seconds say. And then we have two processes here that need to be finished within five seconds. And then we do the track out again. Okay? So far so clear? Good. And then if we look at this and we discover that here we have this route element list and here we have this operation list, this is actually sort of similar, isn't it? So maybe we can make something out of this. And maybe we can actually turn this down here into route elements as well. Oh. So that's what you were doing before, right? Before there it said up there it also said list of operation. Up there? Yeah, up there when it said type route, when you started, my code. My code had route equals list of operation. Right? And now you did the same thing. Oh, yes. Yeah. Right. So now it's the same again. Okay. Right? So it's both route elements. Yeah. Good point. And now if we look at this again, so maybe this actually means that this year is not just a list of route elements, but maybe this is actually a list of routes. It's actually a route down there. So actually derive some information here from the code so we discover that our route QTime zone actually contains a route. So what are? So if we look at this here, what we then can do here with this route element, so here we could plug in any route element. Right? For example, we could plug in a route QTime zone, which is also a route element. So coming from this example here where we have just a flat list that just contains some route operations and a route QTime zone and then a route operation, we could also stack them into each other. So a route QTime zone could again contain a route that contains a route QTime zone. Yeah, that's pretty cool. Do you think that would happen in this pre-reality? Yeah, that's pretty cool because now we can nest QTime zones. And that's something that occurs in reality. Oh, really? Does it? Oh, cool. And so your model has suggested that, but it's something that our old IT systems based on object-oriented programming couldn't model. That's pretty neat. So now I understand why you're aiming at functional programming and saying that you can model things better with it. Yeah, and this is pretty cool. So we discovered this in the code and then we were able to get back to the business people and check back with them whether they would actually see this in practice and whether it's a valuable addition here. And we discovered that just from looking at the type information we had. Yeah, and then we can continue this. And because now we have this list of route elements down there, we could actually say, oh, yeah, a list of route elements. We know what that is. This is actually a route. And now we go one level up. So whenever we learn more about routes or whenever we change this here, this route thing, it will automatically be reflected in here because we abstracted it. And that's what functional programming is all about, abstracting things and figuring out what the common parts are. Right? You noticed you're agreeing with me. Very good. Excellent. So, and now we can also, of course, check how our functions will be modified because now we need to go to all of our functions and see whether they still work. And here we have this route head and also route element head. And now we need to extend this because the route element head works on the route element. And now we have a new route element, which is the route queue time zone. And of course, if we want the route element head of the queue time zone, this is, of course, the head of the containing route. And we have this neat function up here already, route head, which gives us the head of the route. And so we can just reuse this here. So even this has become simpler for us to implement because we have discovered that there is a route in there instead of just a list. So no special handling. We can just revert to the standard function we already have. And if we look at the route advance, so if we want to proceed our route to the next operation and proceed to the next step, then of course we also need to add this here, the queue time zone. And now the question is, what happens if we advance into a queue time zone process? Because somehow we need to keep track of when does it need to be finished? So initially we said, OK, it may only take X time or D time. And now we need to keep track of whether this time is already taken up or not. And so in this case, what we actually do is we need to add another route element. And that's a route queue time limit, which defines when a started operation needs to be finished. So it has an actual time, which is the point in time, like now duration or something, just the finishing point in time. And then it's just the same as the route queue time zone. So this limits our process up to this endpoint of time. And now we can implement our route advance because whenever we have a queue time zone, that's where we didn't know what to write before. So whenever we advance this route, then we know that we need to come up with a route queue time limit here. And whenever we have this queue time limit and we advance over that one, then we know that we just need to basically behave like before. We need to split this up and also keep our time limit, of course, and then just proceed into this limited while keeping the time limit. And here, if we start this out, then we need to determine the endpoint. So we take the current time, which we now need to pass in here at the top. So we take the current time, add the duration, and then we know when we need to be finished with this process. And then in here, we just work on every step while keeping the time limit. So your code suggested that there was a gap in your understanding of what needs to be represented, right? Yes. So I didn't know what to implement for the route advance. And now I know that, yeah, I can handle this. So watching this, I'm thinking that there's still a little, if I look at it with the eye of a domain person, I think there's still a little problem in there. Which is, yeah, if you look at this, remember a route element is something that can occur anywhere in the middle of the beginning at the end of a route. So it has these three things. Obviously, we can have queue time zones anywhere. We can have operations anywhere. But the thing is, we can only enter a queue time zone when it's at the beginning, right? Oh, I see. So now... So you mean here we could have a random list in a random order? Yeah, that's a good point, actually. So this suggests that the queue time zone has been entered because there's a route queue time limit. But there's still an operation there in front of it. Okay, yeah, that doesn't make sense. Yeah, that makes no sense. So if we could go back from the domain knowledge to the code now a little bit, we could refine that type further and we could pull out the queue time limit from that type down there because these are all the things that occur in the middle of a route and pull it up to a top level type and introduce an intermediate type that distinguishes between what's in the middle and what's at the beginning. Oh, I see. Yeah, that's neat. So what we now have is we have this back and forth between the code which yields insights about the domain and the domain and from the domain back to the code. We can play that game. We can use the code for communication. Yeah. So that's what I intended. So that you understand this. Yeah, so that code no longer crushes my soul. Excellent. So I can say that. Yeah, right. Same here. So, cool. Okay. So that's what the point we wanted to make. So if you take functional programming and if you add communication and discussions and this going back and forth and learning from both sides and enriching both sides with the information coming from the other part, then you actually end up at a silver bullet. Everybody's looking confused. That's a bullet train, a silver bullet train. Okay, we're done. Yes. Thank you. Thank you for a very entertaining talk. We have some time for questions. Q&A. So if you have any questions, please line up next to the microphones. We have four microphones spread across the room and we'll start from a question from the internet. As an FP beginner with a weak background in math, would it be preferable to learn functional programming in pure functional language over languages that are multi-paradigm? So I take that one. Okay. So I think the point is that there's many different functional programming languages and Haskell happens to be what's called a pure one, but there are also languages that are hybrid between object-oriented and functional programming. Scala I think is the prime example right now. And I mean, these are, Scala is a fine language. The problem is if you want to combine these two paradigms, you typically get something that's pretty complicated. So Scala is a complicated language that takes more time to master also because you have both paradigms available to you at both times, at all times. It's sometimes, you often get confused about what paradigm you should use in a given situation. So I think both of us, we haven't really seen the great advantages you get from that hybrid model. Right? I think that's a good reason. And I think that's a good reason, because if you're a learner in FP and you try to tackle this with something like Scala, you will inevitably fall back to what you know if you run into problems. And so maybe just jump into the deep end and try to swim and see where you get at and get help on the internet. Yeah. Number two. Okay. Yeah. Yeah. It was a good presentation. Thank you. Every time I see some functional programming, it's refreshing and it's interesting. But the description of your presentation was talking about using functional programming in IoT. So there was nothing specific to IoT in this presentation. There was no interaction with the hardware, no interrupt, handling, no nothing. How do you handle that, for example? Yeah. Good point. I think we had a bunch of slides on that that we ended up dropping because of time. But so my argument would be that IoT is the software is the same software is the same software as any other software. What's special about IoT is the risk that emanates from IoT, obviously. So if you do things like, so if you want to do things like interrupt handling, I think my response to that would be to convert it into functional data structures. And this gives you a deterministic model for handling that kind of stuff. So we talked about that. I think we talked a little bit about the observer pattern, which is analogous to what usually happens with interrupt handling, which is what you were talking about. And the way to do that really is to have, of course, you have a tiny bit of imperative code that hooks your functional code to the hardware or whatever it is, but to convert your interrupts into a list. And you can ask, well, actually, it's pretty good at that. And that gives you all the advantages of functional programming, the testability, the funny, the funky abstractions. And you can use that even on the interrupts. And it turns into software just like any other functional software. Microphone number one. Hi. Thank you for your talk. I have to write code for microprocessors. And most of the time, I only have a C compiler. And if I'm lucky, I get a C++ compiler. Where can I get a silver bullet? So the old Haskell compiler used to compile to C. Nowadays, it doesn't do that anymore by default, but probably you can make it do that still. I'm pretty sure you can still do that. Yeah. But there's a number of functional languages that compile to C. So it's kind of difficult to give one shot answer. We've also done a project, for example, where we get a lot of the advantages from functional programming by writing code in Haskell that generates the C code. And so it's difficult to give you one answer without knowing more details about what it is that you're doing. But there's certainly a spectrum of options available in that context. So functional programming is pretty concise and pretty compact. So no one really wants to use large variable names. And I saw in your examples, like a D and a TTL, RT, and I don't think that there's so much better than the long versions you showed earlier. What is your take on that? Yeah. So the general... So I'm also struggling a little bit with this. One thing is that this was fairly concrete code, right? But often you go into the abstractions. And in the abstraction, there it's arbitrary what you have. So you can use short names because you're not talking about concrete things anyway. So that's why it's easier to use also more like abstract variable names. But what I actually do is I also use longer names. So I would not always use D and RT and something like that to get a better grip on this. But one important thing you must not forget is that this... You have a function, right? And it's two lines, three lines. And so if you start out and you understand D and RT, for example, from the signature, and reading three lines of code with a D and a RT in it, it's not that bad, right? And in object-oriented or Java or whatever, you sometimes have hundreds of lines. And then you have a D and a RT, and you read this for half an hour, and then, of course, you forget what it means. So it's a bit of a balance. So I would use longer names as well, probably, but sometimes also shorter because just the code is so short. Okay. If I can add one detail is I find myself using longer names in dynamically type languages, right? So you don't have to type the type that spells out what that thing is. Oh, right. And then you need to put it in the variable name. Microphone number one. Yeah. In one of your slides, you made the claim that a functional programming lends itself to proving. How would you actually do this? Good question. That's another talk, right? In practice? So there's various ways of doing that. So first of all, as you saw, right, Haskell program is a bunch of equations. So you can use algebra as a mathematical technique to reason about functional programs. So first of all, going to the abstract aspect of that question, which is something, well, you can sort of do it with your Java program, but it is much harder to establish an algebraic way of talking about Java programs. There's also plenty of tooling available to write, to prove aspects of your programs in functional languages. Starting with a classic tool called ACL2, we can talk on something called Idris. So there's a newer breed of functional languages where you can put more proofs into the types of your languages. So it just turns out, it tends to be just an order of magnitude easier to prove properties of functional programming because you can use algebra and equational reasoning as you would about Java programs. Does that answer your question a little bit? A bit. But I think Idris uses dependent types and doesn't, isn't it possible to use it in imperative programming as well, maybe? I don't know. So is that specific to functional programming, dependent types, or could it be used in... It is. Even the way that Idris talks about imperative programming is functional, right? Using monads, by the way. So there is that, and there's this whole spiel about reasoning about effects. But the thing is, side effects, you have an imperative programming. They don't make it impossible to reason about programs, but they make it much, much harder. And so in a functional program, in a proper functional program that doesn't crush your soul, you tend to have large parts that are purely functional and that allow functional, that allow equational reasoning. And you have smaller parts that might be a little bit more difficult that are about the interaction with the imperative environment. Also the thing that we did with a type system, you know, you remember, first we had the list and we had the Q-time limit in the middle, and that was an illegal state. And so we changed the type system to disallow this. And so actually already the compiler tells us, hey, this is forbidden code, right? And it's not syntactically wrong, but it's semantically wrong. And that's what is also like a weak kind of validation or verification in my opinion. Yeah. So we could talk about this all day. Sorry. Another question from microphone number two. I noticed that you didn't present any mechanism to hide your implementation or to make things private, things that you can do in C++. And I don't miss those mechanisms, but I would like to know your take on why, I think you don't miss them. So why do you don't miss them either? No, they exist in functional languages as well, right? And so the mechanisms that you're familiar with, private things, modules, functional languages tend to not use objects and classes for modularization. I think that's the primary difference. But functional languages tend to always have mechanisms for doing that. Languages differ between languages, so it's difficult to talk about this in a talk. We could have told you how to do this in Askel and write a module and hide things, but would have put more codes on the slides. And the other aspect is that you don't really have to hide things because everything is pure. So if you call this function, I don't care, you know? You can't destroy anything. Whereas in object-oriented programming, you have this change my object to really bad something, you know? And you don't want anybody else to call this because it will really break things. And in functional programming, chuck in some variables, get something out, do this as much as you want. I don't care. That last one is the take I love. I endorse fully. Microphone number three. You had some slides on the importance of communication. I have a hard time to see myself communicating with business people using Haskell code. How would you do this? How would you do the communication with normal people? We cleaned it up somewhat, but this actually happened. So it's sometimes a little bit of a process to get there. And sometimes, what you noticed maybe in the code with the routes was that playing with the Haskell code yielded domain insights that you could have also explained to somebody in a meeting. Without showing the code. And so the communication goes through the Haskell code. Maybe it doesn't happen by the Haskell code. But all I can tell you is that that actually happens. We sometimes communicate with clients showing them code and talking to them about is this really what you're doing? Is this what your domain is like? That happens. It happens to me as well. So it depends on your clients. They need to have a bit of resilience. So they can accept that they wouldn't understand everything. But if you talk them through and say, look, here's this and this goes in and that comes out and what do you think about this? And then so you just not throw the code at them, but you have informed communication. This can also be contractually enforced. And I remember one instance where we did that. So four reasons were that AANA had to do the same understandings. You
 So, our first talk is going to be presented by two speakers, Michael Schreber and Nicole  Well. Michael is the CEO of Active Group. He's been developing software and teaching  programming for over 30 years. And Nicole is an independent software developer focusing  on domain-driven design and event streaming. And she's been organizing software craftsmanship  conferences. So please give them a big round of applause for this talk.  Good morning everyone. This thing is on.  Hey, it works. Excellent. Cool. So, sole crossing code. I think before we say farewell, we should  think about what it actually is. And so I thought I'd maybe get a presentation first.  There we go.  So, okay. So first maybe we should talk a little bit about what sole crossing code is.  And so I brought something for you, for your entertainment. And here we go. This is some  code I found in an eclipse tutorial. If you know a little bit about eclipse, you can see  this by looking at this eye thing here. Yeah. And this actually, I mean, I have no idea  what this does. You know, you have this adapter factory, which is really like okay. And then  we get an adapter and there's lots of stuff going on. But what actually is this doing?  So there's to do, okay, this gives a hunch that this might be this famous to do example.  But then I have no idea what's happening here.  But maybe that's just eclipse, right? And eclipse, everything is an adapter for everything  to do something else.  Okay. Maybe. So, okay. I had expected you to say something like this. So I thought I'd  bring another example. And this actually is from an open source project. And this actually  is a native query interpreter initiator. I also want an interpreter initiator. Who doesn't?  And also it's a session factory service initiator. Wow. I'm getting impressed. So, and then  it also does lots of stuff. And then, okay, we have initiate service. And then we have  another initiate service. And then at the end, wow, we have this get service initiated.  Wow. Okay. So, fine.  But I mean, that's just a bunch of kids doing open source software, right?  Yeah, this is those are all hobbyists, right? So, I mean, what would you expect from something  like that? Right?  Okay, fair enough.  I brought I brought a professional example. Oh, I see. Okay. Everybody stand back.  So here's a here's a professional example. So this is from a system that does queries  of some sort. I think there's a shape and translation from German to French to English  and me or somewhere. So you can see that it does either full text search or it does non  full text search or something like that. And so obviously in the initialization of some  C++ class, it checks that flag and it instantiates some object either to the full text variant  or the non full text variant, right? And you would think this is object oriented design,  you just go and call methods. Yeah, that one instance variable that you have there.  If an else is so object oriented. Yeah, well, that's just the constructor, right?  This is not the bad part. The bad part is that every single method that actually does  something like this one looks like this, right? It checks that flag again. And it either calls  full text research, which is I guess also has something to do with full text search.  You can see that there's lines commented out and nobody nobody remembered to leave leave  a comment as to why it's commented out. And you can see that this code is really fragile,  right? If you want to maintain that kind of code, every method looks like this. You always  need to remember to check that flag before you do anything to be sure that, oh, I'm here  or I'm there. Okay. Yeah, so I mean, okay, so the fact that somebody uses an object oriented  programming language does not necessarily imply they actually understand what object  orientation is all about, right? So maybe they are just crappy programmers. Okay, so  they happen to use this and then they mess it up on the way, you know, but non crappy  programmers can produce crappy code. And now you're getting me confused.  I think you I have you have another example. Yes, I have a much better example here. A  real object oriented example. So this is finance finance, right? So here we have options. In  this case, just call options. And so the the financial guys want to talk about those options,  but there are so many different kinds of options. So they cannot talk about each of them individually.  And so they want to group them together. In something they call a basket. So up here,  you can see this basket. And it contains Google and Facebook because they are sort of like  the same, you know, so they just group them together in this basket. And then they want  to talk about properties of this basket of all those options that are contained in it.  And for example, here, they implement this market data. And so this is standard object  oriented business, like everything is a class, right? And there we have two methods in there  because that's also standard object oriented business. We have a class and then we have  methods in there. And one of the first method get spot just gives us the spot price. So  all of these options have a number in the real world. And that's why they number this  here. And for the fun, they call this sick of them. I've no idea why this seems to be  a French word for I don't know what it means. But yeah, just go with this.  So this maturity thing, that's the date at which point the option expires.  Yeah, so that's for the volatility. So you get the volatility for an option. An option  is defined by the underlying asset. And by the date, it's due and also by the price it's  supposed to have them. And that's what is encoded here. So we have the option with this  long and then we have the maturity, which is a point in time. So we can properly use  a double for this, I think. And then we have the strike, which is a price. And probably  some of you know that it's not a very good idea to deal with money in terms of doubles.  But on the other hand, it's fairly common in banking. So let's do this here as well.  Okay. Fine. So yeah, that's it. Yeah. And then what they actually want to do, so they  don't only want to look at the world as it is, but you know, those guys with the suspenders,  you know, they want to analyze and see what might happen if something would happen, you  know. So they want to play what if games. And for this what if game here, they take  the spot price, and they actually want to shift it. So they want to say, what if the  spot price were different? And what would happen then with my options, right?  And here they just, you know, so if you want to modify something in object orientation,  you write a derived class. And this is the derived class, spot shifted market data. And  this derived class overrides the get spot method. And it takes the value of the parent  class and then multiplies it with a factor. Okay. Sounds straightforward so far. And  then of course, they don't only want to multiply this with a factor, but they also want to  do other modifications. And they want to be able to do all these modifications without  recompiling. So they want to play around with these and they don't want to recompile their  code every time they change something. So they want to have a dynamically configurable  code base, so to speak, or dynamically configurable market data. And if you look this up in the  object oriented literature, you come up with the decorator pattern. And so the decorator  pattern is something that allows you to dynamically modify your code. So you have a component  and then you derive a decorator and the decorator as a delegate to something else you want to  plug in basically. And this is how they implemented the delegate. So they wrote the decorator  as a derived class and then they have their, they have the real object in there. And for  the get spot method, here they just ask the get spot method of the underlying object.  Fair enough. And now, going back to the baskets where I started out initially. So what they  did in this one derived modification here, they multiplied with a factor. And now in  the basket, they get here, they get a bunch of options, say, or a bunch of assets. And  now they want to calculate this for all of them. And they go into this recursively. And  it's very hard to see here, but what actually happens is they go into this recursively. And  do this modified operation for all of them. And because of late binding, it happens that  they keep getting through this upper method again and again. So adding the factor again  and again. And of course, they did not figure this out by looking at the code because, like  I said, really hard to understand. And of course, this is all just small snippets of  the code, but this is the essence. But they found this because the values were incorrect,  right? And so what they did is they compensated for this. And for example, here is the most  interesting part, I think, does the first market data derive from the second one? So  they check whether they have this chain going on and then they do something differently.  Well, I mean, this is production code, right? And this is still in operation. And probably  this method by now is like hundreds of lines long because they have so many edge cases  they need to compensate for. Well.  Yeah. I can imagine that. But I mean, it's obvious they just shouldn't have done this  in C++ or using object-oriented programming, right? So do you have a better suggestion?  Oh, absolutely. We have slides on this.  You have slides.  So people should have used functional programming, right? Which is great because...  Oh, how could I forget this? Of course, you would say that.  I'm a functional programming person here on stage. So functional programming has all these  advantages, right? You can have immutable data. Immutable data means you have less coupling.  You don't have these complicated effects going on that you saw earlier, maybe. You can...  Functional programming is very close to mathematics. So you can apply formal verification.  Isn't that scary?  Yeah. And you can use all these great mathematical things in there. You can have catamorphisms.  You can have bifuncters. That's my new favorite thing. Monats. Monatic profuncters is also  something that we've been using lately. That's great. Clice the arrows. There's all these  wonderful things in functional programming and they solve all of these problems, right?  Yes. I could...  Why are you laughing? Who's laughing?  I should have imagined you saying something like this. But have you ever considered that  you're tackling the problem from the wrong angle? I mean, you and your horrid of IT tech  nerd, you're sitting in your cave, hacking away, having your hood over your head and  just sitting there and hacking and hacking.  So that problem solved.  And I mean, really, just throwing tech at the problem is not a solution. It's actually  part of the problem.  But we're a producing software. We're producing tech, right? Have you gone through this thing  here? There's tech outside everywhere. How do you make that?  Probably not by sitting in the corner and just writing, hacking away.  Okay.  Have you considered that there is more to it? That it's not only just tech that you  need to talk to each other?  Mm-hmm.  Yesterday, I saw this robot walking around in a circle and it said, I need new code.  Please talk to me, right? This is something like this.  Okay.  So we need to talk to each other. It's not only tech. Tech is nice and everything.  So where's... Do you have a pattern manual for that?  A pattern manual. Yes, of course. There are talking patterns, actually, for people like  you.  Okay.  So, go ahead.  So...  Educate me.  Okay. So, I mean, there were many approaches over the years, right? Some approaches were,  for example, looking at agile software development, you know? And it says individual and interactions  over processes and tools. Tools. Tech.  Okay.  So, let's talk together and let's figure out things.  Okay. Well, but it does say working software also, right?  One of four, you know, says working software because, of course, we also want working software,  right?  Yeah.  I mean, just talking and no coding is also not the answer.  Yeah.  Anyway, so last year we were at this conference, right? And you were probably talking to somebody,  but I actually attended the keynote and it was by somebody who talked about what worked  and what were the ongoing problems in software engineering. And this was an agile company,  right? They do everything in an agile manner. So, supposedly, they communicate all the time.  But still, when they look at where they spend all of their time and all of their work and  effort, they say that they still spend 53% on maintenance and complexity and not on  new features or... I have no idea what that professionalization thing is, actually, but  it takes up 18%.  Looks nice.  So, let's get back to the technical problem, shall we?  Yeah. So, I mean, we already saw this, right? In the market data example. I think much of  this maintenance and complexity problems is caused that we are in a world consisting  of objects and so everybody jumps on this object-oriented bandwagon, right? And what  they actually end up with is something like this.  Okay. And this is sort of... Like, not helpful.  So maybe... But I would like to explain this maybe in a different way. So, modern object-oriented  programming... Well, you can all laugh at that slide before, but we really need to understand  the problem, right? The technical problem. Is this, right? So, at the heart of modern  object-oriented programming, something called imperative programming, where all these objects  that you showed on the previous slides, they have what's called encapsulated state. Okay?  There's some state in there. And what happens is the world progresses by all these objects  sending messages to each other. And as a result of a message, some code gets executed that  modifies that encapsulated state.  Now, the thing was... I mean, object-oriented programming was originally developed to support  simulations of the real world. And the problem is that the real world just does not work  like that. The real world is not a bunch of objects sending messages to each other. So,  one simple example that maybe can help explain that is there is an elephant... Speaking of  elephants, right?  Yes.  A great elephant slide. So, there's an elephant, and the elephant comes in from the jungle  and walks into some kind of room, right? And the object-oriented model for this is, well,  all the entities get models, get objects. So, the elephant has an object, the jungle has  an object, and the room that the elephant enters has an object that represents them.  And you have the sequence of method calls or message sends that tries to reproduce that  sequence as well. You know, the elephant exits the jungle, and the elephant enters the room,  right?  The problem is that the exiting of the jungle and the entering of the room are one and the  same act. So, the real world has dependencies. It's not just a bunch of isolated entities  that are sending messages to each other. Things hang together in the real world. So, I think  a more useful model for thinking about programs and how programs should model the real world  has to do with... It should really go through the way that we perceive things. So, if you  watch a soccer game these days, there's lots of objects that you see, right? So, you see  22 players, maybe. You see a ball. You see the referees. And you see lots of people in  the audience, and they all move. Now, so they all change their internal state if that's  the model that you use. Now, if you want to know what's going on in the football field,  you need to observe all of these changes. But do you know what the object-oriented model  is for observing changes? Something called the observer pattern, which means that you  register each of these objects and tell them, well, if anything changes with you, send me  a message. You know, do your ball, send me a message. If you move, you know, you do that  with all the players. Supposedly, you do that with all the 20,000 audience members. And  so, and of course, when you leave the stadium, you all send the messages, oh, no, I'm no  longer interested in what you're doing, right? The world doesn't work like that. It has another  problem is that all these messages will arrive in some sort of sequential order. And that  also would mean that with all of these objects moving around, we would observe inconsistencies  all the time the same way that we observed it with the elephants going into the room,  right? If you remember, there was an inconsistent state in the middle here, which was that after  the first step, the elephant is, for a brief amount of time, is nowhere. It has exited  the jungle, but it has not entered the room yet. And the same is true, of course, if we  have many moving objects, but yet we never observe, like, one person getting up and suddenly  appearing in another place or two people appearing in the same place at the same time. And that's  because our perceptive apparatus creates consistent snapshots of what we observe, right? We look  at something and it gets stored in memory and we can think about it for a little amount  of time and analyze what's going on. And so, and of course, you know, we remember things  that were in the past, which is also something that an object-oriented model cannot do. So,  I think there's fundamental problems with this object-oriented model of programming,  and that's one of the fundamental things that leads to that sole crushing code that we've  been talking about.  Yeah, that actually reminds me of a very interesting thing that lots of people are using, and that's  in the UI, and it's called the MVC pattern or model view controller. And if you have  ever worked with this, you can see here that this all goes in circles and you can go in  any direction and then you end up here again or you go this way around or anything or follow  this dashed line and so you can go from anywhere to everywhere. And this leads to the obvious  problem that if you have changes in the model and changes in the view, they need to hopefully  be corresponding or maybe not. And what do you do about this? So, what you end up with  if you do this enough and if you aren't very, very careful, you end up with this, right?  Certainly my MVC programs have always looked like that, right?  Yes. So, it feels really familiar, doesn't it?  Yeah, yeah, it does.  And I think that's also what Alan Kay was talking about back in the day. So, this is  a quote from 1996, but I think the paper just appeared then, but the original quote is much  older. And so, he said, okay, OOP had those motivations that we described here, but eventually  we need to overcome this model and we need to find something better and eliminate it  altogether is what he says here.  Okay, but that never happened, right?  No, I don't think so.  It never happened. So, if these days if you look for examples of how object-oriented programming  works, it always is about encapsulated state that Alan Kay wanted to get rid of. So, I  think that's the first thing when I searched for object-oriented examples was something  with students and you can immediately see that a lot of attributes that you have there  go through some kind of, some method that modifies them.  My favorite one is that you have the student and you can set the grade point average of  the student. So, you can just, yeah, so if you're not happy with the grades that your  kid is getting, you just send the object a message. You know, get a perfect GPA there.  So, and let me reiterate, Nicole, of course people should have used functional programming,  which has all these simple languages.  Yes.  That's complexity, higher productivity, less bugs. You know, we have all these powerful  type systems. We can do property-based testing. We can do, well, it goes on and on. We get  more predictable behavior. Generally, testing is easier because we don't set up and tear  down methods. You get lower couplings. You have fewer dependency cycles. So, I didn't  even say monad, right, here in this list. So, you get all these concrete, you get all  these concrete advantages from doing functional programming, right? So, that's what people  should do to solve those problems.  So, do you remember Fred Brooks? He said, there is no silver bullet.  Okay.  So, what do you say about that?  Fred Brooks is an old guy, right?  Yes.  And what about you?  Yeah, I guess I am too. I'm getting there. Yeah, well, so, Fred Brooks said that, but  he's an old guy. So, let me get you one example of why that maybe is not true. So, in the  early 90s, actually, there was a big study conducted by the US Navy on the effectiveness  of different programming languages. And they had one set problem that was about determining  the regions of influence of warships. And they had different teams write solutions for their  problem in different languages. And what they ended up doing is also, is they gave that  also to people who were using functional programming specifically in the Haskell programming language,  which was still pretty young back then. And you can see, well, the solution in Haskell  is much shorter than the solution, you know, C++, definitely less than 10 times as short  than the C++ solution. I think Java wasn't as big then. But I think the factor would  also be around between 3 and 10 somewhere. Also, what's maybe interesting is that there  are two Haskell solutions, one at the top and one at the bottom.  Probably they just split the code so the numbers look nice.  Yeah, yeah, you would need to add them up. That would be interesting. But what they did  is they had a Haskell expert write a solution. And then they also gave the solution to a  student, I think, who learned Haskell for two or three weeks, and who also wrote a solution.  And if you look at development time, so somebody took 10 hours and somebody took 8 hours. And  the 8 hours is the student. That's because the Haskell expert tried to put many interesting  flourishes and super cool programming techniques into the program. But the student was actually  doing pretty well. So if that is not a silver, if that's not what a silver bullet looks like,  I don't know what would.  Okay, so the Yale study, right?  Yeah.  They got a fixed set of instructions, and they just had to code those instructions. Do I  remember that correctly?  Yeah.  Okay. So do you ever experience that in the real world, getting a fixed set of instructions  from your client, and then just implementing this? And they never change their mind. They  never come up with new ideas. They never, like, say, oh, I forgot something. I actually  don't experience this.  Let me think about it. Maybe you can move on.  That's what we need to consider as well, coming back to the elephant, right?  Okay.  Talking to each other. Everybody has different ideas.  Now, you can start with that agile stuff again.  Everybody has different ideas when they look at something, and everybody describes things  differently. And so what we need to do is to figure this out together, coding a bit,  talking a bit, talking a bit, coding a bit. And so this needs to go hand in hand. And  this is sort of agile. Agile doesn't mean scrum, and standing in a circle every day  or something. Relax, okay?  So personally, I like to communicate with code.  Yeah.  You can do that, too.  So that makes me think of an example that we were working on in our project.  Oh, cool.  A semiconductor factory.  Wow.  So real stuff.  This was serious business.  I see.  Anyway, so when we started this, I don't know, you all know this, right?  When we started this, I thought, well, a semiconductor, the way it gets made, there's a big machine.  You put in a piece of silicone, and you go like this, and junk, and out comes a microprocessor.  And it doesn't really work that way.  One of the reasons is just that a modern, the modern chip consists of many layers.  Another one is that there's just many different production steps that are necessary for making  even a single layer.  And some of the machines that make a layer are so expensive that you can't just make  an assembly line.  And also a lot of things break all the time in a semiconductor factory.  So it makes no sense to just have an assembly line and push things through that, but things  just move around among the different machines in a semiconductor factory, right?  And so what's important is that each chip or each wafer undergoes a sequence of steps  in the factory, and that needs to be managed.  And those steps, it's typically for big microprocessors that might be like a thousand steps.  So you need to manage something that's called a route, which is, well, just a sequence of  operations.  And now here's a bunch of Haskell code.  Haskell is great because the programs are so short that they fit on slides.  But if there's something unclear about that code, then I invite you to interrupt me and  ask.  So first of all, you can read that declaration at the beginning, says data operation.  And that's just a simplified data type that describes what an operation would be.  And it says, and you can read that vertical bar as or.  So it says an operation is either track in or process or track out.  And tracking in just means putting a wafer into a machine and processes.  You do something inside the machine and track out as you take it out of the machine.  And then the next thing is that a route is just a sequence of operations.  And these brackets that you see there, they mean list off.  So what it says is a route is a list of operations.  And down here, you have an example for a route, for a very simple route that says, well, one  route, route number one, might be a list of the following operations.  You put a wafer into a machine.  You process it.  You process it some more.  And then you take it out again.  There so far?  Everybody nod?  Everybody who's still awake nod?  Okay.  So don't be afraid to ask.  So one thing that you do is when you have data types, as you just saw, is you define functions  on them that describe some aspect of what happens in a FAB, in a semiconductor factory.  So in a FAB, what happens, of course, is you need to execute the next step, the next operation  that happens as part of making a semiconductor.  And for that, we're making a function called route head, the head of the route.  And what you do is you write a type signature.  And type signatures are very good for communication, actually.  So you put in a route and you get out a single operation.  And then you write equations that describe what that function would do on different aspects  or different classes of input.  So in this case, you remember a route was a list of operations.  And lists, there are two different kinds of lists.  One type of list is the empty list.  And the other kind of list is a list that has what's called a head or a first element  and a rest.  And because there's two kinds of lists, you write two equations.  And so that's why you see two things where it says route had something equals to something  else.  And the first equation is for the empty list.  This is why you have these two empty brackets.  And the second one that says, well, it's a non-empty list.  And the first thing in that list is some operation op.  So this is something called pattern matching.  You match this onto the actual list that you see.  And op then gets bound to that first operation.  And we don't really care about what comes after that first operation.  And so the second equation is pretty clear.  If you want the head of a route that is not empty, you just take the first element of  that list.  OK, so far?  And the other equation says, well, what do we do with an empty list?  An empty list does not have an operation.  So you are saying you're into the second slide of your beautiful Haskell code and you already  don't know what to write there?  Well, so we're communicating, right?  OK, OK.  So you're talking, you're talking to some of the expert and you say, well, you have  got an empty route.  What's the first operation of an empty route?  And he says, well, empty routes, they don't really have a first operation.  They only maybe have an operation.  And sometimes they don't.  So for that, we can create a data type that says that something might sometimes be there  and sometimes it's not.  And we'll just call it option.  Are there any Haskell programmers in this room?  Oh, OK.  So this is built in, of course, as the maybe type.  But I'm just making a separate type called the option type.  And that says, well, the A says it can be anything, right?  Anything in option A means it can either be there or not.  And for that, it has two constructors or two different classes of maybe objects.  And one are called the sum objects and the other one are called the none objects.  Maybe we'll start with none.  So anything can be a none.  It just says that anything is not there, right?  So anything can be of type option of A. And it means that something is not there.  And that is the type of that particular constructor.  The other constructor says, well, that thing actually is there.  And so the constructor has to accept something of type A and then give us something of type  option of A.  OK?  So you're saying it wraps this object?  Yeah, it wraps the object.  And so if you're not a Haskell programmer, but maybe an F-sharp programmer or an ML  programmer, then that is what it looks like there.  And I believe it's even built into Java these days, something called optional.  So and now that means we can change our route head function a little bit because our first  attempt didn't work out.  And instead of saying, route arrow operation, we write route arrow option operation.  It may seem trivial to you, but it already communicates a tiny little bit of something.  So and then we can write, route head of the empty list is none.  So there's no head of the empty route.  Or if we have an operation coming out, we just write some in front.  And so if we use that example route that you saw earlier, where R1 was track in, process,  process, track out.  What we get is sum track in.  So that type communicates a little bit of what we do.  Because always, it's already calling the shots.  Very good.  The next thing that we might want to do is we don't want to always know only the first  operation.  We also want to know what happens after that.  So we can use that option.  And we already know that, of course, an empty route will not have something coming after  that first operation.  So we could write another function called route advance.  And it takes a route as input.  That's to the left of the arrow.  And it gives us both an operation and a route.  That's why there's these two things in parentheses with a comma in between.  So that's a tuple.  So it gives us an operation and a route.  But only sometimes when that actually exists, which is why there's an option wrapped around  that.  So what we want to do is if we take our route number one, we want to split it into that first  operation and a list of the rest.  So it should split out the track in and then give us a list of the remaining or a route  of the remaining operations that are in there.  OK, so far?  So it gets technical.  Don't be, does anybody have a question?  OK.  So don't hesitate to ask.  I'm looking at the clock.  So and then this is actually pretty easy to write now.  Again we need to make two equations because a route is a list and lists always need two  equations.  So we can say route advance of the empty list is none and route advance of up and the rest  is we just return a sum of up and the rest because the list already splits exactly along  the line that we wanted to between the first and the remaining elements.  So this is just very simple code or at least a short code that communicates what routes  are.  Right?  I see.  So if I remember correctly, I mean you said you put the wafer into the machine and then  it processes it.  If I remember correctly, some of these processing steps can be chemical reactions or something.  And so it might be the case that they must happen in a certain amount of time or something,  if that's true?  Yeah.  OK.  So what we could actually do is we could model something like this.  Yeah, I sneaked at your part of the slide so I chucked this in.  So what we actually could do is we could model something like those three steps here need  to happen together in a set period of time or something.  Yeah, so the chemical reactions mean that your wafer might go bad.  Yeah.  If you start the sequence of steps and you don't finish on time, then your wafer goes  bad.  Like etching and washing for example.  If you etch too much then.  Yeah.  OK.  That's always a problem in existing systems.  Oh, is it?  OK.  Ah, so.  Oh, so maybe I can try and see how I can model this into your existing code.  OK.  Cool.  So let's have a look.  So what we first need is we have this route element here with this operation, right?  And now we need another representation for a route element.  And let's call this route QT zone for Q time zone.  And there of course we have the duration.  That means the amount of time.  This step needs to be finished in or this sequence of steps needs to be finished in.  And then we have this list of operations here.  We saw this before, right?  The list of the operations.  And then what this gives us is of course again a route element.  So we can combine like ordinary steps like putting the wafer into the machine.  Doesn't matter how long it takes.  Maybe it blocks the machine.  But other than that, no issues come from that.  But if we do the etching and the washing, for example, we would need to have a Q time  zone because we need to restrict the time that this takes in conjunction.  Right?  Is that correct so far?  Yeah.  Good.  And then if we look at our example, this is the previous example we had here.  We could create another example.  Where is my there?  R2.  And here we have a route Q time zone.  Say it may only take five, whatever seconds say.  And then we have two processes here that need to be finished within five seconds.  And then we do the track out again.  Okay?  So far so clear?  Good.  And then if we look at this and we discover that here we have this route element list  and here we have this operation list, this is actually sort of similar, isn't it?  So maybe we can make something out of this.  And maybe we can actually turn this down here into route elements as well.  Oh.  So that's what you were doing before, right?  Before there it said up there it also said list of operation.  Up there?  Yeah, up there when it said type route, when you started, my code.  My code had route equals list of operation.  Right?  And now you did the same thing.  Oh, yes.  Yeah.  Right.  So now it's the same again.  Okay.  Right?  So it's both route elements.  Yeah.  Good point.  And now if we look at this again, so maybe this actually means that this year is not  just a list of route elements, but maybe this is actually a list of routes.  It's actually a route down there.  So actually derive some information here from the code so we discover that our route QTime  zone actually contains a route.  So what are?  So if we look at this here, what we then can do here with this route element, so here we  could plug in any route element.  Right?  For example, we could plug in a route QTime zone, which is also a route element.  So coming from this example here where we have just a flat list that just contains some  route operations and a route QTime zone and then a route operation, we could also stack  them into each other.  So a route QTime zone could again contain a route that contains a route QTime zone.  Yeah, that's pretty cool.  Do you think that would happen in this pre-reality?  Yeah, that's pretty cool because now we can nest QTime zones.  And that's something that occurs in reality.  Oh, really?  Does it?  Oh, cool.  And so your model has suggested that, but it's something that our old IT systems based  on object-oriented programming couldn't model.  That's pretty neat.  So now I understand why you're aiming at functional programming and saying that you can model  things better with it.  Yeah, and this is pretty cool.  So we discovered this in the code and then we were able to get back to the business people  and check back with them whether they would actually see this in practice and whether  it's a valuable addition here.  And we discovered that just from looking at the type information we had.  Yeah, and then we can continue this.  And because now we have this list of route elements down there, we could actually say,  oh, yeah, a list of route elements.  We know what that is.  This is actually a route.  And now we go one level up.  So whenever we learn more about routes or whenever we change this here, this route thing, it  will automatically be reflected in here because we abstracted it.  And that's what functional programming is all about, abstracting things and figuring  out what the common parts are.  Right?  You noticed you're agreeing with me.  Very good.  Excellent.  So, and now we can also, of course, check how our functions will be modified because  now we need to go to all of our functions and see whether they still work.  And here we have this route head and also route element head.  And now we need to extend this because the route element head works on the route element.  And now we have a new route element, which is the route queue time zone.  And of course, if we want the route element head of the queue time zone, this is, of course,  the head of the containing route.  And we have this neat function up here already, route head, which gives us the head of the  route.  And so we can just reuse this here.  So even this has become simpler for us to implement because we have discovered that  there is a route in there instead of just a list.  So no special handling.  We can just revert to the standard function we already have.  And if we look at the route advance, so if we want to proceed our route to the next operation  and proceed to the next step, then of course we also need to add this here, the queue time  zone.  And now the question is, what happens if we advance into a queue time zone process?  Because somehow we need to keep track of when does it need to be finished?  So initially we said, OK, it may only take X time or D time.  And now we need to keep track of whether this time is already taken up or not.  And so in this case, what we actually do is we need to add another route element.  And that's a route queue time limit, which defines when a started operation needs to  be finished.  So it has an actual time, which is the point in time, like now duration or something, just  the finishing point in time.  And then it's just the same as the route queue time zone.  So this limits our process up to this endpoint of time.  And now we can implement our route advance because whenever we have a queue time zone,  that's where we didn't know what to write before.  So whenever we advance this route, then we know that we need to come up with a route  queue time limit here.  And whenever we have this queue time limit and we advance over that one, then we know  that we just need to basically behave like before.  We need to split this up and also keep our time limit, of course, and then just proceed  into this limited while keeping the time limit.  And here, if we start this out, then we need to determine the endpoint.  So we take the current time, which we now need to pass in here at the top.  So we take the current time, add the duration, and then we know when we need to be finished  with this process.  And then in here, we just work on every step while keeping the time limit.  So your code suggested that there was a gap in your understanding of what needs to be  represented, right?  Yes.  So I didn't know what to implement for the route advance.  And now I know that, yeah, I can handle this.  So watching this, I'm thinking that there's still a little, if I look at it with the eye  of a domain person, I think there's still a little problem in there.  Which is, yeah, if you look at this, remember a route element is something that can occur  anywhere in the middle of the beginning at the end of a route.  So it has these three things.  Obviously, we can have queue time zones anywhere.  We can have operations anywhere.  But the thing is, we can only enter a queue time zone when it's at the beginning, right?  Oh, I see.  So now...  So you mean here we could have a random list in a random order?  Yeah, that's a good point, actually.  So this suggests that the queue time zone has been entered because there's a route queue  time limit.  But there's still an operation there in front of it.  Okay, yeah, that doesn't make sense.  Yeah, that makes no sense.  So if we could go back from the domain knowledge to the code now a little bit, we could refine  that type further and we could pull out the queue time limit from that type down there  because these are all the things that occur in the middle of a route and pull it up to  a top level type and introduce an intermediate type that distinguishes between what's in  the middle and what's at the beginning.  Oh, I see.  Yeah, that's neat.  So what we now have is we have this back and forth between the code which yields insights  about the domain and the domain and from the domain back to the code.  We can play that game.  We can use the code for communication.  Yeah.  So that's what I intended.  So that you understand this.  Yeah, so that code no longer crushes my soul.  Excellent.  So I can say that.  Yeah, right.  Same here.  So, cool.  Okay.  So that's what the point we wanted to make.  So if you take functional programming and if you add communication and discussions and  this going back and forth and learning from both sides and enriching both sides with the  information coming from the other part, then you actually end up at a silver bullet.  Everybody's looking confused.  That's a bullet train, a silver bullet train.  Okay, we're done.  Yes.  Thank you.  Thank you for a very entertaining talk.  We have some time for questions.  Q&A.  So if you have any questions, please line up next to the microphones.  We have four microphones spread across the room and we'll start from a question from  the internet.  As an FP beginner with a weak background in math, would it be preferable to learn functional  programming in pure functional language over languages that are multi-paradigm?  So I take that one.  Okay.  So I think the point is that there's many different functional programming languages  and Haskell happens to be what's called a pure one, but there are also languages that  are hybrid between object-oriented and functional programming.  Scala I think is the prime example right now.  And I mean, these are, Scala is a fine language.  The problem is if you want to combine these two paradigms, you typically get something  that's pretty complicated.  So Scala is a complicated language that takes more time to master also because you have  both paradigms available to you at both times, at all times.  It's sometimes, you often get confused about what paradigm you should use in a given situation.  So I think both of us, we haven't really seen the great advantages you get from that  hybrid model.  Right?  I think that's a good reason.  And I think that's a good reason, because if you're a learner in FP and you try to tackle  this with something like Scala, you will inevitably fall back to what you know if you run into  problems.  And so maybe just jump into the deep end and try to swim and see where you get at and get  help on the internet.  Yeah.  Number two.  Okay.  Yeah.  Yeah.  It was a good presentation.  Thank you.  Every time I see some functional programming, it's refreshing and it's interesting.  But the description of your presentation was talking about using functional programming  in IoT.  So there was nothing specific to IoT in this presentation.  There was no interaction with the hardware, no interrupt, handling, no nothing.  How do you handle that, for example?  Yeah.  Good point.  I think we had a bunch of slides on that that we ended up dropping because of time.  But so my argument would be that IoT is the software is the same software is the same  software as any other software.  What's special about IoT is the risk that emanates from IoT, obviously.  So if you do things like, so if you want to do things like interrupt handling, I think  my response to that would be to convert it into functional data structures.  And this gives you a deterministic model for handling that kind of stuff.  So we talked about that.  I think we talked a little bit about the observer pattern, which is analogous to what usually  happens with interrupt handling, which is what you were talking about.  And the way to do that really is to have, of course, you have a tiny bit of imperative  code that hooks your functional code to the hardware or whatever it is, but to convert  your interrupts into a list.  And you can ask, well, actually, it's pretty good at that.  And that gives you all the advantages of functional programming, the testability, the funny, the  funky abstractions.  And you can use that even on the interrupts.  And it turns into software just like any other functional software.  Microphone number one.  Hi.  Thank you for your talk.  I have to write code for microprocessors.  And most of the time, I only have a C compiler.  And if I'm lucky, I get a C++ compiler.  Where can I get a silver bullet?  So the old Haskell compiler used to compile to C. Nowadays, it doesn't do that anymore  by default, but probably you can make it do that still.  I'm pretty sure you can still do that.  Yeah.  But there's a number of functional languages that compile to C. So it's kind of difficult  to give one shot answer.  We've also done a project, for example, where we get a lot of the advantages from functional  programming by writing code in Haskell that generates the C code.  And so it's difficult to give you one answer without knowing more details about what it  is that you're doing.  But there's certainly a spectrum of options available in that context.  So functional programming is pretty concise and pretty compact.  So no one really wants to use large variable names.  And I saw in your examples, like a D and a TTL, RT, and I don't think that there's so  much better than the long versions you showed earlier.  What is your take on that?  Yeah.  So the general...  So I'm also struggling a little bit with this.  One thing is that this was fairly concrete code, right?  But often you go into the abstractions.  And in the abstraction, there it's arbitrary what you have.  So you can use short names because you're not talking about concrete things anyway.  So that's why it's easier to use also more like abstract variable names.  But what I actually do is I also use longer names.  So I would not always use D and RT and something like that to get a better grip on this.  But one important thing you must not forget is that this...  You have a function, right?  And it's two lines, three lines.  And so if you start out and you understand D and RT, for example, from the signature,  and reading three lines of code with a D and a RT in it, it's not that bad, right?  And in object-oriented or Java or whatever, you sometimes have hundreds of lines.  And then you have a D and a RT, and you read this for half an hour, and then, of course,  you forget what it means.  So it's a bit of a balance.  So I would use longer names as well, probably, but sometimes also shorter because just the  code is so short.  Okay.  If I can add one detail is I find myself using longer names in dynamically type languages,  right?  So you don't have to type the type that spells out what that thing is.  Oh, right.  And then you need to put it in the variable name.  Microphone number one.  Yeah.  In one of your slides, you made the claim that a functional programming lends itself to  proving.  How would you actually do this?  Good question.  That's another talk, right?  In practice?  So there's various ways of doing that.  So first of all, as you saw, right, Haskell program is a bunch of equations.  So you can use algebra as a mathematical technique to reason about functional programs.  So first of all, going to the abstract aspect of that question, which is something, well,  you can sort of do it with your Java program, but it is much harder to establish an algebraic  way of talking about Java programs.  There's also plenty of tooling available to write, to prove aspects of your programs  in functional languages.  Starting with a classic tool called ACL2, we can talk on something called Idris.  So there's a newer breed of functional languages where you can put more proofs into the types  of your languages.  So it just turns out, it tends to be just an order of magnitude easier to prove properties  of functional programming because you can use algebra and equational reasoning as you  would about Java programs.  Does that answer your question a little bit?  A bit.  But I think Idris uses dependent types and doesn't, isn't it possible to use it in imperative  programming as well, maybe?  I don't know.  So is that specific to functional programming, dependent types, or could it be used in...  It is.  Even the way that Idris talks about imperative programming is functional, right?  Using monads, by the way.  So there is that, and there's this whole spiel about reasoning about effects.  But the thing is, side effects, you have an imperative programming.  They don't make it impossible to reason about programs, but they make it much, much harder.  And so in a functional program, in a proper functional program that doesn't crush your  soul, you tend to have large parts that are purely functional and that allow functional,  that allow equational reasoning.  And you have smaller parts that might be a little bit more difficult that are about  the interaction with the imperative environment.  Also the thing that we did with a type system, you know, you remember, first we had the list  and we had the Q-time limit in the middle, and that was an illegal state.  And so we changed the type system to disallow this.  And so actually already the compiler tells us, hey, this is forbidden code, right?  And it's not syntactically wrong, but it's semantically wrong.  And that's what is also like a weak kind of validation or verification in my opinion.  Yeah.  So we could talk about this all day.  Sorry.  Another question from microphone number two.  I noticed that you didn't present any mechanism to hide your implementation or to make things  private, things that you can do in C++.  And I don't miss those mechanisms, but I would like to know your take on why, I think you  don't miss them.  So why do you don't miss them either?  No, they exist in functional languages as well, right?  And so the mechanisms that you're familiar with, private things, modules, functional  languages tend to not use objects and classes for modularization.  I think that's the primary difference.  But functional languages tend to always have mechanisms for doing that.  Languages differ between languages, so it's difficult to talk about this in a talk.  We could have told you how to do this in Askel and write a module and hide things, but would  have put more codes on the slides.  And the other aspect is that you don't really have to hide things because everything is  pure.  So if you call this function, I don't care, you know?  You can't destroy anything.  Whereas in object-oriented programming, you have this change my object to really bad  something, you know?  And you don't want anybody else to call this because it will really break things.  And in functional programming, chuck in some variables, get something out, do this as much  as you want.  I don't care.  That last one is the take I love.  I endorse fully.  Microphone number three.  You had some slides on the importance of communication.  I have a hard time to see myself communicating with business people using Haskell code.  How would you do this?  How would you do the communication with normal people?  We cleaned it up somewhat, but this actually happened.  So it's sometimes a little bit of a process to get there.  And sometimes, what you noticed maybe in the code with the routes was that playing with  the Haskell code yielded domain insights that you could have also explained to somebody  in a meeting.  Without showing the code.  And so the communication goes through the Haskell code.  Maybe it doesn't happen by the Haskell code.  But all I can tell you is that that actually happens.  We sometimes communicate with clients showing them code and talking to them about is this  really what you're doing?  Is this what your domain is like?  That happens.  It happens to me as well.  So it depends on your clients.  They need to have a bit of resilience.  So they can accept that they wouldn't understand everything.  But if you talk them through and say, look, here's this and this goes in and that comes  out and what do you think about this?  And then so you just not throw the code at them, but you have informed communication.  This can also be contractually enforced.  And I remember one instance where we did that.  So four reasons were that AANA had to do the same understandings.  You
35c3-9812-a_farewell_to_soul-crushing_code_0_59.png 35c3-9812-a_farewell_to_soul-crushing_code_60_599.png 35c3-9812-a_farewell_to_soul-crushing_code_600_1367.png 35c3-9812-a_farewell_to_soul-crushing_code_1368_3323.png 35c3-9812-a_farewell_to_soul-crushing_code_3324_13619.png 35c3-9812-a_farewell_to_soul-crushing_code_13620_15167.png 35c3-9812-a_farewell_to_soul-crushing_code_15168_17795.png 35c3-9812-a_farewell_to_soul-crushing_code_17796_18719.png 35c3-9812-a_farewell_to_soul-crushing_code_18720_19415.png 35c3-9812-a_farewell_to_soul-crushing_code_19416_19679.png 35c3-9812-a_farewell_to_soul-crushing_code_19680_23231.png 35c3-9812-a_farewell_to_soul-crushing_code_23232_24431.png 35c3-9812-a_farewell_to_soul-crushing_code_24432_24575.png 35c3-9812-a_farewell_to_soul-crushing_code_24576_24755.png 35c3-9812-a_farewell_to_soul-crushing_code_24756_24947.png 35c3-9812-a_farewell_to_soul-crushing_code_24948_25223.png 35c3-9812-a_farewell_to_soul-crushing_code_25224_25355.png 35c3-9812-a_farewell_to_soul-crushing_code_25356_25427.png 35c3-9812-a_farewell_to_soul-crushing_code_25428_26819.png 35c3-9812-a_farewell_to_soul-crushing_code_26820_27239.png 35c3-9812-a_farewell_to_soul-crushing_code_27240_28391.png 35c3-9812-a_farewell_to_soul-crushing_code_28392_28535.png 35c3-9812-a_farewell_to_soul-crushing_code_28536_28583.png 35c3-9812-a_farewell_to_soul-crushing_code_28584_28727.png 35c3-9812-a_farewell_to_soul-crushing_code_28728_28823.png 35c3-9812-a_farewell_to_soul-crushing_code_28824_30143.png 35c3-9812-a_farewell_to_soul-crushing_code_30144_30371.png 35c3-9812-a_farewell_to_soul-crushing_code_30372_32411.png 35c3-9812-a_farewell_to_soul-crushing_code_32412_32663.png 35c3-9812-a_farewell_to_soul-crushing_code_32664_33635.png 35c3-9812-a_farewell_to_soul-crushing_code_33636_35087.png 35c3-9812-a_farewell_to_soul-crushing_code_35088_35747.png 35c3-9812-a_farewell_to_soul-crushing_code_35748_38723.png 35c3-9812-a_farewell_to_soul-crushing_code_38724_39935.png 35c3-9812-a_farewell_to_soul-crushing_code_39936_40055.png 35c3-9812-a_farewell_to_soul-crushing_code_40056_41147.png 35c3-9812-a_farewell_to_soul-crushing_code_41148_41231.png 35c3-9812-a_farewell_to_soul-crushing_code_41232_41387.png 35c3-9812-a_farewell_to_soul-crushing_code_41388_41543.png 35c3-9812-a_farewell_to_soul-crushing_code_41544_43739.png 35c3-9812-a_farewell_to_soul-crushing_code_43740_46979.png 35c3-9812-a_farewell_to_soul-crushing_code_46980_48407.png 35c3-9812-a_farewell_to_soul-crushing_code_48408_48851.png 35c3-9812-a_farewell_to_soul-crushing_code_48852_51635.png 35c3-9812-a_farewell_to_soul-crushing_code_51636_54119.png 35c3-9812-a_farewell_to_soul-crushing_code_54120_55703.png 35c3-9812-a_farewell_to_soul-crushing_code_55704_61043.png 35c3-9812-a_farewell_to_soul-crushing_code_61044_68171.png 35c3-9812-a_farewell_to_soul-crushing_code_68172_70895.png 35c3-9812-a_farewell_to_soul-crushing_code_70896_71531.png 35c3-9812-a_farewell_to_soul-crushing_code_71532_71735.png 35c3-9812-a_farewell_to_soul-crushing_code_71736_71819.png 35c3-9812-a_farewell_to_soul-crushing_code_71820_71867.png 35c3-9812-a_farewell_to_soul-crushing_code_71868_72071.png 35c3-9812-a_farewell_to_soul-crushing_code_72072_72575.png 35c3-9812-a_farewell_to_soul-crushing_code_72576_72935.png 35c3-9812-a_farewell_to_soul-crushing_code_72936_73367.png 35c3-9812-a_farewell_to_soul-crushing_code_73368_73619.png 35c3-9812-a_farewell_to_soul-crushing_code_73620_74207.png 35c3-9812-a_farewell_to_soul-crushing_code_74208_74387.png 35c3-9812-a_farewell_to_soul-crushing_code_74388_74471.png 35c3-9812-a_farewell_to_soul-crushing_code_74472_74627.png 35c3-9812-a_farewell_to_soul-crushing_code_74628_77003.png 35c3-9812-a_farewell_to_soul-crushing_code_77004_81935.png 35c3-9812-a_farewell_to_soul-crushing_code_81936_85979.png 35c3-9812-a_farewell_to_soul-crushing_code_85980_86039.png 35c3-9812-a_farewell_to_soul-crushing_code_86040_88547.png 35c3-9812-a_farewell_to_soul-crushing_code_88548_90695.png 35c3-9812-a_farewell_to_soul-crushing_code_90696_90767.png 35c3-9812-a_farewell_to_soul-crushing_code_90768_90875.png 35c3-9812-a_farewell_to_soul-crushing_code_90876_91235.png 35c3-9812-a_farewell_to_soul-crushing_code_91236_91419.png