 My talk is Observer Driven Design, and that is the loftiest name I could think of for my modestly relevant topic. So thank you all for being here. Let me dive in. My name is Omid, like PJ said. I work at Mojo Tech. It's a software consultancy in Providence and in Boulder. My background is in Ruby, and we've basically spent the last year doing research and development in Elixir, which I'll share an anecdote about later, but we've finally got our first client project in our first green field in November, and it was with Phoenix, and so we're proud to finally be using the tech that we have enjoyed playing with for so long. So what is my talk about? So I work with beginners a lot. On the weekends, and after dark when I'm not on the job, I work with people at programming boot camp as they're like online chat support, and so I interface a lot with people who are just getting into programming. And what I learned was that some of the literature and resources out there are targeted toward experienced developers who are either experienced in that tech or experienced in other tech and are literate in the basic concepts. So what I always think about is, well, if I had to explain something to someone who is just learning to think computationally or just learning to think in OTP, what tools could I use to help them better grok that or to shortcut the time it takes to learn? Because what we do is not rocket science. What we do is simple, but it's very broad, and there are a lot of details. And so how do we best communicate those details? And so when I was learning Elixir, one of those really tough parts for me was OTP. And we've had a few talks about it already, so I'm like, fuck, is this going to be totally redundant? But no, it won't. So how do we best get familiar with OTP and use practices in development that help us verify that what we think we know is actually true? So my audience is basically, hopefully everybody, but beginners to programming and beginners to Elixir, if Elixir is one of the first languages you're using, but also people who are implementing features in OTP who need a source of truth to verify their assumptions. And that is an audience that I think is broad enough that this talk could be helpful. So the thesis is, we need to understand the truth about how OTP works. That's kind of hard. Therefore, visual diagrams are extremely helpful in illustrating how OTP works because it's a network, it's physically like a tree, and drawings can really help. And therefore, the observer is uniquely suited to verify our assumptions in the applications tab where you can see everything play out like a diagram. So what is the observer? Let me spend 20 minutes telling you what the observer is. No, I'm not going to do that. What the observer is at its most basic is a graphical tool that lets us inspect early systems. And specifically for my talk, it helps us observe processes. Does anybody here use it? About half of hands were raised YouTube viewers, and what that means is not enough people use it if you really want to understand how OTP works. And I'm not going to give you how to on all of the observer's great features. The UI is basically Windows 3.1, and I do not want to go through all of the different layers of it. It has tons of data. Just take my word for it that it's worth learning about. We're only going to talk about a small slice of it. And we're hopefully going to give it a job that will help support our OTP development. This is basically the part of the observer that I like the most. It's this diagram. It comes with the runtime. And hey, Erlang team, did you do that on purpose? Yes, they definitely did. The reason why, at least I presume, the observer comes with built-in diagrams is because you really need to see it to understand this shit. It is a network. Things spawn other things. Things are connected to other things. And the way that they illustrate it in the observer is the most basic and simple way to transmit that truth to the developer. And so if we can plan our OTP implementation, not all of our implementation, because we won't always use OTP. Sometimes we're just functionally programming. If we're using Phoenix, a lot of these decisions are made for us. If we're using other tools or just doing work or computation, you may not have to use this particular tip or set of tools that I'm suggesting. But when OTP matters, I think the observer and the application's view in particular that produces that nice diagram, those need to be a very important part of our process. So what is OTP? We've already gone through this. This is the part where I was like, damn it, they've already got a full explanation of what OTP is. But for the viewers out there on YouTube, I'm still not going to explain it because it's been said. The important thing to know is that we have a supervision tree, we have workers, we have supervisors, and what supervisors do is restart things. We have a physical network that enables OTP, and that's why we appreciate the observer. Why OTP? Well, there are a lot of reasons. And famously, two of them are scalability and fault tolerance. Scalability in particular is enabled by those processes, those supervisors and those workers, because they don't share memory. And that means that there's no single point of slowdown for state or information. They contain their own state. They are garbage collected individually. And the scheduler ensures that the load is distributed across cores on a machine, and furthermore, they communicate with each other in a nice, discrete way, which is through messages. And fault tolerance is enabled by OTP because of that restarting behavior that supervisors do. And because we typically write imperfect code, we rely on third-party services, file systems, and other error-prone things, restarting can be extremely helpful, like one of our previous speakers mentioned. So let's do OTP well. And to talk a little bit about an anecdote, which I mentioned at the beginning, I first started R&D with Elixir at our company, Mojo Tech, with my mentor, who he and I just set out to replace an internal API that we had. And so we basically just did programming. We did a little bit more functional programming than our previous implementation, which was in Node. We still had a lot of functional patterns there. But when it came to implementing OTP, we thought, well, let's use a gen server here. Let's use ETS here. Let's try to implement some sweet-ass features, because this is a great language and a great opportunity to use this new tool. What I discovered was that it's not enough to implement OTP features. That's how you do not do OTP well. The way to do OTP well is to understand how OTP works with processes and how processes enable it. And if you use visual diagrams with the observer, you'll naturally and organically understand how to properly construct your OTP features and therefore not glue on OTP, but rather to build software that seems to be meant for OTP. So that's the goal here. That's the goal of using the observer. That's the goal of using visual diagrams. But there's already so much to do. Some of us who come from Ruby, like me, or from Java, or from object-oriented languages, have to first grok functional programming. That's hard. We also have to understand things like pattern matching. So language features about Elixir can also be very difficult. We also have to understand the tool set, Ecto, Phoenix, NERVs. There's a lot of different libraries, other than those big ones, that we also have to understand. This is not about all those. The change in mindset we're talking about here is just for OTP. So this doesn't solve all of our problems. But let's try to use what I'm saying and see how it all turns out. And our example application will be pretty simple, but let's go through it. Because what I want to do here is illustrate that to do OTP right, we should think in terms of diagrams. The observer gives us a source of truth in the form of diagrams, and that can help us enter a virtuous cycle of development. So let's start with an example idea of an application, or at least a very narrow slice of one, and see how well, or see how this process that I'm proposing would actually work in practice. Okay, so let's say we have a synchronous process that needs to validate users. The third part of it is important. Let's say we've got some kind of HTTP interface where people are receiving payloads of user information, and if that user information is valid, we'll go ahead and persist it and spin off two jobs. A welcoming email and login entry in analytics. These are third-party services, so it's an opportunity for us to do things asynchronously and also perform throwaway work, which we don't care what the return value is, or we don't want to wait for the response. We just want to dispatch these things and proceed. Excuse me. So how should we implement this? One of the inner monologues I had when planning this talk was, to what degree should I involve the audience? And so I was thinking there are some people who took time off of work, who traveled long distances, and actually sat down to honor me with their audience and to listen, and then there are the sons of bitches, frankly, who are just going to watch this on YouTube, even though I love them, and I have been them. I want to ask you guys, in what way would you use OTP to do that basic task of our application, which is to synchronously validate and persist the user, but then spin off these two jobs? So who would like to make a suggestion? And I'll repeat it back into the microphone. If your voice is soft, you don't have to scream or anything, but please raise your hands. Colorado shirt. Cameron. Very good. So his suggestion was, let's have supervised gen servers handle this work and to group them, if you will, right, in terms of what their job is. Other suggestions. Using different abstractions. Maybe not gen server, maybe something else in Elixir. Adidas jacket. Glasses. My friend. Yes. Make a suggestion. Use OTP. That's true. Well, sure. So he suggests using ETS. And for state, that's a great idea, because if these jobs do fail, let's say we want to have ETS to preserve their state. Let's say if we have to restart the e-mailer, we've got some of that user data in our ETS table, we can look it up just in case something fails, just in case bamboo is down or send grid is down or whatever the case might be. One last suggestion. Who else would have an idea about how to implement this? Glasses, red shirt, hoodie. You. Go for it. Give us a suggestion. Yes, eye contact is the most dangerous thing you could do right now. All right. Make a suggestion. Use S3. Perfect. Yeah, that doesn't always work though. One failure in like a decade. That's pretty good though, right? Okay. So my idea, thank you for your participation. I really appreciate that. My idea was to, like you, survey the different ideas, right? So we can use tasks. We can use gen servers. We can use, you know, bear processes. We can also supervise them. But here is the diagram I used, which was my mental proof of concept to illustrate what I think could handle this basic, the supervision of this email job and the supervision of this analytics job. Which was that we've got this application supervisor. It will start the email supervisor. It will start the analytics supervisor. And each of those respectively will spin off their job when that user's valid information comes through. And so the important things to illustrate would be the supervisors, the workers, their hierarchy and how we spawn them. And so I dislike fewer things more than slides with code on them, but because I had to actually do this, I thought, well, I might as well just share it. But basically here, my application is starting the two supervisors. And I used tasks in order to abstract away some of the details of starting an asynchronous job. Excuse me. So anyway, that takes care of the supervisors and the hierarchy, but now let's spawn the workers. And here in my business logic, I have two supervisors getting two supervised jobs. One is to log the analytics and another is to dispatch the email. I had the distinct privilege of working with James Fish or listening to him during his workshops yesterday. And so I got some of his input about this. And of course, we want more robustness than what you see here. But at its most basic level, let's just see if we can implement something like what our diagram has illustrated. We've taken care of the things we need to do based on our diagram, which was take care of the supervisors, the workers, their hierarchy, their relationship to what are in other words and spawning. So how does it look in the observer? And this is the important thing to ask yourself. It's not so much that we can plan features in OTP. The goal is to have them align with the truth. And just like the urge we have with test-driven development or behavior-driven development or user research is that we want our theories and our hypotheses to be borne out by the facts. And the observer gives us that distinct benefit. And so in the first, in the top half of this image, you'll see that in the application's general state, you have the properly spawned supervisors for the analytics and for the mailer. And with the help of some timers, you may be able to slow the observer down and see that the jobs get created with that same hierarchy that we had in mind when drawing our diagram. So we did it. In truth, in coming up with this talk, it actually took me several tries to not only come up with the right diagram, but also to have the observer do what I wanted it to do. And in reality, it's not so much about making the processes in the observer do what you want them to do, but it's knowing what the best practice is in OTP, seeing what that looks like, and having our mind work more and more in line with that actual reality. But what are some other things we might need to illustrate? Several things. And this is where I'll ask for your participation again. So we have supervisors, we have workers, we have basic hierarchy and spawning. What else might we want to illustrate if we are to diagram things well? Ideas. Your eagerness is impressive. Sir? Message queue? Excellent. So if we want to implement a particular strategy, let's say, about our message queue, where one thing that we want to be concerned about, let's say, is that if this process goes down, we want something about received messages to be handled in some way or other. That's something we should illustrate. What else should we illustrate? Excellent. A supervision strategy would be extremely helpful to illustrate when we diagram too. And it doesn't always affect every feature, but sometimes the difference between those supervisor strategies can be crucial. And for those of you at the OTP workshop yesterday, we saw specific tests that put our software through the rigors and exploited the different benefits of different strategies. Excellent. What other things should we illustrate? Sir? Excellent. So time is very important to illustrate in our diagrams because when one child is younger or older than another, it can have consequences for how we do communication among processes. Other suggestions of things we need to be able to illustrate? Sir? Very good. So when it comes to proximity among processes, and proximity not in terms of like how they're spawned physically and physically, their connectivity to one another, but proximity business-wise, who needs to talk to who and which processes need to be up together or down together or what have you, that's very important to illustrate too. Other suggestions? That's very good. That's good enough. Among other things, we need to illustrate monitoring, linking, time, relationships, supervisor strategies, restart strategies, and failure propagation. So these are all things that are super hard to understand but are very easy to illustrate and physically if we see them in a diagram, they're relatable. So as a tool for enhancing our understanding of OTP and making sure our practice of OTP is improving and getting better with time, we have ways of illustrating these things in the observer and we should include them in our diagrams that we have verified during the course of development. So the virtuous cycle that I keep referencing, and we're getting close to the end of my talk here, so I thank you, but the virtuous cycle that you'll enter by using a source of truth in any form of development is that more and more your beginning thoughts look closer to the end result of your good code. And with test-driven development, you see this by thinking about your API, by thinking about inputs and outputs. With OTP, it's a little bit more complicated. It's not as easy as running something through a test and making sure it comes out okay. So we have to use the source of truth that we've got and our runtime ships with this uniquely useful diagram in the observer that allows us to come up with a plan or a hypothesis for how we think OTP should work for us, verified in the course of development, and modify the model or the diagram that we drew as we go forward, and ultimately to teach us as a learning tool for ourselves because OTP is new to many of us here, how OTP really works. Thank you. My name is Omid. I appreciate your time. Thank you for participating and for humoring me. We are hiring at Moja Tech like PJ suggested I should announce, but thank you very much. The next speaker, Josh, come on up.