 Thank you. Hello everyone. So my name is Hawi. I work at Dropbox as a software engineer. I've been working there for the past three years now. So this talk will be about something that you do a lot when you're working professionally, but something which you maybe do not learn or do not do much when you're just learning to program or when you're a student. So I guess, yeah? I'm going to adjust the mic so you stick a little bit into it. I'll just stand in your normal position. Okay. Yeah, just continue talking. Hello? Yeah. All right. Okay. So a quick straw poll. Like, who here is a student? Okay. Most people here are students. So who here has worked on like a program that's more than, say, a thousand lines of code? Oh. Let's say, 10,000 lines of code. Oh. 50,000 lines of code? So not so many people. So cool. So when you're a student, you tend to write a lot of programs. So you learn how to write algorithms. You learn how to write like a breadth-first search, a depth-first search, textures, all pairs, shortest paths, whatever. But one thing you often don't do is someone comes along and gives you this huge code base that you've never seen before. And your job is to implement some teacher that your boss wants or your boss's boss wants. So that is something that you have to learn that you often don't learn in school. And that's what I will be talking about today. So to begin with, let's say you come to some, you join a project. For example, here's iPython. Who here knows what iPython is? Yeah, iPython. iPython's great. Who here knows what Python is? Not just iPython. Hopefully more of you. So let's say you come to this project and your boss tells you that, well, you are working on this project now. It's your job to add new features to it. So you look at this thing. It has like a few dozen files in its home directory. You click around and you see many, many more files. Many, many, many more files. And your job is to get started trying to use this project. So what do you do? So the first thing that you do is you get it running locally. That's always the first thing you do. In theory, you can make changes to code and not run it and it will work. If you are Superman, you can do that. In practice, you probably will screw up. So you should always get it running locally so you can test your changes. So in most projects, you have some kind of onboarding instructions how to get started. Some will be more or less accurate. You may have to ask people. But for the IPython project, it's relatively straightforward. You have this little section called development. There are installation docs to tell you how to get started. So you clone it. Let me bring this up side by side. Can you see this? OK. So it says it wants you to clone it. It wants you to go into the CD into the repo. I am in the repo now. It wants you to pip install dash E. Whether or not you care what that is or know what that is, let's just do it. So it turns out that the new version of IPython does not support Python 2. So OK, well, we have pip 3 installed on my Mac. So this is for Python 3. And that seems to have done what we want. It didn't give an error. And then what do you do? Well, let's see if you can see. So once it's installed, it wants you to save Python dash MIPython to run it. So let's try that. So package can be executed. Again, I need to use Python 3 because they've deprecated Python 2 in IPython project. And now we have IPython running using the local source code. Or at least we think we have IPython running using local source code. So who here knows how you can verify that we actually are running based on our own checkout of IPython? What? Open the browser. So this is only the terminal version. So this is not the Jupyter browser notebook version. So who here has worked on a code base for an hour and realized that none of your changes are taking effect because you're working the wrong code base? Has anyone done that before? So what do you do to verify that it's not what I'm doing right now? So the easiest thing to do is to change the code and see if it has our changes, at least like a hello world. So let's exit this. Let's look at, say, IPython. And who I don't know if I'm going to change? Let's say console.py, see if that does anything. Console.py. Who knows if this is going to do anything? So this, in theory, should crash because I don't have a variable called a-o-i-d-o-i-j, blah, blah. So let's try running it again. OK, so that clearly did not work. So let's go look at my editor and let's see if we can pick a nice more, OK, main.py. This seems promising. Hello, IPython. It's Python 3, so I need to put parans around it. OK, so did this work? Did this work? Yes, it worked. So now we have hello, IPython, printed console. So now we know that, to begin with, we have the code running locally, and we know we can make changes. This wasn't a very interesting change, but it is a change, and that is already progress. So the next thing that you'd want to do when you're working with such a code base is you want to know what the code does. So before you ask who wrote it, how it's implemented, how many lines of code, all that, it's just like, what is this code base? What does this project do? So in this case, a GitHub repo has not very useful. There's other documentation online at the Read the Docs page. But in short, IPython is a nice Python interpreter that gives you syntax highlighted code, which is nice. If you press Tab, it gives you nice autocomplete, so you don't need to manually type in the thing you're working on. So let's say I want to import a math dot and autocomplete. Generally, I don't know what math.copySign does. It's like math.cosign 0.5. Use me like that. So this is what IPython is. They see a small Python interpreter. The advantage over the normal Python interpreter is if I try to import math and press dot, it screws up my console and doesn't actually work. It doesn't give me syntax highlighting. And so the normal Python console works. The IPython console is just a nicer, more ergonomic version that is easier to use. Takes a bit longer to install, but otherwise it's great. So lastly, you can refer to things from the out variable. So if earlier on, you evaluated an expression and it had a value, you can refer to it using out. And there's some other nice features it has. So let's say, so now we know what it does. What's next? The next thing to know is to decide what we actually want to do. So actually, before we decide what we actually want to do, let's take a small one to explore the project. So before we think about what we want to change in IPython, let's say what is IPython. You know what is externally? What is it internally? So maybe you've never seen a code before, and it would take a long time to read through all these files. It's quite a lot of files. But luckily, we have computers that can help do it for us. So the first question is, well, you may see that you already know it's a Python application. So that's already progress. We know it's not Java. We know it's not C++. It's Python. So what else do you want to know about the Python application? How big it is? Is it 50 lines, 5,000 lines, 500,000 lines? That makes a big difference in how you approach the problem. So you can do that by using bash. So for example, here's a command that gives you a list of all Python files. You can say that, well, how many Python files? You can have 350 Python files. That's probably not what I want to do, never mind. And how many lines of code? Well, if you use this magic incantation, you can run the word count on every file. And it will tell you that we're looking at 350 Python files with about 66,000 lines of code. So this is not small. Most of you have not written a 66,000 line of code program before. But neither is it particularly large. So at work, for example, we maintain a Python code base that's not all of a few million lines of code. And that's pretty standard. Like, for example, Yelp just open sourced a project which I'm using to maintain the 3,000,000 line of code Python website. Like, Yelp.com is like 3,000,000 lines of Python code. So 66,000 lines of code is not large, not small. It's OK, medium size, maybe. What else do you want to know? One thing that's often interesting is, which parts of this code base have the most stuff in them? So for example, if you look at this folder tree, you see a whole bunch of files and you see a whole bunch of folders. Some of the files are interesting. Some of the files are not very interesting. And we may want to know, like, well, as a new person navigating this, I don't know what's inside this code base. But where are people doing all their work? So I can't remember the bash incantation for this. But we have Google. So we can ask Google how to find largest files, Linux, or bash. And I think I have it. So if you go and dig through, you'll find the answer. I've tried my history. Fine, fine, fine. So this is a magic incantation of how to find the largest files in bash. You do not need to remember this. You can Google it later if you want to. But so I run this. And I look at the output. And you can see that, well, it messed up on a bunch of folders which are probably simulings or something, but whatever. Let's ignore those. And we have the largest files in the code base. So this is interesting, because if a file has zero lines of code inside or five lines of code inside, there's probably not much in there to understand. It's probably not that important. But if a file has 130 kilobytes, which is maybe a few thousand lines of code, that is probably something which has a lot of interesting logic inside. So where is our interesting logic? Let's see. Back up here. So IPython is interactive Python shell. So not surprisingly, interactive shell.py is the biggest file. Ultra TB is a pretty big file. I don't know what that is. Never mind. We don't need to know for now. Magic slash execution.py is a big file. For those of you who don't know, let me make this bigger. If I open up IPython on the right to show you what it does, IPython lets you do things like LS or CD, like, I don't know, Dropbox, Personal. And all this is. So this is not Python. That's not Taiwan. C workspace IPython. So this is clearly not Python syntax. This is not valid Python syntax. I've tried doing the normal Python shell error. So these are special commands that in IPython land they call magic. So it's here in the folder called magic. We have Sphinx extension IPython directive. So for those of you who don't know, like, if you Google it, Python, Sphinx, you'll find that this is documentation generator. So IPython has beautiful documentation at this ipython.re.dox.io. So they have a documentation generator that clearly they have customized quite a lot because there's 44,000, like 44 kilobytes of code in it. And there's other stuff, autocomplete, unit tests, supports latex or something, not sure, and other things. So now we've looked at this code base. And maybe we've never seen it before. But we already know roughly what we are looking at. So we're looking at a Python shell that's about 66,000 lines of code, mostly in Python. The most important things are the interactive shell and shell-related commands and IPython executing commands. So that's enough for exploration. So we've done this and we can't know what it is. So the next job would be pick some kind of, like, let's give ourselves a goal. So let's say we want to make some change to IPython. For example, instead of printing out hello IPython at the start when I open the shell, let's say I want to print out the text executing every time I start executing a command, maybe. So this is kind of arbitrary, but we'll give us a good. But if you start work, this is the kind of first task you'll often get. It's not super difficult, but it's something to just get you into the groove of working with a project. So how do I print out the word executing before executing a command? So first I need to find out where commands are executed. So well, there's a lot of code in here. So what do we know? Well, it's probably not in the test folder. So you probably don't need to change the units folder for now. Later if you're going to add unit tests, we can. That's a good practice, but for now let's skip it. If we look at the top level folders of IPython, we have core, extensions, external, kernel, lib, Sphinx, terminal, testing, utils. So it's probably not testing. It could be utils. It's probably not Sphinx because that's documentation. Maybe it's lib. I don't actually know what that is. I don't know what kernel is. I think that's to do with the browser version of IPython. External seems to be stuff to do with QT and Math Jacks. So that's probably not something we need to care about for now. Extensions. So I don't know what these extensions are, but if we are making a change to core IPython code base, I don't think we need to make a change to the code for extensions because that's usually outside the core code base. And lastly, we have core. So OK, just by looking at the top level folders, we can identify the fact that, well, we can probably look for what we want in either core, lib, or terminal, or utils. Utils looks like a bunch of stuff that's kind of IPython, like not IPython specific. So it's general helper functions. I don't think we need to look there. So just by looking at top level folders, we have narrowed down to core, lib, and terminal. So let's see if we can find something useful in there. So the next tool that we use when you're working on someone else's code is you use grep or search a lot. So for example, I don't know what to look for, but maybe if I'm trying to execute code, the word execute will be somewhere in the code that's actually executing my IPython commands. Another alternative could be maybe the word command is in the code that's executing commands. Maybe I don't know how it's spelled. Maybe it's cmd, but I can search for it. So if I search for execute, so let me bring this up. That's not what I wanted. So you scroll through what is happening. So in IntelliJ, it nicely categorizes what you're looking for based on whether it's inside a string, whether it's inside code base, whether it's inside a string constant. So we can kind of see that well. We have a bunch of these like execute events, which maybe are relevant to us. So in this case, we seem to be registering like a post-execute and pre-execute events. Not sure if that's relevant. At the top, we have some self.db.execute, and this looks like SQL. So that's probably not what we care about. We want to execute Python or not SQL. More SQL, more SQL. InteractiveShell.py. So this was a big file that we saw earlier. InteractiveShell.py. And there's a few execute words in it. So let's look at what it does. So here's register, post-run, execute, which is deprecated. But never mind the fact it's deprecated. It seems to be registering some kind of event that gets run every time we run a command. Maybe, I think. So if you are working on this in the terminal or in VIM or sublime, often the text is all you have. But in a nice editor like IntelliJ or any other editor you want, there are many Python IDs, Eclipse, whatever, you can look at, see where things come from, see what the documentation is without having to dig around too much. So for example, if you want to define what event manager is, we could act event manager. And it's probably a class. So let's act class event manager. And this will tell us it's in core events.py. And we can go and search in. And we can go and search in core events.py. Or if you're using a nice editor, if you just jump to it and it brings you straight there, which is convenient for making things faster. So event manager seems to be so it's infrastructure for registering and firing callbacks on application events. So that maybe is relevant. Maybe not. Let's go look at this register, post-execute command a bit. So this looks relevant. But how do we know if it actually is relevant or whether it's a false positive? That sounds relevant, but it's actually not. So again, you can search, register, post-execute. It seems to be called nowhere. OK, so that's probably not something that is actually used in the code base. I guess that's why it's deprecated. If we go back to execute and search again, well, let's not do that. So I guess the next thing to do since that didn't work out is to kind of just browse through the code on this interactive shell in this interactive shell file. So this file has a lot of stuff. And if you look at the bottom, it is 3,000 lines of code. This is not that much, but it's still a bit much to look at at first. So if you can fold the code, if you're using sublime or similar, you also have a code folding command that lets you see at the high level what is in this file. So we have this interactive shell object. Let me make this bigger. You have this interactive shell class which sounds like the whole IPython shell. We have some interactive shell ABC, which is probably some abstract base class that the ABC stands for in Python land. We have some execution result, which sounds promising. So this is something that sounds like it would get created every time we execute something. So we don't know that, but maybe. So here we have the result of a call to interactive shell.run cell. So that seems like it's something that we may want because we want to execute code and here it's called, maybe it's calling it run instead of execute. So if I look for run cell, so let's see. That brings us to here, runs a complete IPython cell. Let me close the search bar. So I don't know what the IPython cell is, but it's something that can be run and it's maybe what happens when you type stuff in the console, maybe they call it a cell. Again, this is not my project, so I'm kind of making this stuff as I go along. But this is something that you'll be doing too if you end up looking at someone else's code base. So how do we know that this is what we're looking for? Well, we can print something in it and see if it actually works. So Python dash M, Python three dash M. Okay, so now before each command, we can now print something. So over here I said hello run cell, but if I wanted to, I could say executing dot, dot, dot. And then I close this, run it again. Oops, let's make it 10 instead of 100. Oh, it's Python three. So I need to put friends around it. I work in Python two day to day, so this will keep tripping me up. So here we go and it's, you see it prints out executing and you print out the square roots of one to 100 because that's the code I put here. Sorry? Oh, here we are. Okay, so that's the first thing that we've managed to accomplish. So what have we learned from this? So let's say what tools we have for us. We have searching for things and we have guessing and we have print. So in reality, this is often what you'll be using when you try to work with the unfamiliar code base. If you've done it a lot, then you may find, you may want to use, for example, there's a debugger which you step through the code. Or there are other tools which you instrument the code to plot out nice control flow graphs of what the execution looks like. But at first, you often don't know what in the world is going on. So the best you can do is you guess, you search for something, you guess what you wanna search for and you kind of put print statements, which is very important. Put print statements to verify what you think you're running, you're actually running. Like the first file I found, I put print statement, I wasn't actually running it. So if I spent an hour working in that file and nothing was happening, then that would have just been a total waste of time. So make sure you validate early on that I think this is something that's running and I need to make sure. Okay, so let's try to make this a bit fancier. Let's say I want to echo the lines of code that are actually being run rather than just having a hard code that executes things, print. So I'm gonna make this a bit smaller because I need to see more code. So I know that this code is being run because it's printing execute. I don't know who is running this code, I don't know who is running this function for one. And I don't know what the arguments to this function are being called, but the arguments this function are being called with. Those are both very useful information even to make any actually intelligent changes to the code. So let's find that out now. So the simplest way is to print everything. So raw cell, store history, silent, sell futures, don't know what that is. Maybe sounds like some stock market term. And let's make that run. So one, two, three. Okay, so this is print, raw cell appears to be one, two, three. And if you don't know whether it's a number one, two, three or the string one, two, three or some other object which has the name one, two, three, I can call type on it. And I'm just gonna call type on the others just to be sure. So you can never be too sure that what you are seeing is actually what you think you are seeing. Maybe some jerk went and made the object that two string is called like two but it's not actually the true object. Which can happen. So maybe you think it's a Boolean but let's verify it's actually a Boolean. Okay, so one, two is actually the string we know that it's not some user input class instance. The rest are all Bools. If we want to print out the code that's being run we now know it's pretty simple. So we can easily make a fenced print line, one, two, three, four, one, two, three, four. And we can print raw cell, delete the extra prints we don't want. Want to, let's do something that's more interesting. For I in range zero to 10, print if I percent two equals zero. So one other nice thing about I Python is it lets you do multi line editing in the terminal like you can do in any other text editor which is convenient. But that's out of scope for now if you're not gonna talk about it much. So now we have the ability to echo out what the user's gonna print before they print it. So what else would I want to know about the code base? About this function call in the code base. So maybe I want to know who is calling me because usually a call stack is quite interesting because a piece of information tells you which functions are calling which functions are calling which class, which are calling which other function. And all of those are good at helping you navigate what your code base is doing. So the simplest way to do this is to just screw up and it will tell you exactly what your call stack is. Bang, okay, here's a call stack. Okay, so let's look at this bit by bit. Okay, run module as main, don't know what that is, run code, start ipython, this is a function, this is a file we saw earlier, main.py. And we were almost correct in saying that is the first file gets run. Actually it's not, actually just runpy.file is the first file, but it's close enough. So you go through runpy, you go through main.py, we go through the ipython start ipython function, ipython's like init package level, the package init file. We go into application, launch instance, we go to terminal ipapp, which is probably ipython app, ip, interactive shell, self-interact, run cell, and then that's our broken code that gives us a stack trace. So now we know kind of like what the control flow of ipython program looks like. You can see that well, we come from here, here, here, and we are currently living in interactive shell.py, that's where the most recent stack frames are. We can see that there's a main loop function interactive shell.py. So that's interesting because that means that once the program executes into interactive shell.py, into the main loop, we probably keep looping inside the main loop until you exit. So we know the interactive shell's where the program so-called lives. Okay, so that's interesting. So now we know, what are humans, what arguments are. Now we know what the call stack is. So remember at the start, we did not know anything about this code base. We had just cloned it from GitHub. We had just got it running the first time. And now we know a bunch of useful things. We know how the code gets run when you type in the ipython. You know who calls which function. You know what arguments that function look like. If we wanted to, we could go into this, we could go into the stack trace and put more print lines in interact.py, in main loop.py, and other places in order to see what's happening. But for now I'm gonna skip that. Okay, so next interesting point. We all have this two-dimensional piece of code in front of us. And if you open it in Sublime or VIM or something like that, it's a two-dimensional piece of code. If you set it up with Sublime, Python plug-in or VIM C tags or something else, you know it's actually not quite two-dimensional like all of these names come from somewhere. And jumping to where the names are defined is a useful exercise in seeing how this code is used, not just as a piece of text, but as like a function that is called all over the code base. So for example, I may want to see that well. So I know the execute result comes from Python call interactive shell, we saw it earlier. I know where raw cells are argument. I know where does this space come from? This space comes from the Python standard library. What else is interesting? Self.events is defined in this init.events function, the same file, pre-filter manager. So that sounds like a very enterprise grade like piece of code. So pre-filter manager is also in init pre-filter in the same file. And so we know that this is not just a piece of code that's like a character in a file, but is a graph where each of these names points to somewhere it came from. And if you want to know anything more about any of these names on screen, you can go look for it, whether it's by jumping to definition in the editor, or whether it is by going to the terminal and typing something like act to find all the usages. So both of these are valid ways of doing things. It's up to you which one you prefer. So you have two dimensional code, you have this graph of the history of what the code, it's not history, you have the graph of the definitions of where all these names came from. So the last thing that is interesting, the last thing that's interesting is the history of the code. So this is something you don't really care about when you're working in a school project, but code is not just a file, code is the work of everyone who has put something into this code base. So all the work of like hundreds of committers has gone into making this file you see in front of you, and you can see it. So one easy way is if I look at git blame, ipython, who is it? Core, core, interactive, shell.py. You can see who wrote which line of code, and it pages it for you. And this is kind of a pain in the neck to read, so I don't like doing it here. If you are using third party software like Source Tree or some other UI application, it makes it a lot prettier and easier to navigate. In this case, the editor has his own UI. So you can see that this piece of code isn't just a function. This piece of code is a function that's mostly written by this Thomas Clover person, but not just by him. We see fixes by Matthias Bosonia. We see that this Volcker Braun person looks like he added a tri-cats block. So why did he add a tri-cats block? And why did he add a tri-cats block? If you can't read it, it says, also catch syntax errors from input transformers in run cell. So the run cell method is not used in ipython terminal, so there are two code paths where the syntax error needs to be caught. Also, the commit moves the terminal test, blah blah, doing some suffering in the test to clean up the test suite. I've checked that this works in the terminal, the QT console, and HTML notebook. So this is a kind of history that a piece of code has. That's not obvious for someone who just graduated from school, but it's very, very important to someone who's working in the code base that they did not write. So as someone who just came in looking at the text file, I do not know why we have a tri-catch statement here. Like, is it obvious that this thing can show an exception? Maybe it is, maybe it's not, I don't know. But once you look at the history of the code, you can see that each of these lines of code has a little story behind it of why the piece of code is as it is. So we can go on and see, for example. So this single line of code here is written by someone called Benjamin Ragan Kelly. I don't know these people, so they're just a person, but they added the silent keyword argument to run cell, and presumably it looks like it's a shut-up the logging in cases where he didn't want it. I don't know why they wanted a shut-up the logging, but it's a thing. Over here, we can look at Mathias Bosonia, which says, use generic show trace back instead of show syntax error. So that is maybe not a very interesting commit message. We don't know what that is. But very helpfully, he has the task ID. So ipython task number 9199 was fixed by this change. So if you want to look at what this change was, this change was pretty straightforward. We can go look and see if we can find ipython task of bug 9199. And we can see that, well, here is a bug where it seems that if we register a custom exception handler, it gives the wrong kind of error that we would versus some other kind of error that we'd want. And this is discussed quite thoroughly in this bug report. And so even though that this person, Mathias Bosonia, did not write a very detailed commit message, he didn't have to because this code is not just the code that lives in a file or the code in a repo, but also all the history and all the discussions that went into building it. So this one line of code, or this four lines of code, in this case, was the result of four pages worth of discussion in addition to the work that he did into investigating it. So the last thing I'm going to show you about the history of the code, why the history of the code is useful, is that we can see all the changes that people made in each of these commits. So for example, when Mr. Volker Braun went and caught syntax errors from input transformers in run cell, or whatever he wanted to do that, we can see that he added documentation. So clearly before this, it was not clear that he may raise a syntax error. And he added the command saying that, yes, it can raise a syntax error. He, of course, made the change to add the try catch. So it looks like previously it was a single line of code. And now it is a single line of code wrapped in a try except with some error handling reporting code. What else did he do? He seemed to have made a small change to these two lines of code. So this is a bit mysterious. I do not know why he made this change. So he seems to have replaced a pre-filter failed, false, and checked for the length of the lines with if not pre-filter and checked for length of the lines. So this is a bit mysterious. I don't know why he did that. If we cared, we might investigate it more. But for now, let's ignore it. He added, or he modified some of the tests. So it looks like he added a new syntax error test. So given this syntax error transformer and this IPython code, which you could run yourself in the IPython console, typing in these commands should apparently now result in a syntax error and not whatever it was before. So this is something that we did not know before, now we know. We could, if we wanted to, we could reproduce, run the test locally, or check out the original version before this diff and run the test to see what the behavior differs. He similarly added the test to the interactive shell test suite and he created a new test file inside terminal tests in which he tests more or less a similar thing. So this is a history for this one line try catch exception and tells you what this person was trying to do, why he was doing, what problems he was trying to avoid, and how he made sure that the problems don't come back in future. So these are the tools that you have when you're looking at other people's code. Just a wrap up, when you first start looking at someone's code, always run it locally. Don't try to send out diffs blind, no matter how smart you think you are, you will make a stupid mistake and people will laugh at you. Make sure you know you can make a change. Don't accidentally be working on a file for like two hours and realize it's the wrong file, let's not do anything. Make sure you know what the project does. So from outside point of view, what in the world is this project, why does it exist? Make sure you know that. Look through the project, look how big is it, what are the main files and folders, how many files in each folder, how big are the longest files, which are the biggest files, all those are important. Pick a small goal and make it happen. So if you join the company, the Chancellor, whoever's helping you mentor you for the first week or first two weeks, will pick this goal for you because they will know more than you about what's easy and what's not. But the point is you must pick something that's small and the fact that the goal is trivial does not matter. The important thing is that you can do something that is useful. The tools you have, to begin with, are usually searching, guessing, and printing. You could try hooking up to fancier debuggers. So for example, you could in Python use PDB and step-through code, you use IntelliJ or Eclipse's debugger and step-through code. There, you can profile it and print out the call graph. If you know how to do those things, great, do it, see what it looks like, see what you can learn. And if you wanna do something more advanced, know what arguments are being passed around, debuggers work, prints work too, know what the call stack is, who is calling you, why are they calling you, who in the call stack is important and who's not. Look around for where all the definitions come from. So code is not just text. Each of those names is a reference to something that's defined somewhere else. And make sure you can know where all those things are and how your thing fits together with those. Make sure you look at the history of the code. So a code is not just what lives now but everything that's happened in the past few years. So if you look at, for example, this piece of code, this piece of code dates back to 2011, much of it. So this is actually a pretty old piece of code. There's a lot of history to it, a lot of bugs, a lot of things that were fixed, issues that were raised. Make sure if you see a piece of code you don't understand, if it fixes an issue, look at issue. If you see a line of code and that's how it changed, and you're wondering why they changed it, look at the diff that changed it, look at the text he wrote, look at all the other changes he made that were part of the same diff that are probably related and try to understand why he made those changes in the first place. So I think my time is up, so that's the presentation of diving into other people's code. And I guess I'll take questions. Questions? No questions? Going once? Going twice? Okay, I guess we are done then. If you can come look for me after if you wanna talk more. Cool.