 Hello folks My name is tin and it might be a bit a bit of the surprise for you who have seen the schedule This talk was originally supposed to be given by my colleagues than this love, but he has Called in sick, so I'll be replacing him the talks are not exactly the same But the gist is very similar. So if you read his abstract, it's pretty close. So let's get on with it I'm going to talk about refactoring about changing your legacy code to meet some modern standards I'm going to talk about why what's the point how to do it and how to do it? Well, I'm also going to touch on to the topic of throwing it all away Is there any point in keeping that old code when you can rewrite something much nicer? But first some introductions. I am tin. I'm a team lead at kiwi.com Leading the booking back-end team. It's web development. I Love software architecture. I enjoy Solving problems in a way that makes sense in delaying decisions in trying to make as much With as little information that I have I have some experience working in Python open source if some of you have heard of edX and Right now I'm a developer at Kiwi So I've seen a lot of troubled older code that needs Developing that needs working on and that needs people to give it some love and I'm going to be sharing the experiences of this today So yeah, what's the point? We are going to be learning how to read from older code how to see what's there We're also going to be respecting what's called Chester tones fence It's a principle mainly used by Wikipedia where you're not supposed to alter anything You don't understand because if somebody put it there, there's probably a reason why nobody removed it yet We're going to push for incremental changes. We're going to focus on modernizing things not reinventing them And I'm going to mention tests naturally because a lot of legacy code is known as the code That's almost not tested at all. So we're going to talk about how to make that happen So yeah, this is a quite a bit general topic some examples will be provided and they'll be Specific and we're going to cross it in some three chapters. So to say we're starting with easy wins Which may be interesting for majority of you. These are tools and Approaches that can be done today To instantly make your code base better we're going to cover some patterns and anti patterns some things that you may see and Encounter often and how to change them and then we are going to talk some philosophy some practices we use in our Work structure for our company which may be useful for those of you who work in smaller companies or startups That still haven't developed all this methodology So yeah, easy wins as I mentioned, they're easy. There are things you can do in a day There are plugins libraries utility software some scripts things you can run today to make your working life easier Instantly they are great, but they usually don't fix the root cause of why legacy code is legacy code We're going to go through them anyways because they are just great stuff to use So we use a lot of automated tools to assure our code quality Because tools are cool. You set up a script. You'd make a decision and that decision saves you so much time How many of you do code reviews at your companies? Could you raise some hands? That's great. Almost everyone so Code reviews can be a pain especially if things are not automated your colleagues Maybe nitpicky you may have problems. You may argue about spaces or tabs about in the station styles About where to place that bracket and things like this waste our time. They waste a lot of time That's why we try to make all of these rules and we try to make them all automated so you press a key binding and key binding and Everything is automatically formatted. We try to avoid any arguments that are trivial So code reviews can focus on the actual code and not ego fights So yeah for this we use linters to most famous linters our pilot and My pie my pie is more of a typing software, but they're similar they run the code To check if it follows these rules. It is they are full of industry practice. So you don't have to double guess most of it and Many companies use this. How many of you use pilot weekly? Majority and how many of you do automate it so you don't have to run it yourself That's a decent number on the half. So The rest of you you should automate it It's great thing to have automatically to check your code before it enters the master branch Before it gets shared to your colleagues If it's automated if it's not automated people will skip it There will be reasons for not using it and it's not going to be good My pie checks that your code annotation your typing annotations. I've seen a talk yesterday that mentioned these It checks if they follow What's written in the code how your code works? So my pie will check that your code follows the types you've set down So it's not just an annotation in your EDE. It will have to be practically viable as well And it's great because it's an opt-in thing. It's a thing you use for a single function to run it to have That functionality just for the function itself. That's great Because if you have a large code base if you have a messy code base You know that the majority of your code cannot be typed easily but you start you start with one two three functions and as you grow your code base as you cover more and more these Practices rub off on to more code and eventually you achieve Typing at least in over half of your code base and it's easy to get it rolling You don't have to stop drop everything and start focusing just on typing You can develop features as usual while just sprinkling a little bit of typing here and there So yeah black how many of you use black? I talked about black on a lightning talk in a pycon UK and I was in love then I'm still in love It's a code style Formator that doesn't let you configure it. This sounds like a bad idea for you who didn't see it, right? You cannot configure anything, but that's what makes it great. There are no arguments It's how it is they accepted a lot of feedback from the community They set it up and it works and a great thing is that it checks the python AST To make sure that the code runs exactly the same it compiles it in a type of Speaking to make sure that you didn't make any syntactical changes by formatting your code. That's invaluable so Then there's koala koala is Some kind of a framework that runs many tools in a very modular Framework bases. This is maybe the most advanced of these tools and it's a bit Too complex to cover in a single talk and you can check it If you want it also runs fixers So a lot of issues that the other tools just show you koala offers automatic fixing for it's a pretty awesome tool so yeah, this is a simple example of Some function that we ran through the automatic code inspection and it cleans up a whole mess into a very nice documented if useless function and Thing is The things that you cannot automate the change off you can block the developer from releasing code if it doesn't Pass the checks. That's great That's something you can do in a week and then every developer will have to check up what they're doing how they're Doing their code and they will not be able to take the lazy shortcuts So yeah, these tools make discussions these tools make you Not have to tell your colleagues to clean up their code. They're automatically blocked and they will have every change matter It's a great win because you think about real problems. You think about things that matter logic and Code quality and not about line breaks and other Somewhat nonsensical things. It's an easy bump. It will not fix your code base. Let's be real about these things It's not going to be a cure for all the problems you've been having, but it will help you focus on them more So what will help you more is? introducing some better patterns and Discovering what are the anti patterns in your code base? So when you have a code when you have code that's hard to use It's usually because that code is very surprising that code does things you cannot expect it to That's what people call with a that people call out with the principle of least astonishment Basically, if your code base Astonishes you every hour You're going to have a very slow pace at making changes Generating updates because every time you think something is going to work. It breaks and it's a versa It's equally bad if you think that something broken shouldn't work and it actually does That's sometimes even a bigger problem. So yeah legacy code often astonishes people How many of you have heard of historical reasons when you've asked about the bad change? Yep, it's a common thing. It's a common thing that somebody can say. Oh, we did it this way it's very bad, but we had a really good reason back then and This may work shorter But the more of these you have the slower you are at developing the slower you are at Getting changes out and there's more opportunity for mistakes to happen for outages crashes bugs for things to break And we don't want our code to break So yeah, you can detect these by choosing for code smells Those are symptoms of some bad code of some bad architectural decisions They have they are showing you where code has been neglected where somebody was inconsistent Things that shouldn't be there and they're usually because of these reasons because of some deadline of a coast cutting Somebody was supposed to have a week, but they got It got released after two days prototyping things like that there There are plenty of reasons why somebody may hurry up a developer who will then do a shanty job of his code So yeah, easy ones are super easy to fix. It's a couple lines of code It's somebody not following your formatting logic not using list cooperation properly things like that. They're they don't really have scope They can be fixed in one afternoon by an eager person then you have the medium ones the hefty ones which are some mistakes that are Patterns or anti patterns as it may be in your code base. These are mistakes that people repeat because They see them all around the copy paste code. They figure out if they did it this way. I should do it as well these mistakes Respawn they happen all over and People start reusing them often and there are some of the worst problems Then you have the hard code smells the Things that everybody notices and everybody knows it's wrong, but you really cannot remove it It's bad choices of framework. It's bad choices of how you structure your entire code base It's a very bad decisions that were made at the start of a project and this is the usual the usual reason to rewrite everything and Sometimes that may be the only cure, but you can also work around most of these if you have enough time and determination So yeah, here are some examples from our own code base at Kiwi We have an easy one where people were adding airlines and adding them currencies and these currencies Started repeating. This is maybe three realized a bit, but we had something very similar where you had dozens of ellipse all replaceable by a single dictionary and We replaced them and it ended up saving us Like 50 lines of code for just a simple dictionary lookup Then we had a bit more medium a bit more dangerous pattern Where people would just use a dictionary as a general dump of all information they would add data and return data as a dictionary and Every Part of this function would just modify that dictionary in place it was a nightmare until we managed to get rid of it at least most of it and That's a that's a problem. That's a big anti pattern and the hardest one in knowledge that I had no is The orm we we used to work with raw SQL queries and we use those queries directly We didn't actually type our database We just use a dictionary that was returned From our SQL query and then did work on it. That's a bad idea trademark Basically, it meant that we didn't have typing anywhere and that our database changes would break off our code Without us even knowing we changed that by adapting a scale alchemy and Creating an object layer where we typed everything we got from the database with those objects representing our Changes it helped we didn't adapt a very strong framework because we tried not to we tried to keep to lightweight frameworks and modules to keep changing easier but adding a scale alchemy saved us a lot of time and And to work with these to know where you need to make changes and what's a good thing to change Great to is sonar cube it's a static analyzer that you can install that you can subscribe to and it analyzes your code base through your get Get a repository of choice and it analyzes bugs code smells It adds security oversights that it knows for different languages in this case python It checks your test coverage trends who adds code that breaks tests who adds code that's good And it attracts that comments and docs are made everywhere and what's great It does it in your source management tool for example in git lab It directly comments on your very emerged request telling you that your method doesn't work well doesn't follow standards and To make it even greater each of these Identifiers have these little blue book you click and get a full explanation of why is this a bad change? Why is this a good change? so it's a great thing to Provide for junior programmers because then they know Okay, we're not forcing our opinion. We have a whole lot of reasoning for any restrictions we make so With these tools that will show you where you're making issues in your code You can recognize some anti patterns that go throughout your code base wherever people work in a team There's always going to be people who are Easily impressed who follow a direction that's already there and they don't They don't question it too much It's what happens when your code grows organically when you get changes from people who are just enjoying their work They're not thinking too far into the future. They're copy-paste coding often and It's a normal thing in smaller companies. It happens everywhere So for us one of these were the magical methods so to call them Which were just the antithesis of functional programming where you would get a lot of things happening on a very simple Function you would never know that the function at its dictionaries that you didn't even pass to it It's a implemented side effect that was later Replaced by better object-oriented approach by making Stricter data access layers, so you wouldn't be able to change anything in any function But we had a lot of problems as developers would see this Would see that a function is able to change anything and they would start doing it as well It makes things easy when you can just edit a global variable, but it doesn't make them very constructive and we had a very unique problem I would say that we had functions with dozens of decorators That's very I've never heard of anybody else having that problem and if you had a Codebase where you would use over six or seven decorators come talk to me to the stand I would like to hear your experiences But generally decorators should be explicit and they shouldn't replace method calls if they don't need to and For us we had these huge chains and people would see that They would see oh decorators are a cool thing and they would write their own They would also add them and we had problems with that We had a lot of problems teaching people that no decorators aren't the greatest thing ever So yeah, these things were anti patterns that were spreading organically because people would see think it's a cool thing They didn't know better. They made problems. We needed to push some better patterns to have newer code that would Succeed that would flourish better because we separated from these older messier structures We did that by creating some kind of an interface not the Java or other hardcore object-oriented Programming interfaces. It was more a bit of an abstract module that we put all the interfacing code in We tried to hide mistakes of yesterday. So people would see okay. We're hiding this actively because it's a bad pattern Let's not do it again So yeah, we would find the common usages of a pattern and then replace it with something that would point out It's a bad idea and it should be done differently We would try to find that use case. It's trying to solve and create a replacement that we would promote there And in the edge case, we would re-implement so people would see okay. That's how it's supposed to be done We also created these facades where as we add a smarter function a smarter object It doesn't always interface with the rest of the stuff easy. It doesn't go easy to the Rest of the code so we would create some mocking Objects that would hide all the complex functionality and boil it down to a single function So instead of a user that you can add a password that you can add Username change etc for we would just create a function change the user's password and it would instantiate the user object and Explicitly say this is how you do it when you can So yeah, we also inverted this principle as well Where we tried to hide that old code in a better? bubble of functionality You use an interface that is class-based in the behind it you actually use all the Global logic, but you try to make it explicit that this is not supposed to be You create a contract that people who work on this project will try to follow So yeah, it's almost never pretty after you grow and after that hacky project of five people ends up being a corporation with 200 but you cannot really throw it away because It's how it's how it works. It's what brings you money or success or research or however You use it and you cannot really throw it away because it would be a huge road black So you try to create this bubble of cleaner code try to interface around it and try to get everything to be Explicit so if you're going to take shortcuts you make them very explicit and you teach people this is not the way But we have to use it so with this we've covered the Patterns and t-patterns and some tools But most important of it all is to try to instruct your peers to Follow these rules to try to enforce them somehow basically We can talk about good practices as much as we want if somebody ignores these rules. They are not going to follow them and For that you need to get people to think a bit out of the box you need to push People to realize that they need to change themselves as well so yeah You need to approach this problem slowly you cannot throw it all away because people will get thrown off incremental steps help you adapt With time when you make a change leave it a week Give it a week so people can figure it out read through the code and realize okay. This is a great idea These incremental steps will let everybody adapt and work with your code and Force code reviews. They are a great thing. You can have Required tools to pass and don't allow anybody to add code that wasn't reviewed So try to bake in protections against this and split the responsibility Don't say that that code review is just there if something breaks Required a reviewer to assume some of responsibility and help fix it as well because they didn't notice breaking This way you get people to actually try to cooperate and I just do it for practice and Yeah, it will help you reduce the bust factor of your company if all code needs to be covered by at least two people So keep it blame us as well. Don't blame people for Not knowing things for not Realizing things when you review make it impersonal and go through the tier system Keep people on the track to look over the overall scope to figure out. Is this working? Does it fit our system and is the code clean? By following these three steps you keep reviews manageable in length and people will do them Happily when they don't know that they don't have to rewrite everything for several times Try to educate your people make sure that your devs understand why how and Why are we doing this focus on documentation? I don't probably don't need to tell you about this But documenting why is the bad reason there is also useful? Why is the bad there? Because then people will understand that somebody else had the same logic and that it ended up being not that great Explain it explain how things were and how things should be so everybody can feel a part of the process There's no easy win here. You cannot Make your code great overnight it increases slowly and tooling doesn't replace good engineering That's why we I called all those tools easy wins quick wins They are great. They will help you, but they will not suddenly make your product work better. It's just a step there And also manage expectations teach people that code is written to be replaced There's it's not good if there's too much ego in programming because there's always improvements, and they're always there and Eventually you want to have all your code Replaceable overnight so it doesn't depend too much on each other So it doesn't depend too much on other implementations separation of principles pretty much but a lot of people don't realize that and And yeah explain people that code debt is real debt that having Bad code will eventually cause things to crash to stop and that mistakes will happen more and more it's a problem sometimes for you who have a lot of managers or a strict management to explain why why do we really need to make these changes? Why do we really need to update things and Explain them in simple time. It will always take time to work around a bad code base Basically convince them that mistakes cause losses and that code debt is to blame and not the developer Developers aren't all powerful and in a work day. There's only so much surprises you can you can have from your code So yeah, basically a low quality code is a symptom. It's Thing that Happened because of bad decisions of bad causes But you cannot fix it overnight go step-by-step and try to keep it consistent try to keep it a philosophy of the company and not Just your own one-day inspiration. There's no winning this overnight. It takes a lot of policy changes and a lot of reviews and introspection So yeah, when you have old code it tells a story There's a reason why most of those decisions were made that story needs to become better It needs to modernize it doesn't need to be rewritten First grab the easy boosts add some tooling make it obvious that people want to make improvements Try to rewrite the failures you have in bubbles one by one Isolating them using any type of abstraction you want some facades and then maintain quality going forward teach your people how it works and why it works so and Maintain that quality So thank you for your attention I'm up for any questions if there's a quick question or two and I'll be at the Kiwi stand Afterwards if you want to ask a question in private so anyone Thank you team Have a question there Yep. Hello. So one question about automation of piling my pie. I know that from my trace You can't add to get hooks running piling by default. How would you? Did the automation stuff for your code before pushing your code to your We have the we have the hooks git hooks added there and Part of our repos so everybody pulling gets those files as well And we also have a continuous integration So git lab the server runs our code checking tools and doesn't allow you to merge if you there aren't green Okay, thank you no problem Hi Thanks for your speech. I have a question. I had a manager once a tough one and I was trying to explain to him that we need to make some refactoring in in our code base huge refactoring because it's going out of like being very old Fashioned old style and have having many mistakes and and yeah He always asked me Why and I said the same as you Time but then he said he was asking for Hard numbers and I was wasn't able to Estimate that numbers and what could you advise in that situation? I would advise that you create a small proof of concept and MVP with like smarter technology and Track the time it would probably not take that long as adding the changes to the existing product and show him Okay, I made this MVP in three hours. I will need two weeks for this functionality Maybe the numbers will not be as correct as the reality But the the scale itself will be completely different at least we've found it to be Thank you. Thank you again. We have that's all the time Thank you