 Let's start with the next speaker. Please welcome our next speaker, Redslaw, who is joining us from Poland. He is an experienced Python developer and works mostly with Django. We'll be talking about the joy of deleting code. Let's start with the talk. Over to you, Red. Hello, I'm Radek and I will tell you about the joy of deleting code. In this presentation, in this talk, I will first talk about some different thoughts I have about deleting code. I will tell a bit about my story and then I will focus on the concrete methods that I used or that I recommend. So let's start. So why do you want to delete code? The code that lives in our repositories, either it is legacy or just developed code, it might contain in some places the code that is not used. We don't want this code to bloat our software, our repo. We just want to get rid of it. So you may ask yourself, why? Why do we want to delete code? Because less code is less bugs. It's as simple as that, hard to oppose. However, also, when you delete code, you also can introduce more bugs and when you, for example, have multiple places when the same code is used and you make a function out of it, I miss some things, some differences, minor differences that will introduce bugs. So we need to be extra careful. And also, especially in Python, that will bite us many times, many places. Sometimes our code is used in, it's referenced. Only it is referenced in YAML files like defining classes in open API definition or code that is used by another module, which we doesn't see that it is used. And also the code that is used only in particular environment. For example, our code coverage will show us that it is not used, but it is really used, but somewhere else. And also, it is very easy to fall into this intimidating mindset that real programmers delete code. We don't want, this is additional code and needed code is not something that we want to have. And we should, part of our professional professionalities so that we detect and delete what we don't need. However, this statement is as true as any other statement we can coin. It only makes us a bit sad, a bit guilty, but it doesn't change anything. Every case is different. And for example, there are, if we have the same code in different layers of the program, we might need to keep it because they have different purposes. If they look the same, maybe they will evolve into something other. Also, there is a wet principle that opposes the dry principle, which say write everything twice. Also, it is also commonly said in other words that duplicates start from three. That if you have to duplicate, it's okay. If it's three, okay, let's get it out. But also, yeah, there are many, there are many problems, but also sometimes you just need to speak up because there are projects, especially with legacy code that you won't understand what the code does. You won't understand how the code is used. The number of WTFs per hour will be very high. The rotten code, the code where dragon lives, maybe it would be good to delete it instead of spending months on getting how it really works. So sometimes you just need to do it. Just get rid of the unneeded code. And whatever happens, happens. Of course, it's very careless. But for example, if you have a legacy project, no CI, no test coverage, no things that could help you with detecting the possible unused places. You just can sometimes remove something, but check, test it on a test instance, not production, of course. Sometimes it's the only way to see what happens. Also, many people don't like deleting code. They say, oh, we are going to need it, or we are going to need it again, which is the worst because this code was used some time ago, maybe we will use it in future. It's a trap, don't go for it. There's a principle, you ain't going to need it. So now I'm going to need it. Maybe in future you will, but maybe you will need it in different form. Or maybe if you're adding a code that will be used in future, you are just bloating your work. You will not be able to finish the task in sprint because you added something that you think would be useful. On the other hand, if something is really going to be needed, and you really know about this, maybe it would be worse to extract it to a separate library or module so that you will see that. Okay, here are some stuff we are going to need it, but it lies on the side, so we know that it won't break our test coverage or something like this. It just lies here and waits for its turn, but I don't recommend this. Maybe another package or something like this, or I don't know. Sometimes the situation that you have divine force is you have a revelation how to solve something you don't need to solve now. Maybe just put it in gist or a file in your file system, not exactly in the repo. Yes, I said a couple of times about the legacy code. The legacy code is very difficult case, because if you would like to comment legacy code, it means you need to delete it. In most modern projects, we use something that is called Git or other version control system, so nothing is really lost. The code is somewhere there, if we'll need it, we'll get back. Problem is, commented code rots a lot more than the usual codes that are surrounded. So in the end of all these random thoughts about the code, you need to just do it, but don't do it carelessly and don't fear too much. That's about the outcomes. In modern projects, we use continuous integration, linters, other tools, and they could help you spotting the possible problems, possible bugs as soon as possible. So you just are going to do it and see how good it feels to delete something and to get your program a bit lighter and a bit more understandable. So a second about my story. So I'm a developer. I worked with Python for 10 years, and I changed my job and projects quite often. Also, it's counting along with some side projects. Half of all my projects contained legacy code, and by legacy code, I mean not something written a month ago, but a year ago, or five years ago. Half of the half of projects was in so bad shape. It deserved to be rewritten, but we didn't have time to do this, or we didn't have courage to do this. And that led us to constant refactoring and getting the code better. There was a project when we refactored it for a year, and then even our manager. So guys, it's leading to nowhere. Let's rewrite it all and do the smooth, smooth pass from the old code to the new. So sometimes even people, all the people around you see that you should give up and to rewrite it, but you don't see so it's good to have a perspective. But suppose we are given a legacy project and we can, we need to refactor it. It is working. It needs to be working. We don't have time. So that leads us. The first thing you are thinking of doing in such case is, at least I am thinking is deleting code because less code is lesser factoring. What's, what's the, what's the purpose of writing unit tests for legacy code if you know that some part of it will be deleted. Of course, it is extremely dangerous because you don't know the code. Part of course used looks unused, but if you have any way of finding it out of checking it in a, in a development environment. It might be good to just drop the code that looks dead and see what happens. A friend of mine once told me that he was give he was in his project there was a thousand line function where there were big chunks of code with under if statements with contradicting with contradicting expressions. So there were, it was just unreachable code. When he cut out of the unreachable code he the result was a hundred line function, not a thousand hundred light function is function is still big, but it's it's better than thousand. Okay, so how do we prevent having to use the code or how do we find it. So let's grab the first and the easiest way. So unused imports. It is basically a full auto approach. There are tools that can help you I sort I said will not find the unused imports, but it will get rid of the obligated in imports and sort everything gently and pyflex or piling will show the unused imports. So this is not not a big deal, not a big gain, but it will make your code more clear. And it will be useful for next state steps. So next step is unused packages. So here we, we use the previous step because here we will, we will take advantage of it. We, for example, there's a simple, maybe, or maybe not so simple bash command that extracts all imports from your project. And you can compare it with your requirements file or setup file, setup file dependencies. Of course, some of the imports will be imports from the standard library so you need to take into know it, but if you want to want to be able to find your requirements in one of the imports, it might mean that it is unused. Of course, there are some packages like the development tools, which are not imported like piling or Python, Python is imported, which aren't or genie corn, which are not important in your code but still they are used so you need to have some knowledge, have some, know what you, what you have in your, in your code base, but it will help you to get the, get the obvious, obvious candidates. Okay, so unused modules. So modules are big animals. So it is good. It is easy to, to track them. And we do, we do with this just like with packages, we see what's imported. We can do the same graph as here but just find only things imported from our, our project. So also you can see code coverage, but not only test coverage, because coverage model can also track, for example, stuff used when you use the site you can run, if you have a web app you can run your server with coverage. And you do some things and you see what code was, was actually run. So it's good if you have, if you don't have tests, you can use coverage this way. But also here, as I said, in the beginning, modules can be imported in an untrackable way, especially in Django, when you have middleware, which are strings, strings with the module path, or installed apps. So, yeah, you need to think about it. Okay, so let's, let's talk about level advanced. There's a tool called Vulture that is, that is finding unused code, but it is giving us lots of false positives. As you can see, as you can see here, variable field sets is used by Django admin, not explicitly in the code. This is used automatically found at news by Django or imported in the settings. So there are many problems with it. But for some things like for classes or functions, it is the findings of Vulture can be, can be helpful. You always need to think that the Vulture doesn't know everything, it just sees at the code. And also it is, it is good if you run Vulture on your code to exclude the, of course, tests, because even if your code is unused, it might still have tests that imports it. Finding and removing that code is, is, is complicated. It's better to just get your code clean. For example, with classes, Clean Architecture or Hexagonal Architecture can help you or using Mixins, because Mixins won't be used in config files. If you see unused Mixin, it's probably, it's probably really unused. Or if you have registered classes or just group classes somehow, it is easier to spot the unused ones. About methods, it's pretty much the same. So if you have for methods, it's good to keep the interfaces or protocols for functions, you can separate them as small, as much as you can. So that you will see the missing, the missing, the functions are unused on the coverage. And, but here you can, here and with the attributes, there is dynamic access from, get out from Python, which can prevent us from finding out this. And about attributes, class attributes, it's good to group them into data classes or named tuples. So that it will help us to, if we, if we have to remove something, we have to remove it in one place. And about variables, piling is pretty good with finding out which variables are used and which not. So to sum up, PyFlakes finds unused imports, MyPy keeps class interfaces piling finds lots of unused stuff. And you can code coverage, clean architecture and good practices to help you here. Okay, quick one about duplicated code. As you can, as I said previously, there's dry and there's wet, so write everything twice. And sometimes the duplicate, it's good to assume that duplicates start from three, because you don't need to always go for the same, always track the duplicates. And about tools, there are no modern tools that could help you. There is old clone digger, which is pretty awesome with finding duplicate code. Piling also find duplicated code, but piling findings are exact matches. Clone digger analyzed syntax tree and didn't find, for example, duplicated code with different variable names. We are pretty much left alone on this road, we need to write a good code, keep the good practices in mind, so that we won't find out after some time that we have lots of duplicated code. Yes, so we just need to find out which is used where and do a lot of code review and good practices so that it will help us detect any problems. Also, the ID is I pretty have many extensions that could track the duplicates or unused code. So just check if your ID has anything like that. And that's all from me. Thank you. I had to speed up in the end, but I think I made it. Thank you. And do you have any questions? Yeah, it's time for questions now. Thanks a lot for your talk. Wow, that was really good. So we have one question. Is Vulture a software? Yes, Vulture is a Python package, but also it's a CLI tool. You can install it with PEEP or with their OS package. All right. Right. Any other questions? You can pop in the questions in the QA window. Let's see. Where's the QA window? All right. We'll wait for a couple of minutes. And if no one has any questions, you can follow with Rad in the Microsoft talk breakout channel. I'm posting the link to the same in the Microsoft track channel. Okay, thank you. Yep. Thanks a lot, Rad. It was really nice session. Yeah, it doesn't seem like there was any question coming. Okay, I now see the QA questions. Okay, I'm seeing. Okay, so that says yes. Thank you for keeping the room. Yeah, so there's a question. Do you have a process to detect dead code? Process. I usually start with Vulture. And as I said, I start with looking for classes and functions in the Vulture log because it's most probable that Vulture will detect unused class or function. And also, if the project has some tests, I run the test coverage to see if the parts with missing coverage are really used. Because sometimes it's easy to spot, especially if you have, if you are measuring the branch coverage, if you have branch coverage enabled in the coverage RC file. You can see, if you can see a big branch, which is uncovered, which means that means that either the tests never touched it or maybe it is really unused until you can find it. So, in most cases, it is just finding possible places where there is unused code and checking it manually. Later, verifying it by a human. Thanks for answering that question. I think that was really good explanation. Okay. So, if no one has any questions, maybe we can conclude this session and you can follow up with the red in the breakout channel named talk decoding joy of deleting code. I posted the same in the Microsoft channel. You can follow on that. Thanks right for joining.