How to Avoid Refactoring Legacy Code HELL

  Рет қаралды 35,770

ArjanCodes

ArjanCodes

Күн бұрын

In this video, I’ll teach you a 5-step framework for refactoring legacy code. To show you how it works, I’ll do the so-called Gilded Rose Kata, originally created by Terry Hughes.
🐱💻 Git Repo: git.arjan.codes/2023/gildedrose
🌹 Gilded Rose Kata: github.com/emilybache/GildedR...
👷 Join the FREE Code Diagnosis Workshop to help you review code more effectively using my 3-Factor Diagnosis Framework: www.arjancodes.com/diagnosis
💻 ArjanCodes Blog: www.arjancodes.com/blog
🎓 Courses:
The Software Designer Mindset: www.arjancodes.com/mindset
The Software Architect Mindset: Pre-register now! www.arjancodes.com/architect
Next Level Python: Become a Python Expert: www.arjancodes.com/next-level...
The 30-Day Design Challenge: www.arjancodes.com/30ddc
🛒 GEAR & RECOMMENDED BOOKS: kit.co/arjancodes.
👍 If you enjoyed this content, give this video a like. If you want to watch more of my upcoming videos, consider subscribing to my channel!
Social channels:
💬 Discord: discord.arjan.codes
🐦Twitter: / arjancodes
🌍LinkedIn: / arjancodes
🕵Facebook: / arjancodes
📱Instagram: / arjancodes
♪ Tiktok: / arjancodes
👀 Code reviewers:
- Yoriz
- Ryan Laursen
- Dale Hagglund
🎥 Video edited by Mark Bacskai: / bacskaimark
🔖 Chapters:
0:00 Intro
0:36 Steps for refactoring Gilded Rose
31:19 Framework
35:27 Final thoughts
#arjancodes #softwaredesign #python
DISCLAIMER - The links in this description might be affiliate links. If you purchase a product or service through one of those links, I may receive a small commission. There is no additional charge to you. Thanks for supporting my channel so I can continue to provide you with free content each week!

