 We have an announcement for you all. So the announcement goes, group discussion starts at 1830 ISD in D.E. Shaw, India, booth number one. I gave a thought on whether we should have Python as the first language to be taught in universities and colleges. If not, this is the time to think and share your views. We look forward to some interesting discussion here. And of course, there are some exciting prizes of a grab. That's amazing. Thanks, Tisha, for that. So feel free to check out Zulip. If you go to the announcement channel, you'll find a link to wherever the booth is on Hopin, or you can check the booth on Hopin itself if you want to. And there are some forms to be filled if you want to grab those gifts and prizes. So go to Zulip announcement channel. You'll find a link to the registration form. You'll find a link to the booth as well. Now moving on to Pavel. Hey, Pavel, can you hear me? Hello. Hey, I can hear you clearly. So I'm just going to share your screen now, and the stage is all yours. OK. Hello. My name is Pavel Polevich, and today I'm going to speak about library interfaces changing over time. Let's begin. First, in upgrades can be painful. But for developers, those are often worse than for regular users. I'm going to tell you a story about the Debian server upgrade that I took part of in 2006. After upgrading the operating system version, all services were fine except one, FTP. It accepted connections but refused to transfer files. This FTP was the only way for us to put new music on a streaming server of the largest e-radio station on the planet at that time. So we had to get it on. First, we tried the init script. Just stop it with an init script. But it didn't do nothing. But in its scripts, they sometimes have bugs. Sometimes they rely on pit files that are not there. So I thought, OK, this is not working. Let's list the process list, find the FTP process, send it to kill. So that's what we did, but it didn't work either. So we thought more, OK, OK, so what else can we do? Kill means nine. Sick kill. So we sent that. But amazingly, it still not killed the process. Or 21 was still accepting connections, not transferring files. You kind of puddled. But then one of the admins has remembered that there is a command that can kill every process. It was kill or pie. He invoked the command without any parameters to see what the proper syntax is. Because most commands, if you just type the command name, it was an error or missing argument. But the density terminal froze. No help was displayed. And that happened because Kill5 does not accept any arguments. It kills all the processes in the system. Every service died, including SSH. We couldn't log in anymore. The stream switched to the backup server. And there was no KVM, so we couldn't connect to that server either by that. But even after this, the port 21 was still accepting connections. So we had to call the data center. I asked them to press the physical button on the machine to reboot it. When I think about that story, I smiled. It was fun. But not all version are great stories are that funny. Non-backward compatible changes are a major issue with long-term support. Maybe young startups don't feel it that much, but successful projects eventually have to upgrade their dependencies. Startups that take a longer time to get to the market are impacted most by this because their stack is getting old, and they still have very limited resources. Probably products. The ones that are closest to our hearts don't have a free time. Those are hit the hardest because there is almost no resources and dependencies are changing their version, and you have to follow them. Otherwise, your project just doesn't work. The interface changes in the libraries eventually force the application developers to adopt their code to work with the new API. So for them, it would be best to never have any non-backward compatible changes. The thing shown on the screen is the most famous adapter in the world on board of Apollo 13. I want us as a community to make less of those. The thing is, if a library has 200 users and non-backward compatible change will eventually force all of those users to go over the changelog and adapt their code to the new interface. But most of this effort is hidden from the library maintainer. While hundreds of engineers try to migrate their applications over to the new interface, the library maintainer already works on new features and next changes. So there is a great disparity between the effort that the community needs to make to follow the version and the amount of work that this developer can do to increase the major assembly to release a new non-compatible version. Both users and maintainers face the same problem from different sites. Maintainers want to improve their interface for the new users. The old users would like to keep their applications running so they don't want the interface to change. Meanwhile, new users want a new modern nice API, but as soon as they start using it, they want stability. They become old users and they don't want the interface to change anymore. Users also generally want access to new features, performance and maintainability improvements even after they settle for an interface barrier. So library maintainers need to introduce non-backward compatible changes to their APIs to improve them. But then eventually, application developers have to follow those changes in order to receive security updates and support because the maintainer will not keep maintaining the old versions, old branches of the library and fixing bugs on all of them. Eventually, the support is going to be dropped. Version 2 will have zero users on the third day, regardless of popularity or version 1, because nobody can adapt their code yet. And there seems to be that there is no other way, but maybe there is. Turns out there might be a way. Actually, I think it's not that hard. I called the abstraction of the interface which solves this problem up-ever because it assumes that the API of the library will have different values. Here is how it looks for the unit. Now, this is how we previously imported Coke. So there is the internal structure of the library is exposed a little bit, and then the user needs to know this to import a function. And this is the new way that I propose. So the obvious question here is, what about namespaces? So it is unlikely that you really need them. If you even have to file classes in different modules that do different things, you might want to change their names a little bit, that's less confusing. Alternatively, just do this and keep a little bit of your external structure, of your internal structure in the interface. I realized that my library is like medium-sized and it can be flattened to a simple namespace easily. The important part is that V2, which gives you back your freedom. If you use API-Ver, you can move your code around as much as you want, really, because users won't mind. In fact, most of them won't even know that something happened. Imagine what your users would think if you'd like to rearrange modules so that the structure is slightly more consistent. There's no functional change to it, but it looks more tidy for you. But then sometime later, you decide something between the old system and the current system would be even better and you change it again. Everybody would have to fix their imports and then fix their imports again. So you're creating a lot of work for all of your users, your break compatibility for them, for no functional change. If you use API-Ver, you are free to change your internal structure without impacting the users. Okay, so how does the implementation look like? How do we do this? Well, it turns out it's not expensive. It's one line per public member of the interface. So function, class, or constant. That's all it takes. See for yourself. The newest version imports from your internal structure. So this is version two. And it's imports from the structure that you had. The imports seem similar to how we used to import before API-Ver. And the old version, version one, imports from second version. So this one unit file is the adapter that bridges the gap between version one and version two changes. The older versions import from the one above them. Version one imports from version two, version two imports from version three, and so on. So you only need to focus on one adapter at the time to cover the API differences between the last release and your current pull request. Okay, so that's moving. But how about renaming a function or a class? Let's do that. Version three is, again, one line. In fact, it's the same line that you used to have in version two, because it's a top version, except it now imports a renamed function. And users of version three will call the function by its new name, by renamed function. While users of version two will call the function the same name as they used to call it, and it will still work for them. And the adapter for version two here is just one line. No need to release a new major version, no need to adjust code for all the users, just works. Okay, how about adding a new mandatory argument? So here we assume that version four needs to explicitly provide the value and version three uses a default. It's up to the developer to decide if the style keyword argument should be available for version three users. Here, there seems to be no benefit in finding it. The alternative is to do this. So you just, you don't expose it in the version three interface. So they can't define the style, but it is defined for them. Okay, so in version two, we have moved the code around. In version three, we have renamed functions, in version four, we have added mandatory arguments. Now imagine that we would also refactor portions of the code, keeping the same interface in version four, but then we would fix an old bug. So if we had different versions of the code on different branches, we would not be using up ever, we would have to backport the fix through code movement, renaming, and refactor. And that requires more and more and more work from the maintainer, the farther we go into the past. That is the reason why people care of support. But then some bug needs to be fixed in different implementations. Three refactor and post refactor. So you're doing the same thing twice. And it is wasteful. If you're using up ever, the fixing of the top version is enough. And also there is no need to drop support for the old versions because there are no old versions. No need to force folks using the old versions to adjust your code, just works. Okay, so that's all good, but there can be some issues. So these are the ones that I found. Some rappers may be hard to write. If you change a lot in your interface, and that means the users would have to adapt their code. So either everyone implements their own adapter or they change their code, which is even more work. So we can do this 200 times across the entire community, right? Or we can do this in one place in the library itself. The cost is way lower, but the other person bears the cost. So that's a little bit of a problem. I have to say that if you are the person that is breaking the compatibility, you know the old interface, you know the new interface, you have all the code in your memory, and you're making that change. So creating an adapter for you is quite easy. Creating an adapter for someone else that you just installed your library for years ago and has no understanding about the internals is way more difficult. So it's not like it's 200 times easier for you to do that. It's even more. Some tooling would be nice. We can probably manage things better. We can add decorators to indicate in the documentation that the given method is going to be phased out in the future, but not future major release, but future happy release. We can automatically list the differences between the interface versions and so on. That tooling is not here yet. You can make it. And if you think, if you don't think about your interface, which methods and functions should be public and contents and you are all ready above version one, then you may want to cut down the interface to what should actually be public in a major Semver release before adopting Happy Bear. Because supporting internal infrastructure with wrappers is just not necessary. Nobody will ever use those wrappers, but you don't really know because you don't know which methods are public but in which are private. Defining the interface surface is important in Semver. Not all people do that. That's a good movement to do it. Okay, so what's next? You already know how not to use your internal module structure as a library interface. Just create one file which exposes the flat interface, preferably flat, and let people use that. So if you start using Happy Bear, you can start using it now, but you probably learned something and please share that learning with me so that we can make it better. And yeah, I'm sure it can be improved, but for that we need to start using it and we have to talk. It's the shoot summary. This is how it looks for the user. This is how you implement something, right? The wrapper. So just create an init file and take from the higher one or from the... If you're on the top version, just import from your internal structure. And benefit that you get from that is freedom to do whatever you want with your internal structure of the code without messing everything up for all of your users. And on version two, you don't have an empty problem where you just release the second version, but nobody can use it because they already used the old version and they don't really have time to modify their code on your schedule. Thank you. Let's start during the break and... Thanks, Wabi. Thanks, Wabi. Oh, yeah, yeah. So let me finish. If you'd like to discuss this subject with me further or any other Python backend subject for that matter, find me during the break in the full way which this TeamShanky will mention in a moment. And here's my email if you want to write to me. Finally, many thanks to the organizers of the conference for letting me share this. I hope it will make the word slightly tiny little better place than it used to be. Okay. Thanks. Thank you, Pavel. We have one question. Would you like to take that right now? All right. Yeah. So the question goes, does that mean when we implement the 10th version of a library, we have to include 9th, 8th, 7th version in the package? Wouldn't that increase the size of the package a lot? Okay. That's a great question. So you don't include the entire code base of it. You only include the top version and wrappers for the old versions. But those are only one file that has one line per interface member. So it's extremely light and people also zips it. And most of it is going to be import statements and the zip eats those pretty well. So maybe the package will become a little bit bigger, but you shouldn't even notice it. Like I don't think it's a major concern. The storage cost now is very small and it takes you a tiny little bit fraction of the send to store this forever. So kind of yes, but it's not that a little bit problem. Okay. Any other questions? Anyway, let's go to the, oh wait, maybe discuss this on video. We actually have a video chat on open that we can all go into and discuss it on video. Sure. So I have this. Can you try? Yeah. So I have this Holly track. As we can see we have a lot of holiday tracks which are completely free to join. And one of the holiday tracks which is my curate is completely free right now. And we can invite all the attendees who are watching right now should have any questions. If you want to communicate after the session, feel free to join my curate hallway track and ask your questions or have a conversation. Talk more about how we can do that right here. If it's a bad idea, please come and tell me. Got it. So I'm sure you'll find a lot of questions there. And thanks a lot, Pavel. Thanks a lot. We'll see you on the holiday track now. Okay. And we are going to, yeah, thanks. See you there. Bye-bye. Bye-bye. Okay. So major announcement after this session is that we are going to have our keynote speaker on the Bangalore stage. So Naomi Sardar will be joining us. She'll be giving a keynote session at 7 p.m. IST that is 19-00. And it is going to start in just three minutes. So if you want to check out that keynote session, please head towards Bangalore stage. So we are going to stop the Delhi stage stream right now. Feel free to head towards the Bangalore stage. Feel free to head towards the Bangalore stage. You'll find that session running on the stages. Click on Bangalore and you'll be in. Okay. Thanks a lot everyone for joining on day one on Delhi stage. And see you tomorrow. Sure. Share your feedbacks or questions in the comments on hopping chat. Tweet about the session tag at the red pike on India hashtag at the red pike on India 2020. And yeah. Thank you. Bye bye.