Code Like a Pro: Refactoring to Patterns!

Поділитися
Вставка
  • Опубліковано 25 лис 2024

КОМЕНТАРІ • 94

  • @git-amend
    @git-amend  2 дні тому +16

    Happy Sunday! I really enjoy refactoring because IMO it's the best way to keep your programming skills sharp! I hope you do too! 👍

    • @ВалентинТерентьев-п4р
      @ВалентинТерентьев-п4р День тому

      I don't love refactoring because I can't reliably feel the line between refactoring and overengineering
      What I love, tho, is to receive notification about new git-amend video upload ❤

  • @bogoid
    @bogoid 2 дні тому +21

    Regarding what you mentioned about technical debt at the beginning, many years ago, during my first project as a lead, I had the opportunity to work with a very experienced architect, guy in his sixties I guess he must be retired by now. Well, one day, we were discussing a feature we needed to implement, but the timeline was pretty tight.
    I suggested we could do a basic, quick-and-dirty implementation and then "properly implement it later, after the release." He replied, "There's never a 'later'..."
    It took me some time and a few challenging projects under my belt to truly understand why he was so strict about technical debt... But Craig, if you're reading this, you were absolutely right!

    • @git-amend
      @git-amend  2 дні тому +4

      Hahaha, those are VERY wise words! Thanks for the comment!

  • @oldshamen
    @oldshamen День тому +3

    This type of video is awesome .. not only will it encourage programmers not to start over "because I know better now" but also shows how to use all the important programming patterns you have already taught in previous videos. Great work :)

  • @nickdevprod3667
    @nickdevprod3667 День тому +4

    Super cool type of vieeos. Just let viewers send messy code and refractor it. Best way to learn something

    • @git-amend
      @git-amend  День тому +1

      Thanks! More to come I'm sure!

  • @gonzaloasencio4503
    @gonzaloasencio4503 2 дні тому +9

    like that you bring advanced things and videos like these. Excellent work as always 😃

  • @Luciphear
    @Luciphear 2 дні тому +3

    It's interesting to watch even though I knew the majority of concepts here, but there were some things that were new to me! It's a nice feeling to realize how much I've learned since I started. I really appreciate that you're giving good advice and habits right away despite being a bit more complex unlike many tutorials, that even I had to follow, which taught me some really awful habits that I had to spend a lot of time unlearning. It'll take time either way so better to take that time to learn than have to take the time later on unlearning and feeling unproductive because now you're kind of back to what feels like square one.

    • @git-amend
      @git-amend  2 дні тому

      I agree 💯 - thanks for the great comment!

  • @abdou2247
    @abdou2247 День тому

    So, I understood about 80% of everything you did here. The issue arises when i try to do those things when i’m working on project. All hell breaks loose and I end up with a whole bunch of classes, interfaces and bunch of code that I don’t know what to do with.
    Any help, suggestions is appreciated.
    As always, you videos are very well detailed, very high quality. This the level i aspire to reach one day. Thank you for the all the work you do.
    Looking forward to more amazing content!

    • @git-amend
      @git-amend  22 години тому +2

      Thank you, there will be more videos like this in the future!

  • @lemetamax
    @lemetamax 2 дні тому +2

    This is really good! Nicely done.
    I actually learned the factory pattern from one of your previous videos. Now I use it everywhere possible. It ties cleanly with an object pooling system and jobs and burst.
    Please make more refactor videos like this one. And Happy Sunday!

    • @git-amend
      @git-amend  2 дні тому +1

      Great to hear! Thanks for the comment!

  • @Mikso46
    @Mikso46 День тому

    Hey there. I wanted to thank you from the bottom of my heart for all the amazing content you create. I'm a self-taught programmer and game dev, and after coding for 2 years, I hit a learning plateau. That is, until I discovered your channel. At first, I didn't fully grasp your videos, but I kept rewatching them over and over again, slowly refactoring my game's code. Nowadays, I feel like my code is on steroids, and it's all thanks to you

    • @git-amend
      @git-amend  День тому

      Thanks for the kind words, very motivating!

  • @silchasruin4487
    @silchasruin4487 День тому

    This is fantastic, I can always admit I've made a few mistakes that I wish I knew some of these programming principles and patterns long before I had made the mistake. I always recommend your channel to those devs who struggle with redundancy and scalability. Congratulations on the 20K milestone! But it looks like you've already passed that, at this pace you should hit another milestone before the end of the year!

    • @git-amend
      @git-amend  22 години тому +1

      Thanks! Yup, a million views is just around the corner. Thanks for the comment!

  • @bromanguy
    @bromanguy День тому

    I can never get enough of strategy pattern. Thank you so much for another great video, these refactors are really helpful!

    • @git-amend
      @git-amend  22 години тому

      Glad you like them!

  • @ewwitsantonio
    @ewwitsantonio День тому +1

    Absolutely love this refactoring video approach! It's so helpful to see the before and after, because I know so many of us work ourselves into corners and it can be quite hard to see a path out when you are too close to the project and have been looking at it from one perspective for too long. Thanks a lot for sharing these videos with us!

  • @grzegorzpedrycz2630
    @grzegorzpedrycz2630 2 дні тому +3

    Love that series :) My game code is so much better thanks to you !

  • @nickolasbrown2260
    @nickolasbrown2260 День тому +1

    This is the type of youtube channel where u see ur first video and hit subscribe within 10 min

  • @marlonruvalcaba386
    @marlonruvalcaba386 21 годину тому

    Another great video,
    You can also use an animator override, that way the unit will have different animations depending of the weapon that it is holding.

    • @git-amend
      @git-amend  16 годин тому

      Thanks! Good reminder about the override, that can be useful.

  • @AnotherGameDev2411
    @AnotherGameDev2411 7 годин тому

    This was brilliant!

  • @Typtick
    @Typtick День тому

    Beautifully explained

  • @kyoseoul
    @kyoseoul 2 дні тому

    One of my favorite types of videos! I love seeing so many coding patterns in action. Some are still a bit tricky for me, but I was surprised to realize I’ve already used a few.
    Do you code like this in your own projects, or do you use more "niche" tools like R3 or other libraries/assets? I'd be curious to see some of your older code!

    • @git-amend
      @git-amend  2 дні тому

      Thanks for the comment! I actually don't use too many niche libraries - mostly it's just regular C# when I'm coding. Of course I do use my own systems, like the Service Locator, Event Bus, Improved Timers and the Unity Utility library that we keep adding to as well.

  • @검은모래
    @검은모래 2 дні тому

    Thank you for the great video! I'll enjoy listening to it

    • @git-amend
      @git-amend  2 дні тому

      You're welcome! Thank you!

  • @techdave99
    @techdave99 2 дні тому

    Awesome. will watch again. could apply this to a toy i am working on.

    • @git-amend
      @git-amend  2 дні тому

      Nice! Glad you liked this one.

  • @simeonvasilev4074
    @simeonvasilev4074 2 години тому

    really nice video, pretty educational.

  • @JustLetMePickAFuckingUsername
    @JustLetMePickAFuckingUsername День тому

    Grest video as always. Cheers

  • @Haze_E1
    @Haze_E1 День тому

    amazing content as usual 10/10

  • @GTZ-98
    @GTZ-98 18 годин тому

    Hey Adam, love those type of videos. :D
    Your example should be easily applicable to just a pure FPS game right?
    I've had a weapon wheel in mind for that UI weapon swap and a simpler one with just moving the mouse wheel up or down.
    A factory seems perfect for achieving this.

    • @git-amend
      @git-amend  16 годин тому

      Absolutely, though one thing I would consider for fast swapping is instead of instantiating weapons as you need them, you could start with all options instantiated and just enable/disable them so you just have the current weapon enabled. Instead of destroying a model, just turn it off. Then instead of referencing a prefab to instantiate, have a model lookup that will enable the weapon model on the player.

  • @bodardr
    @bodardr 2 дні тому

    Had a lot of refactoring to do this week as well. I ended up moving the factory pattern to the scriptable object directly, so it doesn't use a factory instance, plus I can override it in the child classes. I wonder what's your opinion on that. As always, keep up the good work, your code is top notch!

    • @git-amend
      @git-amend  2 дні тому +1

      Having a static factory method is a viable option, especially if you don't need to mock the factory for testing purposes. I do it fairly often actually. Thanks for the comment!

    • @bodardr
      @bodardr 2 дні тому

      Yeah when I can I love going static. But I actually meant moving the object creation to the WeaponConfig as a public function. That way you can make it virtual and override it for child Config classes. You could for instance load the projectile prefab for BowConfig or StaffConfig, or any kind of additional stuff. But in your scenario it was perfect because it was simple enough to not be required at all, since there's only WeaponConfig class for now.

  • @ilkangamedev4477
    @ilkangamedev4477 День тому

    Teşekkürler.

    • @git-amend
      @git-amend  День тому

      Teşekkürler! Çok sağ ol, Süper için!

  • @KojiKazama
    @KojiKazama 21 годину тому

    Never listen to that person who says "We'll refactor later" because it never happens.

  • @GameDragon2k
    @GameDragon2k 2 дні тому

    @git-amend Sensei! Great video! Great way to showcase refactoring workflow. I have two questions regarding your setup. 1. How are you getting those Hierarchy Folders? 2. When you're doing null checks in Rider, I noticed there's a little icon there. What is that for?

    • @git-amend
      @git-amend  2 дні тому

      The folders are an Asset created by Sisus that is extremely useful, I'll add a link in the description of this video. Actually, I recommend (and own/use) all Assets made by that creator, especially InitArgs and Debug Extensions. The icon in Rider indicates an implicit check on Unity object lifetime, which is different from regular objects.

  • @Fitz0fury
    @Fitz0fury День тому

    This feels like someone wanted help transitioning from stephen Hubbards arpg course to something more scalable....

    • @git-amend
      @git-amend  День тому

      Could be, I don't think I'm familiar with that one.

  • @TheKr0ckeR
    @TheKr0ckeR День тому

    Nice video content mate! Where would we need enum in that case? Can we solve that differently, every time we add new item type, we also need to add enum, thats what i dont like about enums.

    • @git-amend
      @git-amend  22 години тому +1

      Further refactoring would probably lead to a Generic Weapon instead of enums. Maybe in a future video...

  • @youtubechannel548
    @youtubechannel548 18 годин тому

    Love your videos! This is a bit out of topic of this video, but was curious, I recently saw your data persistance video, which was very helpful, however, I wonder, how do I identify scene objects? I have a scene that has many objects that I can alter during runtime. As an example, there are multiple buildings that have doors. You can open/close a door which means each door holds a state. However, when I want to save all scene objects, which includes all doors how do I then when I load the data back identify which state belongs to which door? I know that some create an object id component that each object has, however, when I tried implementing something like that I couldn't figure out how to avoid each scene prefab instance object id from being overwritten when I apply changes. It seems kind of tricky and would love to know how would you tackle such problem? 🙂

    • @git-amend
      @git-amend  16 годин тому

      The challenge you're describing-persisting and reloading object states while maintaining a consistent way to identify objects-is a common one. Here’s how I’d approach it:
      Use a Persistent ID System: Assign a unique, immutable ID to each scene object using a scriptable component. This ID should be generated at design time (e.g., with a GUID) and stored with the prefab, ensuring it doesn’t reset when applying prefab changes.
      Handle Prefab Overrides Carefully: To prevent IDs from being overwritten when applying changes to prefab instances:
      - Use a custom editor script to ensure the IDs are only regenerated for new objects or manually when needed.
      Serialize the ID field explicitly to retain its value even when applying changes to prefabs.
      - Link State with IDs: When saving, associate each object’s state with its persistent ID in your save data. On loading, iterate through the saved states and match them to scene objects by comparing their IDs.
      For runtime-instantiated objects (like new buildings), assign IDs dynamically when they’re created and track them separately in your save system.
      This ensures every object has a consistent ID regardless of prefab overrides and enables reliable mapping of saved states to objects in the scene.

  • @DapperNurd
    @DapperNurd День тому

    Could you elaborate what the point of the interface for the Weapon is, when you just load it into the abstract class anyways? You could remove the interface from your code and have the exact same functionality.

    • @git-amend
      @git-amend  День тому

      The interface ensures a clear contract for any weapon implementation. This approach comes from the "start from interfaces" principle, rooted in the Interface Segregation and Dependency Inversion principles of SOLID. While it may seem redundant with an abstract class, I almost always start refactoring classes that have things in common by first defining the interface they must all adhere to.

  • @damonfedorick
    @damonfedorick День тому

    Nice! Only 50k more views.

  • @mmertduman
    @mmertduman 2 дні тому

    I have no problem refactoring the code to the state you've shown in the video, but then things get more complicated and the patterns start to feel insufficient.
    For example, what if the bow needs additional config variables that the sword doesn't need? What if the staff needs the same? What if I make variations to the staff that all take different elemental attributes and their configs? Soon enough, each weapon would need its own "WeaponConfig". Its not the end of the world, but different weapons would need to cast the given WeaponConfig to their own config type, e.g. StaffConfig, BowConfig. Maybe there is a better way to handle this?
    The biggest pitfall I encounter is that the inheritance hierarchy that made sense the first time I'm writing it starts to make less and less sense as the project gets more complicated, and refactoring an inheritance tree is a mess.
    I really liked the IWeaponState refactoring that allowed each weapon type to implement its own Down/Up/Update functionality and still be driven by the WeaponController. Because the bow would probably need to aim before shooting, etc. And if a weapon needs additional variables to function correctly (instead of the simple target we get from Use(Transform target)), they can collect it during these 3 states. As I was watching, I was wondering how you'd handle that, and the solution makes a lot of sense to me!
    I would love to see more videos like this as the project gets more complicated. Even though your example has great coverage, the game is not really 'playable' from the POV of a consumer. At the later stages, I feel like patterns become a hassle to maintain as well. Nonetheless, they are much better than the initial code you showed at the beginning.

    • @git-amend
      @git-amend  2 дні тому

      Thanks for the comment. I'm sure we'll look at some more challenging scenarios in the future, maybe some works in progress from Discord.

    • @bodardr
      @bodardr 2 дні тому

      There's always generics. For instance I'm working on an inventory system, and I decided to make the item config as a generic parameter in my item class.
      So something like *Item where TConfig : ItemConfig*. That way the definition is always of the type you want it to be. So you'd have Bow : Weapon, Sword : Weapon. And they all inherit from the contract, either IWeaponConfig or WeaponConfigBase.
      But generics aren't perfect because sometimes you want to use a Weapon as a parameter, but you can't because it requires that generic argument now. You can't make an equip function that takes in Weapon, or Weapon, it won't compile (which is understandable). Solution? Weapon should inherit an interface or a base class that has no generic argument. Now you're good to go.
      I know this is a mouthful but the takeaway is : if you're going generics, it's great, but make sure you have no generics at the top.

    • @git-amend
      @git-amend  2 дні тому

      @@bodardr Great advice. Maybe a good topic for a future video as well.

    • @mmertduman
      @mmertduman День тому

      @@bodardr​​⁠ Yes, but as you said, functions still need to take the non-generic definition. How would your example work with the WeaponFactory shown in the video? The factory also needs to be generic then. Even so, i feel like there needs to be casting somewhere down the line. Same with the UI buttons which take in a List. How would that work? In my mind, if I need to cast the non-generic definition to one of the generic and concrete types, its not much different than casting at the weapon level. Maybe it does help, but Id need to sit down and try to code it to see. Nonetheless, I agree generics are great, especially for EventNotifier, Messaging etc patterns where by nature of the design you need to be able to work with any type of event, message, or payload.

  • @guillem99
    @guillem99 2 дні тому

    8:29 Would it be acceptable to make WeaponFactory and its methods static?

    • @git-amend
      @git-amend  2 дні тому +3

      As it stands right now, you certainly could. However, one of the nice things about a Factory or Abstract Factory is it's use in testing - if you added an interface, it would be very easy to add a test version of the factory and just produce exactly the kinds of output that you need to executing test logic. We don't necessarily need it in this simple example, but injecting a factory is an extremely common practice. Another option you could go with, instead of a static factory, is have a static factory method on the WeaponConfig object so that it can create itself.

  • @akifemrebozdemir
    @akifemrebozdemir День тому

    How do you draw the line between refactoring and over engineering?

    • @git-amend
      @git-amend  День тому +1

      Well, keep in mind that over engineering means adding features that were NOT requested. Refactoring is improving code so that you can facilitate changes that were requested. It's important to keep this in mind so you don't build things that are unnecessary, while still building the things that you do need in the best way you can for your skill level.

  • @RonaldMcDonald-o5z
    @RonaldMcDonald-o5z 2 дні тому +1

    for the algo!

  • @PerroConChaleco
    @PerroConChaleco День тому

    How would you like taking a look into a project that already became a mountain of tech debt?

    • @git-amend
      @git-amend  День тому

      How would I like it? Haha, well I have to do that a lot in my current work, and I can't say I like it too much. Nobody likes it, which is why it should be avoided in the first place. Of course, in the real world it does pay very well. But if you are asking me to consider looking at a specific project for a video, maybe before the next refactoring video I'll ask on Discord for some submissions.

  • @neinxxl1440
    @neinxxl1440 День тому

  • @raymk
    @raymk День тому

    Ah... much clean!
    I think most programmers are capable to clean up their codes, but laziness and ignorance take the best of them.

  • @ilkangamedev4477
    @ilkangamedev4477 День тому

    Thanks a lot can you upload 2K or 4k please :), High quality videos deserve higher resolution.

    • @git-amend
      @git-amend  День тому +1

      I'll see what I can do!

  • @lee1davis1
    @lee1davis1 День тому

    Interface question??? I see in most of your videos you write an interface then never edit it. This vid. You edited the interface three times then had to update all the scripts that implement it. My questioni is...Isn't it bad practice to ever edit an interface?

    • @git-amend
      @git-amend  День тому +1

      Editing interfaces isn’t inherently bad practice, but it can lead to maintenance overhead as all implementing classes must be updated. If it’s your own code, it just requires some extra work. However, in published or shared code, changing an interface can break dependent systems, so be careful if you are doing that.