Пікірлер: 160
@ArjanCodes
@ArjanCodes 9 ай бұрын
👷 Join the FREE Code Diagnosis Workshop to help you review code more effectively using my 3-Factor Diagnosis Framework: www.arjancodes.com/diagnosis
@devvbob
@devvbob 10 ай бұрын
This is surreal, never have I ever seen such a clear requirements specification!
@Dyanosis
@Dyanosis 10 ай бұрын
Clearly not a real requirements spec. No User is ever that detailed or knowledgeable about the changes they want.
@corsaro0071
@corsaro0071 9 ай бұрын
My first thought.
@Betacak3
@Betacak3 10 ай бұрын
9:27 IMO Copilot generated a bad test here. If the quality is 0, it's not going to drop any further, regardless of whether the item is Sulfuras or not. It would've made more sense to test this with any other value. That's why you gotta check your AI generated code!
@Arunnn241
@Arunnn241 Ай бұрын
I agree. A few of these tests have confounding factors and so they aren't testing the specific functionality they say they are testing. Otherwise, I'm genuinely surprised how copilot is able to create these from the rest of the files/requirements
@Conciliabo
@Conciliabo 10 ай бұрын
This is literally like one of those satisfying pressure cleaner videos just for python code. Thanks Arjan!
@ArjanCodes
@ArjanCodes 10 ай бұрын
Hahaha, that's the best comparison I've seen so far! :)
@allo5668
@allo5668 10 ай бұрын
THIS!!! This is an amazing video. Make more of these, it explains exactly how to go from beginner to intermediate. It’s so clear!
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thank you so much- glad you liked it!
@Betacak3
@Betacak3 10 ай бұрын
"Have you ever been in a situation where you had to work on legacy code?" Working on legacy code is half my job. The other half is writing new legacy code.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Nice 😊
@Dyanosis
@Dyanosis 10 ай бұрын
I'm also pretty sure that, at some point, every dev touches "legacy code". It also depends on your definition of legacy.
@owenjones9640
@owenjones9640 10 ай бұрын
I'm in the process of refactoring a pile of legacy code right now which looks a lot like the example you started with, so this video really helped me frame my approach more clearly. One thing I would add is that you may need to go through this whole process (steps 1-5) several times before you're happy with the result, as your understanding of the system gradually improves with each successive refactor and you think of more test cases to add.
@haxwithaxe
@haxwithaxe 10 ай бұрын
I've looked at someone else's brand new code and wanted to jump out a window.
@Kevin-jv7mz
@Kevin-jv7mz 10 ай бұрын
This
@Dyanosis
@Dyanosis 10 ай бұрын
LOL Haven't we all.
@marcolaube2957
@marcolaube2957 10 ай бұрын
I've looked at my old code and wanted to jump out of a window
@haxwithaxe
@haxwithaxe 10 ай бұрын
@@marcolaube2957 I thought that was such a universal experience that I didn't bother mentioning it. XD
@ArjanCodes
@ArjanCodes 10 ай бұрын
It’s become clear to me that we immediately need to stop putting developers in offices with windows.
@roPe_A
@roPe_A 10 ай бұрын
I am a PhD student and my suprvisor told me at the beginning of my studies to develop a hydrological model as a part of my thesis and to create a desktop software with GUI for it. I have never touched programming before but your videos about everything made my learning so much easier and I really appreciate the refactoring advices you have shown not just in this video. Also tutorials on dataclasses, protocols and other stuff really helped me with finishing this rather large project of mine. So thank you for making my studies so much easier! Maybe I should provide this project for smelly code roasting videos.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Wow! That's amazing! If you join my Discord channel, there's space for code roasts/smells, you can submit your project there. :)
@billgates3229
@billgates3229 10 ай бұрын
Your opening remark about jumping out of a window made me laugh out loud. It reminded me about my job as a software developer just before I retired several years ago, where my team was faced with converting a mountain of the most convoluted and awful-looking legacy code to a new technology. How that legacy code came into being was due mainly to a lack of proper software-engineering management, e.g. how to assure quality code, how to assure developers are adequately trained in how to write quality code, and providing the necessary oversight of unskilled developers. Most of that code was churned out by several very smart unskilled developers.
@tacozmacleo
@tacozmacleo 10 ай бұрын
Nice use of min & max functions. Have never thought about that before. 😅
@saminyead1233
@saminyead1233 5 ай бұрын
I've never thought of using max like that before!
@johnabrossimow
@johnabrossimow 10 ай бұрын
I've been using knowledge from your videos and I noticed I am writing smaller classes, use functions more, and use composition more. I am still learning all the design patterns, might have to read a book now. Regardless, my code has improved as a result. It is less bloated, writing documentation instead of comments, more reusable. I'll have to hear from others if what I write is readable though lol. Thanks a lot!
@ArjanCodes
@ArjanCodes 10 ай бұрын
Wow, that's actually amazing to read! Thanks so much for your kind words. :)
@malteplath
@malteplath 10 ай бұрын
I'm taking away two things from this video: a) there are actually refactoring katas b) you are very good at driving home the message of test first. You may read this as TDD, but whatever the case, the existing system is performing some task according to current requirements, so you have to make sure you don't break that. Many thanks Arjan!
@ArjanCodes
@ArjanCodes 10 ай бұрын
You're very welcome! :)
@szabolcsjobbagy30
@szabolcsjobbagy30 9 ай бұрын
The BEST video on Refactoring, I could create a refactoring checklist for myself, and it shows perfectly why unit testing is inportant. Thank you very much!!
@ArjanCodes
@ArjanCodes 9 ай бұрын
Thank you - you’re welcome!
@pablofueros
@pablofueros 10 ай бұрын
Please more of these videos!!! They are great to learn from an experienced programmer point of view. Keep the good work! Edit: After rewatching the video, I have a question. What's the purpose of the ItemUpdater protocol class you define?
@abdallahel-falou3849
@abdallahel-falou3849 10 ай бұрын
ItemUpdater defined a Protocol that’s later used in his method definitions. It basically defines the common methods that any item updater would offer, such that the method definition (or any other static type declaration) doesn’t have to be specific to the class given. In this way, it’s similar to Abstract Base Classes (ABC), with a little more flexibility since the “subclasses” need not inherit explicitly from the Protocol (“parent”) class. You can search about duck typing (that’s not a typo lol) and python Protocols to learn more about this.
@pablofueros
@pablofueros 10 ай бұрын
@@abdallahel-falou3849 Hi, thanks for your reply! I already knew what a protocol was... still appreciate it! I looked at the repo and noticed that it uses the ItemUpdater class in the ITEM_UPDATERS dictionary. That was the missing piece of the puzzle!
@croc541
@croc541 10 ай бұрын
@@abdallahel-falou3849 DefaultItemUpdater and all the derived classes are indeed compatible with the ItemUpdater protocol but, as far as I can see, ItemUpdater is not mentioned as a type hint anywhere. item_updater is simply retrieved from a dictionary. You could theoretically put an incompatible class into that dictionary and that would break update_quality_single() method. If we removed ItemUpdater protocol class, the code would still work, right?
@virtualraider
@virtualraider 10 ай бұрын
This is got to be one of your best videos yet! I just want to comment on my recent experience with this. In real life refactoring we may not have such clear starting instructions. So step one of analysing the code will often include writing down that behaviour. I usually find that simple flowchart Mermaid diagrams during the first step help figuring out what the code does so we can write those tests 👍 GREAT video ❤
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thank you so much!
@wtfbomb
@wtfbomb 10 ай бұрын
I'm always amazed about how you tackle problems by seeing it through step-by-step in a structured manner and with such ease. Really somethin I want to adopt and get better at for myself!
@JeffreyChadwell
@JeffreyChadwell 10 ай бұрын
This video was very useful, no matter what language you're working in.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thank you Jeffrey! Glad to hear you found it helpful.
@JeffreyChadwell
@JeffreyChadwell 10 ай бұрын
@@ArjanCodes This is also one of the best videos I've seen on TDD.
@WalterVos
@WalterVos 10 ай бұрын
We recently practiced this kata at work in our TDD Dojo using approval testing and code coverage reporting. Felt like black magic sometimes, but it was very effective.
@InglesConConfianza
@InglesConConfianza 10 ай бұрын
Seeing your thinking process here is so valuable. Thank you very much!
@tbpotn
@tbpotn 10 ай бұрын
I wish my legacy code at work looked like this. Or had these clear requirements lol.
@pintokatendejonathan1740
@pintokatendejonathan1740 5 күн бұрын
Thank you very much for this video, because I just saw this when I had to refactor old code from the company
@ArjanCodes
@ArjanCodes 5 күн бұрын
Glad I could help!
@mikefochtman7164
@mikefochtman7164 10 ай бұрын
Great stuff. As you were starting and I could see some of the original, I was like: "Oh, we should refactor this... split sellin and quality..." My mind started racing with ideas lol. Fun to see the design you came up with. One thing with older languages/ projects and legacy. More than once I came across a difference between the 'requirements' and the 'performance' of the legacy code. For one reason or another, the code didn't match the documentation. So when writing unit tests, if there is a conflict have to go back to customer to try and identify why. Often a lazy programmer in the past fixed / updated something but didn't update the documentation. :(
@Gustavo-ve9hr
@Gustavo-ve9hr 9 ай бұрын
Nice content. One can learn so much with an example like this one. Thank you!
@ArjanCodes
@ArjanCodes 9 ай бұрын
Thank you for the kind words, Gustavo! :)
@whkoh7619
@whkoh7619 10 ай бұрын
Amazing content. Thanks Arjan
@seanoverton798
@seanoverton798 10 ай бұрын
Can't reccomend your content enough to colleagues. Thanks again Arjan! Always enjoy the refactor type videos
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thank you so much! I really appreciate it. :)
@clusterbyte
@clusterbyte 10 ай бұрын
One of the most helpful and instructive videos about programming I've ever seen!! Thanks, Arjan.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Wow, thanks!
@Cincin21
@Cincin21 10 ай бұрын
Awesome video! Nice work Arjan!
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thanks! Glad you liked it
@juvewan
@juvewan 10 ай бұрын
This is beautiful!
@alberto.cartaxo
@alberto.cartaxo 10 ай бұрын
Great video! I think this is the best tutorial on the subject I watched
@ArjanCodes
@ArjanCodes 10 ай бұрын
Wow, thanks! Glad you think that :)
@ahmedtremo
@ahmedtremo 7 ай бұрын
Great Informative video, thanks for sharing!
@ArjanCodes
@ArjanCodes 6 ай бұрын
Glad it was helpful!
@abomayeeniatorudabo8203
@abomayeeniatorudabo8203 10 ай бұрын
My daily dose of learning. Thank you Arjan.
@aflous
@aflous 10 ай бұрын
Weekly*
@ArjanCodes
@ArjanCodes 10 ай бұрын
You’re welcome! 😊
@abdujabbarmirkhalikov5480
@abdujabbarmirkhalikov5480 10 ай бұрын
Great, thank you for your time and sharing knowledge!
@ArjanCodes
@ArjanCodes 10 ай бұрын
My pleasure! Glad it was helpful! :)
@Daniel-hc7kn
@Daniel-hc7kn 10 ай бұрын
Great video. I consider all code in production legacy code.
@takjakbyskadinad
@takjakbyskadinad 10 ай бұрын
I love the format.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thanks!!
@Soltaiyou
@Soltaiyou 10 ай бұрын
Step #3 is the capstone! Thanks!
@NZ255
@NZ255 10 ай бұрын
Have you got tips on how to make a PR when refactoring? Doing to step by step it makes sense, but if someone’s reviewing the final PR it can look like a sea of red and green
@ArjanCodes
@ArjanCodes 10 ай бұрын
You definitely don’t want to do all of this in a single PR. At least each step could be a PR. For example, you could first do a PR that adds the unit tests so everyone involved agrees that the tests properly reflect what the software is supposed to do and whether this is enough tests to feel confident to change the code. Then, move on to step by step refactoring and make a planning before of how to organize that into separate PRs. Then a final PR could be about adding the new feature. But it also depends on how large the codebase is, so you might want to split things up even more.
@thisoldproperty
@thisoldproperty 10 ай бұрын
Your never more than 50 test was interesting, as in not sure it tested for the scenario. I really appreciated seeing how someone else writes unit test cases. Great video.
@ArjanCodes
@ArjanCodes 9 ай бұрын
Glad you enjoyed it!
@fisher00769
@fisher00769 4 ай бұрын
I was looking through my external hdd the other day and found code I wrote like over a decade ago. As a self-taught programmer, resources back in the day on how to write good and efficient code were not even close to being as abundant as today. I thought it would be fun to sort of improve on the code, but of course it was a mess. There were no tests, classes with hundreds of lines of code and everything in one giant file. Not even halfway through refractoring I figured it would be easier to just completely rewrite it from scratch 😅
@doghosuedean
@doghosuedean 10 ай бұрын
Thank you for this, my day job requires me to work with legacy code that was written in a hurry! Maybe I can slowly chip away at it using this framework
@tobylerone007
@tobylerone007 10 ай бұрын
👏Very nicely done!
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thank you!
@lunalect
@lunalect 8 ай бұрын
Very satisfying video to watch, thank you
@ArjanCodes
@ArjanCodes 8 ай бұрын
Thanks, Luna! Happy you enjoyed it.
@lunalect
@lunalect 8 ай бұрын
Keep making more of those :)
@banatibor83
@banatibor83 10 ай бұрын
For these type of work I recommend everybody to read Martin Fowler's amazing book, Working effectively with legacy code. What Arjan does at the beginning called approval testing, basically cementing down the current behavior with tests. From there you can refactor and write more unit tests. The goal with legacy code is to refactor enough to isolate your attachment point where you can add your new functionality. The new functionality should be well tested and written following TDD rules.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Great suggestion!
@TimLauridsen
@TimLauridsen 10 ай бұрын
Another great amd interesting video, very useful, thanks
@ArjanCodes
@ArjanCodes 10 ай бұрын
Glad you enjoyed it! Thanks :)
@ericfornstedt7044
@ericfornstedt7044 6 ай бұрын
Great video! About your 3rd step, create a safety net, how would you approach that if the legacy code is difficult to unit test in it's current state? For example, if the legacy code has hard dependencies to hardware and servers which is not currently available, but functions/classes tries to access those entities as soon as they are executed or created.
@JohnJohnson-dl8oq
@JohnJohnson-dl8oq 27 күн бұрын
Very helpful video! This seems like an ideal place to use a class hierarchy, where the cheeses know how to age themselves, etc. This would encapsulate the knowledge nicely. Perhaps this wasn’t appropriate for a refactoring video?
@twelvethis3979
@twelvethis3979 10 ай бұрын
Loved the video, thank you, Arjan, for taking the viewer step by step out off this terrible code into something much much better.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Glad you enjoyed it!
@deez_gainz
@deez_gainz 10 ай бұрын
This is so great, do you think it is worth creating a video about Katas? Pros / cons + some go to resources ranked by level of difficulty or topic?
@IvanToshkov
@IvanToshkov 10 ай бұрын
Great video! I think this kind of stuff is really missing from "normal" education. It's hard to put it in a book or an article, because refactoring is dynamic, but video works great. Are you familiar with the Mikado method? It's quite similar to what you described here, but it is designed to also handle bigger changes, which need more steps than a single refactoring. The "The Mikado Method" book is quite good. There are also a few articles and videos if you search a bit. I highly recommend it.
@colter09
@colter09 10 ай бұрын
As always, amazing content! Thank you for producing these videos, I'm confident to say that they help a lot of developers out there. I just wanted to point out that I always had a problem with these updater objects like the one you implemented. In my opinion, creating such objects often results in coupling between a dataclass (like Item in your example) and an updator class (the DefaultUpdator here). Wouldn't it be more logical to create an implementation where the behavior is directly connected with the state of the class, for example an AgedBrie class that implements a update_sell_in and an update_quality method?
@ArjanCodes
@ArjanCodes 10 ай бұрын
Thank you! Unfortunately, we can’t change the Item class because the requirements don’t allow it. So to do what you propose, AgedBrie would need to be a subclass of Item. This introduces the problem that you can now have items with a name that’s different from its type (I.e. you can create an AgedBrie instance named “Conjured”). To avoid confusion, I decided to use updater objects instead. It’s not what I would do if I created the code from scratch, but it’s a compromise and a good illustration of the things you sometimes need to do in the real world.
@user-ty9qu7kh2h
@user-ty9qu7kh2h 10 ай бұрын
Wonderful video as usual. You have never used cyclomatic complexity to evaluate the issues of a code. Is there any reason?
@edgeeffect
@edgeeffect 9 ай бұрын
One problem I have with writing tests for legacy code before refactoring is, unlike a kata, we rarely have any specifications and so have to dig through the mess to try to workout what it's supposed to be doing anyway. (laughs)
@cs0576
@cs0576 10 ай бұрын
Around Minute 20 you change the if statements. I wondered if that may slow down the code if the original programmer tested for the more common case, hence avoiding having to call the else statement too often?
@Thomas_6c
@Thomas_6c 10 ай бұрын
Great video! But the example shown is usually not the problem I run into. The example code was very straight-on, declaratively written, whereas the legacy code I usually run into was written by someone who read half of Clean Code and then decided he knew everything. I.e., it's chock-full of unnecessary abstractions and indirection and relies too much on inheritance. Do you have any tips on dealing with this type of legacy code?
@ArjanCodes
@ArjanCodes 10 ай бұрын
If you have a codebase you’re willing to share, you could submit it as a code roast and then I might cover it on the channel.
@AnOmegastick
@AnOmegastick 9 ай бұрын
Thanks for the great videos, Arjan, big fan. AFAIK the solution presented here doesn't fulfill the requirements. The requirements doc says there will be multiple conjured items, and this would need an exhaustive list of all conjured items in advance to function. Instead, it would be better for each ItemUpdater to have an acceptance method that checks if it applies to an item, so that you could match all the items beginning with "Conjured".
@MichaelFJ1969
@MichaelFJ1969 27 күн бұрын
I've often started refactoring and then run into bugs that turned out to be present in the original code base. Lesson learned: Run your unit tests BEFORE starting refactoring.
@murphygreen8484
@murphygreen8484 10 ай бұрын
I feel myself being pulled towards a rabbit hole on this example, where I want to build this exercise from scratch. Instead of a numeric quality value, a more real world example would be a purchase date. Then you only have to care whether the depreciation is linear or exponential. Inflation vs deflation is simply a matter of a positive or negative value being passed as the rate. In this way all items could be boiled down to two methods, yeah?
@mayconfrr
@mayconfrr 10 ай бұрын
Hi, is there any chances you could do localized pricing for your courses? I just checked the price for the mindset one and it costs the minimum wage in brazil. I look forward to learning more with your videos and hopefully, courses.
@ArjanCodes
@ArjanCodes 10 ай бұрын
Hi, can you email us at support@arjancodes.com? We might be able to help.
@TravisPickle
@TravisPickle 10 ай бұрын
im lost at your Item protocol, is it not used or inherited?
@carlesmolins3269
@carlesmolins3269 10 ай бұрын
Why use a Protocol instead of an abstract class? Thx for the video!
@ArjanCodes
@ArjanCodes 10 ай бұрын
Either one works. I like protocols because they fit well with Python’s duck typing system and they don’t require an inheritance relationship to work.
@MrGeordiejon
@MrGeordiejon 10 ай бұрын
33:50 Inverting logic - What about all the lessons on testing False is faster than testing true? Do your tests and refactoring in these areas not also require timing / performance testing?
@ArjanCodes
@ArjanCodes 10 ай бұрын
I wouldn’t prioritize performance if your goal is to make the code easier to maintain. In many cases performance optimizations add complexity as opposed to making things simpler. That’s why you typically do them once you’re happy with the overall design of the code. On top of that, I don’t expect the performance difference between True or False comparison to have any impact whatsoever on this particular use case. If performance really becomes a bottleneck, you’d probably don’t want to use Python anyway.
@MrGeordiejon
@MrGeordiejon 10 ай бұрын
@@ArjanCodes Thanks for answer
@SachinSomia
@SachinSomia 10 ай бұрын
Is there a reason you chose to create updater classes rather than going for inheritance on the item and adding the update quality and sell in methods directly to the Item subclasses? Or was that just a rule for the Kata?
@ArjanCodes
@ArjanCodes 10 ай бұрын
The issue with inheriting from Item and adding the update methods is that to do it ‘properly’, you would need to first create a subclass with those two methods, and then create subclasses of that subclass to provide the implementations for each of the item types. On top of that, it introduces the potential for inconsistent objects as it’s now possible to have an object that carries the name of one type, but it’s actually an implementation of another type via the subclass. With a separate ItemUpdater hierarchy, you avoid these problems, though of course you can still choose to use the wrong ItemUpdater on an item, at least it’s not encoded in the object itself.
@psymon25
@psymon25 2 ай бұрын
How to effectively manage race conditions using python with redis?
@ArpadHorvathSzfvar
@ArpadHorvathSzfvar 10 ай бұрын
I liked the video, and I found something that is not its main topic, but interesting for me. This solution doesn't satisfy all the SOLID principles. According to Liskov Substitution Principle, you shouldn't have replaced the default behavior with an other behavior. (And if I'm right it is also Open-Close Principle violation.) Maybe I wouldn't make the DefaultItemUpdater as the parent of the others. The DefaultItemUpdater would be one implementation of the protocol, and all of the others would implement both methods, not using the default methods. But the question is not this. Is my version makes anything more flexible? Yours is a kind of Don't Repeat Yourself version, and DRY sometimes contradicts SOLID as I see. It seems to me that whether to use the DRY or the pure SOLID version is a trade-off. Less code vs more flexibility.
@Andrumen01
@Andrumen01 10 ай бұрын
This is similar to a project in which I'm working right now. Only each file is 1000+ lines long and for a complete suite of 20+ files per module....a nightmare, without any obvious test cases....I'm kind of pulling out my hair, but I am now about 70% done....nightmare!
@ArjanCodes
@ArjanCodes 10 ай бұрын
You can do this! 💪🏻
@MrGeordiejon
@MrGeordiejon 10 ай бұрын
Safety Net 😆❣
@HunterMayer
@HunterMayer 10 ай бұрын
I'm there now... And I wrote it 11 years ago...
@alexjenkins8026
@alexjenkins8026 8 ай бұрын
I spent 5 months trying to refactor a legacy codebase that was running in production for 3 years with no1 across it... I couldn't figure out TTD cause it had about 8 x 400 lines of code functions with database connections and pushing changes to systems etc (I've now learnt how to mock those variables but didn't at the time)... 5 months later I finally had data and was able to test it... couldn't get it going (broke something). Scrapped the whole thing and rewrote it in 500 lines of code over a weekend (and it out performs the old model). Don't skimp on tests :P but better yet - don't skimp on 'is it useful' step :P I still have no idea how that other code works :/
@AndreaDalseno
@AndreaDalseno 9 ай бұрын
Since Item is alrady an object, wouldn't make more sense to define the methods inside the class (and subclasses) so that the object is responsible for it's own updates?
@ArjanCodes
@ArjanCodes 9 ай бұрын
Yes, it would. However, the rule of the kata is that you’re not allowed to change the Item class.
@AndreaDalseno
@AndreaDalseno 9 ай бұрын
@@ArjanCodes thank you very much, I didn't catch that. May I ask a "weird" question? Have you got any plan to show some use cases of BDD using Behave in python? It's more a large-team feature but it might also be useful for solo programmers or small teams.
@ChrimleOfficial
@ChrimleOfficial 10 ай бұрын
16:25 "Don't have to worry about the constraints that it must be between 0 and 50, because it is built into these functions" False, it is possible to provide increase_item_quality with a negative value, allowing the quality to become negative and violate the constraint. This is also true for the decrease_item_quality, but vice-versa.
@ChrimleOfficial
@ChrimleOfficial 10 ай бұрын
So technically speaking, the only thing that the max() and min() functions do ensure is that ONE of the constraints is not violated.
@ArjanCodes
@ArjanCodes 10 ай бұрын
An easy solution would be to merge the two functions into a single one that combines a min+max.
@ChrimleOfficial
@ChrimleOfficial 10 ай бұрын
@@ArjanCodes Yup! What about the bounds then? Do you recommend that the bounds' default values should continue to be set in the function? What about introducing attributes to the ItemUpdater for representing those bounds? (e.g. qualityUpperBound) That would allow different Items to have different maximum Quality - but might require a Template pattern. ... I can't see those attributes being added to Item, as it would allow Items with the same name to have different maximum Qualities. So it makes sense to add them to the ItemUpdater, and allow sub classes to override them (when need be).
@ArjanCodes
@ArjanCodes 10 ай бұрын
Adding the bounds to the item updaters would be a really simple change to the code that would allow different values for different item types. Adding them to the Item class would allow for even more flexibility since you can then change them per item. However, none of that is specified in the requirements, so I wouldn’t spend time on it unless it becomes a requirement 😁.
@ChrimleOfficial
@ChrimleOfficial 10 ай бұрын
@@ArjanCodes Fair enough :D I haven't used Python in quite a while, so I don't watch as often as I used to. But wanted to say: Thank you for the video, I enjoyed it as always! ^_^
@75hilmar
@75hilmar 3 ай бұрын
Kata as in "to perform a Kata in Karate"?
@Everth97
@Everth97 10 ай бұрын
Testing, or "how to move the magic values out of your sight"
@nicholastan8163
@nicholastan8163 10 ай бұрын
Good summary! What you describe as "invert logic" for step 4 (Refactoring Step-by-Step) could be fleshed out a bit by mentioning the SOLID principles. Not that you would have to clean up the entire codebase to comply 100% with all SOLID principles. But using them as a checklist for the code that you intend to change anyway would be helpful, I find.
@jonathan3488
@jonathan3488 8 күн бұрын
I once wrote 15,000 lines python script in one file. I had to refactor thousands of lines at the middle of the development 😂
@PerisMartin
@PerisMartin 10 ай бұрын
I am going through the refactoring legacy code hell right now. I am dealing with the software written by a really dumb engineer... me 10 years ago
@ArjanCodes
@ArjanCodes 10 ай бұрын
Hahaha! Good luck :)
@marcotroster8247
@marcotroster8247 8 ай бұрын
Yeah well done. But when refactoring an actual legacy codebase, you need to make the code testable first. And that's the tricky part because there's no safety net. So better get comfortable to refactor without tons of tests 😂
@Luca-re3ve
@Luca-re3ve 4 ай бұрын
the worst thing is working on legacy code that is also poorly writed, It makes it both unreadable, unmanteinable and makes work really feel bad
@willemvdk4886
@willemvdk4886 10 ай бұрын
Great video once again, Arjan! Reminded me of a very good talk Kevin Henney once gave about the Gilded Rose Kata and refactoring, he called it "Refactoring Driven Development" :) kzfaq.info/get/bejne/obqTd6WKqNbOZ4U.html
@lucianop.3922
@lucianop.3922 10 ай бұрын
I would have created each item (Sulfuras, Aged Brie, etc.) as a subclass of Item, and I would have added the default behavior of update_quality and update_sell_in as methods of the base class Item. Then, for each specific method, I would have overriden the base methods when defining each specific subclass. Alternatively, I would have added an instance attribute called updater, that contains the specific updater that the item needs. This way, I don't need to have a dictionary to set each specific updater, rather they are assigned when each item is created (I only need to add the updater in each subclass definition, inside the __init__ block). And a third alternative would be to use the dictionary but instead of storing the result in a local variable item_updater, to store it in an attribute of the Item object, for example the updater attribute. To me, this way it makes it clear that every item has an updater, either the default or a specific one.
@Decrupt
@Decrupt 10 ай бұрын
Definitely agree, though in this refactoring you weren’t allowed to edit the item class/file.
@lucianop.3922
@lucianop.3922 10 ай бұрын
@@Decrupt Right, but you could still inherit from the Item class and make these changes in the subclass. Maybe in a subclass called ItemCustom to make it clear that we are customizing the original Item class for the purposes of the requirements. In that sense, we could also call it ItemCustomForRequirements to make the intent even more explicit. But at that point, I think it will depend on the specific circumstances (any keywords/terminology that we use in the project to refer to specific requirements or custom versions of imported classes/files, what conventions are established, what makes it more readable for the team as a whole, etc.).
@ArjanCodes
@ArjanCodes 10 ай бұрын
The reason that I didn’t create subclasses of Item is that it introduces the problem that you can then have items with a name that’s different from its type (I.e. you can create an AgedBrie instance named “Conjured”). To avoid confusion, I decided to use updater objects instead. It’s not what I would do if I created the code from scratch and was allowed to change Item, but it’s a compromise and a good illustration of the things you sometimes need to do in the real world.
@rommellagera8543
@rommellagera8543 10 ай бұрын
You are going against today's dev mantra We don't have to understand the system we just need to improve it - Jim Coplien 😅
@hematogen50g
@hematogen50g 10 ай бұрын
I like how procedural spaghetti code got better and better until it eventually became overengineered OOP.
@simmonslucas
@simmonslucas 10 ай бұрын
yeah, my own code lolol
@DeepFriedOreoOffline
@DeepFriedOreoOffline 10 ай бұрын
Holding a fn key to use delete is very frustrating 😮‍💨
@patrick6294
@patrick6294 3 ай бұрын
Step 4.5: type pytest 1 mio. times... 😜
@bonquaviusdingle5720
@bonquaviusdingle5720 10 ай бұрын
Refactor code before it becomes legacy. Or discontinue it if it's not in line with product decisions.
@Dyanosis
@Dyanosis 10 ай бұрын
With the size of existing projects, that's WAYYY easier said than done.
@anasouardini
@anasouardini 10 ай бұрын
You've lost me there with all the very specific fixes.
@k98killer
@k98killer 10 ай бұрын
This must have been a very tedious video to produce.
@ArjanCodes
@ArjanCodes 10 ай бұрын
It was a lot of work to prepare, but it was actually really fun to do.
@richardhaw9757
@richardhaw9757 10 ай бұрын
thats one ugly code
3 Tips for Writing Simple and Clean Code
17:38
ArjanCodes
Рет қаралды 45 М.
Refactoring A PDF And Web Scraper Part 1 // CODE ROAST
37:44
ArjanCodes
Рет қаралды 43 М.
Heartwarming: Stranger Saves Puppy from Hot Car #shorts
00:22
Fabiosa Best Lifehacks
Рет қаралды 21 МЛН
БОЛЬШОЙ ПЕТУШОК #shorts
00:21
Паша Осадчий
Рет қаралды 10 МЛН
7 Python Code Smells: Olfactory Offenses To Avoid At All Costs
22:10
Modern Python logging
21:32
mCoding
Рет қаралды 161 М.
The Ultimate Guide to Writing Functions
24:31
ArjanCodes
Рет қаралды 178 М.
How Senior Programmers ACTUALLY Write Code
13:37
Thriving Technologist
Рет қаралды 1,4 МЛН
Refactoring A Tower Defense Game In Python // CODE ROAST
36:49
ArjanCodes
Рет қаралды 256 М.
From Legacy Code To STATE OF THE ART DEVELOPMENT
20:04
Continuous Delivery
Рет қаралды 22 М.
How To Reduce Coupling With Facade | Design Pattern Tutorial
28:29
Fun Refactoring! - Gilded Rose Kata, Hands-on with Approval Testing
21:57
Protocol Or ABC In Python - When to Use Which One?
23:45
ArjanCodes
Рет қаралды 198 М.
Heartwarming: Stranger Saves Puppy from Hot Car #shorts
00:22
Fabiosa Best Lifehacks
Рет қаралды 21 МЛН