 Hello, everyone. Thank you so much for being here today. And I'd like to give a special thank you to the organizers that made all this happen today. So we're going to talk about today design my contract in Elixir, where the Erlan moto, let it crash, meets it shouldn't crash. And we're going to see how and why. I am Elba Sanchez. I made this conference with this talk with a partner, Guillermo Ibaran. He could not be here. So I'm going to give it myself. We both work at a company named Bright. It is a company that is trying to reinvent how people commute. And we want to remove 1 million cars from the road by helping people share their own vehicles through carpooling. And meanwhile, we help the environment. Here in Bright, we work on a daily basis with Elixir. So starting with design my contract, how did we get here? Bugs and crashes. We deal with them every day. We try to avoid having them. So who has been on the Elber situation? Only me? OK. What happened to him? Maybe he missed a net cage when he was testing. So did you know that there are really expensive software errors? And they're all also mortal errors, but we're not getting that dramatic. So like the NASA Mars climate orbiter that crashed, it disintegrated when the spacecraft encountered Mars on a trajectory that brought it too close to the planet. What happened in here? The computer software produced output in the United States customary units instead of Newton's seconds in the metric units. So this was all in a contract between NASA and Lockheed, but they missed it. Also, the hetero-thermal 5 opened that misplaced more than 23,000 bags, canceled 500 flights, and may last of 16 million pounds. What happened here was that when they were testing, they left all the data in the database. And when they were trying to do the real thing, the system could not handle it anymore. Also, the Marinius-1 spacecraft that also crashed, the rocket responded improperly to commands for the guidance systems on the ground. Why? Because they missed the hype. That error cost $28.5 million. Also, the Morris worm. It was initially green, not to cause damage, but to gosh the size of the internet, but it ended really, really bad. Also, the night error that cost $440 million, the story tells that the unmaintained code base, it had a bug that they couldn't find because the code hadn't been used for eight years. And also, the Ariane-5 flight 501, who also crashed. And this is the example that we're going to have for this presentation. So in 1996, half a million software error caused the crash of the maiden flight of the Ariane-5 launcher. The rocket was reusing working software from its predecessor, the Ariane-4. But its faster engines exploited a bug that was not found in these models. So 36 seconds before after the launch, it crashed. What happened? The software tried to cram a 64-bit number into a 16-bit space. So in other words, the value that was converted was greater than what can be represented in a 16-bit sign there. So after this, there was no explicit exception handler to catch the exception. So it followed the usual flow of an uncut exception. It broke the entire software, and hence the onboard computers and the entire mission. So this is the kind of trivial error that we all are familiar with, although the consequences for us are not that expensive. So when they did the postmortem about this case, they found that they couldn't blame management because, well, something clearly went wrong. But in this case, the issue was technical. They couldn't blame the language either because they used ADA for this. And the exception mechanism is not the best. But in this case, not all the conversions were protected. They couldn't blame implementation either. What they did was they removed the conversion protection to achieve performance. That was criticized, but it was backed and justified by authority and analysis. And they also couldn't blame testing. But because even if you always can't test more, you can never test all. So what they really have to blame was their reuse specification. What was unacceptable here was the absence of any kind of precise specification associated with the reusable model. So the requirement that the horizontal bias should fit in a 16-bit signing tag was, in fact, a state in an obscure part of the mission document, but it was nowhere to be found in the code itself. So back to the signed by contract, we're going to start with a little bit of theory and history. So the signed by contracts has its roots in work on formal verification, formal specification, and horse logic. It is a formal system with a set of logical rules for reasoning about correctness of computer programs. So all the basics that we're going to need for these presentations are the basis of horse logic. Horse described the use of a representation invariant and abstract functions to prove correctness of abstract data types. We're going to see a little bit more easy this concept right now. So the basics of horse logic. Horse logic is at the core of the deductive approach of the signed by contract. And the central feature of horse logic is the horse triplet. This triplet describes how the execution of a piece of code changes the state of computation. So the horse triplet is formed where P and Q are assertions and C is a command. P is named a precondition and C and Q a post-condition. When the precondition is met, executing the command C, it establishes a post-condition. So horse logic is much more extensive. It provides actions and a lot of inference rules. They're rules for concurrency, procedure jumps, and pointers. But we're going to stay just with the basics for this presentation. So we may want to see the signed by contract versus testings. Contracts as in daily life are a set of specifications that cover mutual obligations, benefits, and consistency constraints that a software system has to meet. Versus testing, the signed by contract falls under the implementation and design. And the unit tests in this case are used to verify that the software works correctly on their sample, on their certain example cases. And with this, it's hard to detect all possible edge cases during development. So what is in fact the signed by contract? In human affairs, this is an illustrated contract between an airline and a customer. So for me as a passenger to get from Colombia where I'm from to here, I had to buy an airline ticket. My obligations as a client was to buy an airline ticket, bring an acceptable baggage at the airport and be two hours before there. And my rights as a client, I get to reach a destination. Also, the obligations for the airline is to bring the passenger, in this case me, to the destination and they have the right to not to carry a passenger who is late or that has an acceptable baggage or that hasn't paid the ticket. So the obligations as a client must ensure preconditions and the rights as a client must benefit from post-conditions. The obligations as a supplier must ensure preconditions and the rights as a supplier may assume preconditions. So the structure of a contract. We have, I have talked now about preconditions and post-conditions. Pre-condition is usually a required clause and a post-condition and a short clause. These preconditions characterizes the responsibility of a program that calls that method and the post-condition characterizes the responsibility of a program that implements that method. So if the precondition is true when a method is called, then the method will terminate returning to the calling program and the post-condition will be true. And if the precondition is not true, when this method is called, then the method will do nothing. So here we have an example in a NIFL version. We are assuming a routine call put that inserts a value in a dictionary and this will be retrievable through a key. We can see here the required clause that introduces an input condition or a precondition and an ensured clause that introduces an output condition or a post-condition. Both of these conditions are a sample of assertions or contract clauses in this case, associated with software elements. In the required clause or the precondition count is the current number of elements and capacity is the maximum number. And in the ensured clause or the post-condition has is the Boolean query which tells whether a certain element is present in the dictionary and an item returns the element associated with a certain key. So back to Ariane's case, this is another piece of NIFL code that where we added a required or a precondition. Here we tell that the horizontal bias should not be greater than the maximum bias. So does it mean that the crash would automatically have been avoided by having the mission use a language or methods supporting building assertion in a design bank contract? That is a bold thing to say but maybe. So how can all these theory help? Well, we as developers seek for several things and one of them is productivity. So this is a really good quote for this. When quality is pursued, productivity follows. We also look for reliability and there are two points that highlight reliability. Robustness, that Robo software acts acceptably in cases it which cannot do what it's supposed to do. And correctness, correct software does what it's supposed to do and that's it. So if I want to check my bank account online, I should be able to do it without that transaction reducing my balance or incrementing it. It should do what is correct and that's it. Advantage of this I bank contract. We have assertions, preconditions and poor conditions that can be automatically turned on or off during testing. These through a simple compiler option and errors might be cut then. The assertion can remain turned on during execution triggering an exemption if it's violated. And assertions are prime components of software. We can automatically produce documentation with this which is pretty cool. There are several languages that support that have implementations of design by contract libraries like JavaScript, Ruby, Java, PHP and C++ and there are other languages that have native support for design by contract like Eiffel, Clojure, Racket or Ada. So how can we achieve something like this with Elixir with the power of metaprogramming? Here's the book cover of the metaprogramming Elixir book by Chris McCord which should be around here anyway. We are going to take leverage of macros. So the Elixir macros give programmers the power to write code that writes code. It provides the freedom to extend the language. But macros give us great power and with great power comes great responsibility. So there are a few rules about writing macros. The first rule is don't write macros. So you may hear this rule loudly when talking to other programmers about metaprogramming. Remember that writing code, that write code requires a special care because with macros programs can be difficult to debug and reason about. And use these when there's a clear advantage over using it over standard functions. And the second rule about macros is use macros like they're free. So this is kind of not the first rule. But if you think about it in Fight Club, what the rule taught us is to break rules. So when we are ready to use macros, we can use them gratuitously. So don't be afraid to use and learn about the macros system. Macros can be used to save time and share functionality in a fun and productive way. So as I said before, macros is code that writes code. Many constructs in Elixir are macros like dev, the if, unless, and the dev models between others. The macros allow domain specific language abstractions and provides the freedom of extending the language as I said before. Also, the Elixir code runs at compile time and can be used to manipulate the language AST. So use appropriately macros often offer effective model composition and code generation techniques. So what some of you may know, maybe the majority of you know that an AST an abstract syntax tree is a representation of code on its own data structure. So the building block of an Elixir program is represented with a tuple of three elements. Where the first element is an atom or another tuple in the same representation. The second element is a keyword list containing metadata like numbers and context. And the third element is either a list of arguments for the function call or an atom. When the element is an atom, it means that the tuple represents a variable. So we have a couple of macros that we use to build the design by contract library for Elixir and the quote macro, which you can get a representation of any expression by using it. So here you see that we do the quote to a function sum with a list of arguments one to three. We get the triplet with the first element, the function name. The second element is a keyword containing metadata. In this case, it's empty. And the third is the argument list. We also use the unquote macro. When quote is about retrieving the inner representation of a particular chunk of code, unquote is used to inject some other particular chunk of code inside the representation we want to retrieve. So here we see that we are trying to, we inject the number into us with the 11 plus and then we get the representation of it with the quote macro and then print it as a string. So back to the design by contract, what we have to do to build a library for Elixir was use Elixir macros to extend the language and add support for the design by contract constructs. We tag the existing functions with requires and short tags that are our precondition and post conditions assertions. And macros manipulate the code inside, manipulate the function body to insert precondition and post conditions inside our functions. So we can see a little example here of how to use the library. We had to redefine the def clause as support to the tags requires and ensures. And we can see here, and we also had to add support to the use clause. You can see here in the short clause that number has to be a certain range and this is a little bit like pattern matching. And this is how contracts looked in the library in the library that we have built. So demo time. What we are going, the example we're going to take here is something as simple as filling up an empty in a tank. So this is the model of the test for our contracts of filling up an empty in a tank. We defined a tank with these parameters initially and use the library. For the function of filling up the tank, we inserted the precondition in the tag requires that the tank is not full at the beginning, that the involve is opened and the tank and the outflow is closed. For the post condition, we have to ensure that their tank will be full at the end and the involve will be closed also as the outflow. And we have the test for that function. The tests are supposed to meet our preconditions. So in this case, this is a failing test for filling the tank because it says that it starts the tank with level 10, which is already full. And for the other function, the empty in a tank function, we require that the involve is closed and the outflow is open in the precondition and in the post condition and ensure close. We make sure that it's empty and the involve is closed and the outflow is also closed. Here we have the command of the empty function leaving the tank at the end in level one, but we all know that for the tank to be, for the tank to be empty, it has to be in level zero. So the test for this is going to break, but not because we are not using the test correctly, but because we are doing it badly on the function. So this is the test for the empty tank function and we are going to see it right now. So we can see here both of the tests and both of the functions and we're going to try and run it to see what happens. So hopefully you all get to see this. In the first test, the fill function, it says it fails and says that the precondition, we didn't make the precondition and blame the client because the client's the one that is using it bad. Sorry. So as I was saying, in the first step, it failed because the client is using this wrong. And for the second test, okay, let's fix the first one. So we see that in this test, we are leaving, we are starting with the tank with the level 10. It is already full, so it's not going to meet the precondition and we're going to change it to level five so we can end up failing it. And with this, only the second test is failing. As I said before, in the second test for it to empty the tank, the post condition is not met. So we have to blame ourselves because we're doing something wrong. What we have here is leaving the tank not empty with level one. We have to ensure that it is level zero for it to be empty. So with that, we have our two tests passing through. Yeah. So you can find this working progress library at the GitHub repo, Elixir contracts, and there's the URL. This is still a working progress library that we are working on with my partner Guillermo. And for this, we still need to do some things. Like, we have to make it generate test cases from these contracts. Also, our configurations to turn on are off and the contracts during development and production, as I say, there were advantages of this methodology. Also, we need to generate automated documentation from contracts and generate quick chest tests. So to conclude this talk, this I by contract does not replace regular testing strategy, rather it complements external testing with internal self-tests that can be activated both for isolated tests are in production code during that test. The contracts are an extra grade of reliability. And they're not a silver bullet. We still need to do testing, the contract, and some other things to achieve what we would like to do and not end up with this mission, really expensive crashes. Here are the references for the talk. Thank you very much.