 OK, thanks a lot for coming. Yeah, I'm Christian, Christian Lidderman. I work for an enterprise technology management company. And today I will tell you a tale of two kitchens or how to go about hyper modernizing your code base. So what I'm going to talk about is what is hyper modern Python? Why we would like our code base to be hyper modern and how to get there from our legacy code to a nice hyper modern code base. Yeah, what is hyper modern Python? Hyper modern Python, actually, the idea stems from an article series with the same title by Claudio Jolovic. And it's an opinion-native guideline about best practices and clean code in Python in the 21st century. So that is the hyper modern Python cookie cutter. So that's from the readme of the repo. I won't go through it. So let's run into it. A tale of two kitchens. So just let this thing get up. So which kitchens do you think is better in terms of security, health and safety? Where would you deliver faster, deliver higher quality out of? And if you had to work in those kitchens, where would you get better job satisfaction and personal growth? So if you think it's Kitchen 1, please raise one hand. And if it's Kitchen 2, please raise two hands. I just wanted to see your whole audience doing the order. And it's not that our kitchens sometimes messy. Sometimes, actually, there is a fire in it. Yeah, I tried to get a picture of a kitchen fire in. But I wasn't successful. So you have to Photoshop that in your mind. Nobody seems to take a selfie with a kitchen fire. OK, let's talk about why we actually want to clean up our code base and make it hyper modern. So first of all, minimize our context switches. If our code looks the same everywhere, we have less mental overhead to switch in between different code styles. And it's a lean principle. We want to eliminate waste. Sorry. So our fiction is low. Sorry, a bit about. I'm a bit nervous. When you think about broken windows, so when you have an abandoned house, as soon as the first window is broken, the next windows will follow suit. And it deteriorates from that in amazing speed, actually. Or when you think about your Boy Scout rule, always leave the place better than you found it. It's so much easier to leave the place better than you found it if you found it in a relatively good condition in the first place. So all these are to improve the quality of our code. Yeah, how do we start? We start small. We start simple. And start narrow. So and where to start? Yeah, pre-commit is nowadays pretty much our weapon of choice to execute code when you do modifications. I don't mean the pre-commit hook, actually, but the pre-commit Python package. And what you won't have much to discuss about is imports. I sort will sort your import just fine. And if you have legacy code that's still from ..import star, then with absolute defy imports and remove star, you get all your code into consistent format. Speaking of consistent format, the next step is then black, well-known uncompromising code for matter. And yeah, it's a bit more intrusive than I thought. But yeah, you will find this really helpful. PyUpgrade and Flint are examples of tools that bring your code base from earlier Python versions into, yeah, the newest Python style, doing reformat old string formats into F strings and similar things. And we want, ultimately, we want to test our code with Flake 8 and plugins. So we have even more control about how we want to format our code. Yes, if you first introduce a new plugin for Flake 8, mostly you have a lot of violations that you then comment out with noQAXY001. And yes, QA is a little tool. You run over it. And if it finds a line with noQA, some error code. And that error code is actually not raised in that line. It's like, OK, this comment can go. Also keeps your code. PyDia, let's try that. Security, there are automated security scanning tools out there as well. First of all, a bugbear. Bugbear, well, it's not so much a security tool, but it alerts you to really common mistakes and caveats, like passing a list as the default value for parameter. It alerts you that you should better not do that and apply. Bandit is a security scanner that is really focused at security, SQL injection, collection, cross-site script exploits, and such things. And safety and dependent bots actually will scan your dependencies, see if they are still up to date, or if they're even security issues for your dependencies. You improve for your measure. And the easiest thing to measure is your test coverage. So there's a good old coverage, of course. And tool building on top of it is called diffcover, so which measures the coverage of your current pull request. The next thing is what is easy to measure is the complexity of your code. McCabe, Radon, and Xenon are the better-known tools, and they do a pretty good job. And the newer tool is Lizard, which I tend to go with Lizard because if Lizard thinks the code is too complex, it is most likely too complex. McCabe and Radon can be harder to interpret. And then only two years old, I think, is the cognitive complexity, also available as a Flake 8 plugin, which takes more into account how a human actually processes the code, so not only decision points, but also recursions, for instance, to go into the future. OK, typing. OK, we want our code hyper-modern. Should be typed. And yeah, my pipe is the go-to tool, how to ensure that my types are good. But it's a real big task to type annotate a legacy code base. Luckily, there's a monkey type, I think, from Instagram, which actually observes your code while you execute it and observes the types that are flowing into your functions and return from your functions. And then with that information, it gives you a rough draft of type annotation. So you don't have to do it all by hand, but you get an educated guess by the usage of your code. And Pyre, the type Facebook answer to my pipe has a command Pyre infer, which infers from the code flow it observes statically and the types you already have in your code, infers the type that probably are used in the code that builds upon it. PyType from Google, pretty much just the same, has a slightly different command line interface. So that's where we are with static type checking. We also can, of course, type check at runtime. Type guard is an example. It comes with an overhead, so you probably don't want to, at least not immediately, put that into production. But you can use type guard for your tests, meaning that you observe your tests and that you are really passing the right types around when you're testing. Talking of tests, you need a little love, too, when we are hyper-modernizing our code. Tyit, if you still use unit tests, try Tyit. It makes it so much more, it affects your code to have much more precise assertions. And it's really great for legibility. PyTestify and unit test to PyTest are both tools to convert your old unit tests into PyTest. So hyper-modern testing, yeah, hyper-modern Python, actually, the article series does not have big opinions about testing apart from PyTest. And I just want to throw something into the ring here. And that is hypothesis. Hypothesis enables you to do property-based testing, which really means that hypothesis generates lots of test data for you, throws it at your functions, and then see what comes out. There's even a little tool, Ghostwriter, in hypothesis. I haven't tried it, that's why it's that tries to write hypothesis tests for you based on your function signatures. And if you're working with web APIs, try Schema Seizes. Schema Seizes is built on top of our hypothesis. And it, you pointed at an open API specification or the GraphQL specification, and it generates tests for you. It generates test data that is valid according to your specifications. You'll be amazed. Yeah, are there any Q8 persons in here? Oh, OK. Yeah, and Schema Seizes is also available as a service. So you don't need to be a developer. It's available as top versus service. You just pointed at an open API endpoint, and it generates the tests, and it really comments your code. OK, Chris Cosodius, who is watching that watchman? How do you know that your tests are actually testing what you think they are testing? And 100% test coverage, are you really sure if you change something in your code that your tests will test that? Probably not. I'm pretty sure about that. I tried a mutation testing tool, which pretty much runs all your tests, and then changes just a little bit in your code. Instead of x equals y, it says, OK, if I change this line to x, if x less than y, or x greater than y, will the test break? If the test break, that is a bad thing. If the test break, that's a good thing. The tests are testing the right thing. If you test path, that is a surviving mutant. That is a very bad thing. You didn't test for that. This is when I said monkey type takes more time to run with monkey type, with mud, mud. This explodes exponentially. So yeah, you have to be very specific. Your core business logic, actually, is what you want to test with this kind of tool. So we have an upgrade on a regular basic. PyUpgrade assists you with getting your syntax for the new update with the new version. And then also tools for specific frameworks. PyUpgrade and Django code mod, for instance, will convert, I think, Django from version 1.11 up to 4.0. And if you're working with Django, that has changed quite a lot. And it does a pretty decent job at it. You can also roll your own code modification tool with libcst, cst for concrete syntax tree that does all that. There was a talk on Monday I wanted to attend to tell you a bit more about it. That was unluckily canceled. So sorry, this slide is very short. OK, refactoring as a service. Sponsors here, you can just look them up. Sorcery, I've used sorcery for years. It does a really, really good job for small refactoring. Sonar Cloud is kind of in the same problem space. They are downstairs, too. Have a look at them, talk to them. And Metabob is a kind of new kit on the block. And yeah, when we are thinking back on test coverage, coverage.io is a test coverage as a service software which does a really good job at highlighting your pull requests. What is covered was not covered and so on. So where do you want to go from here? Right now, we pretty much refactored our code line by line. That is not what real refactoring is about. It's more about don't repeat yourself or if you write everything twice to see patterns emerging. And there's also the solid principle, single responsibility open, closed, list of interface, segregation, dependency and inversion. You should know them. And the more, more cupid principles which originated in a talk why every single solid principle is wrong, at the end of the day, cupid and solid are not so different. You should read up about both of them and then get your own philosophy out of that. And when I say here principles, it's not like Isaac Newton's principier, these are opinions. You can, these are opinions. This is not like the law of gravity. You can't argue with gravity. You can't argue with all of this. Those are, yeah, means to achieve an end. What do we want? We want to maintainability, extensibility, modularity in our code. And always remember, perfect is the opposite of done. Do you have still the picture in mind how we thought our cushion would look like? Well, we are not quite there. But this kitchen is so much better than what we started with. And it's much more going to work in a kitchen like that. OK, in summary, we talked a little about what hyper-modern Python is, why we would like our code to be hyper-modern, and some tips and tricks how to hyper-modernize your legacy code, and a bit about refactoring in general. OK, done is better than perfect. Goes for talks too. Thanks a lot. If anybody has questions. Do we have any remote questions? No. So if there are any questions in the room, please use the mic. Thank you very much. I really enjoyed that. Yeah, if the worst legacy code base you've ever seen, what's one first step I can sell? Yeah, I thought import order. Nobody argues about that. Just do it. That's the easiest step to get started. And at the same time, introduce pre-commit, so every time it's executed. And then black and further and further. Any other questions? If not, then Christian, thank you very much. And just another round of applause.