Five Must Have Code Patterns for Your Godot Game (feat.

Поділитися
Вставка
  • Опубліковано 17 гру 2022
  • 🎟 EARLYBIRD coupon
    up to 50% on preorders of Godot 4 courses: school.gdquest.com/godot-4-ea...
    Learn 5 more Godot code patterns with PlayWithFurcifer: • 5 INVALUABLE Godot 4 C...
    You can find more free Godot videos on their channel: www.youtube.com/@PlayWithFurc...
    Follow them on Twitter: / tweetfurcifer
    ---
    📚 THE LINKS
    Learn Gamedev From Zero with Godot 4: school.gdquest.com/products/b...
    Godot node essentials: school.gdquest.com/products/n...
    ---
    👥 CREDITS
    Video edited by Nesi: / nesiawesomeness
    ---
    💌 JOIN US
    Come chat on Discord: / discord
    Follow us on Twitter: / nathangdquest
    ---
    📝 CC-BY LICENSE
    This video is licensed under the CC-By 4.0 license: creativecommons.org/licenses/...
    You can attribute it to "CC-By 4.0 - GDQuest and contributors - www.gdquest.com/"

КОМЕНТАРІ • 94

  • @Gdquest
    @Gdquest  Рік тому +16

    We're running a Christmas sale right now; all our courses are 50% off with the coupon code DISCOUNT50: gdquest.mavenseed.com/
    Don't forget to watch PlayWithFurcifer's video for 5 more Godot code patterns: ua-cam.com/video/UuEqUN98uZo/v-deo.html

    • @ecclesoul
      @ecclesoul Рік тому

      Will you add a complete 3d game development course at some point?

  • @dairyfreelemonstreams9493
    @dairyfreelemonstreams9493 Рік тому +93

    0:50 Subclasses
    2:58 DataClasses aka why I'm rewatching this again
    4:04 Feature Tags
    6:56 Fluent Interface
    8:20 State Machine

    • @willnationsdev
      @willnationsdev Рік тому +4

      I'd like to point out that the notion of a "data class" also goes by another generic name: POD or "Plain Old Data" class. There are also other names used for such classes, but which are more use-case-specific:
      - a "Context" class is one that is used in the manner described in the video: you specifically want to make method refactoring methods easier as well as simplify the process of re-using the same arguments across many different methods without refactoring all of them.
      - a "Data Transfer Object" or DTO class is one that is used purely to map data between endpoints in the application to the application's internal APIs. For example, when accepting user input, displaying data to the user, fetching data from a database, or sending data to a database, the exact set of fields and properties associated with data will very likely be specific to that targeted "endpoint". You then transfer the data from that object to a format that is more friendly to your application's domain, i.e. perhaps an array of comma-delimited strings gets converted into a Dictionary of integerinteger mappings.
      This pattern can also be combined with other patterns, for example...
      - the static factory pattern (as described in the video) where you write a static method that creates a new instance of the class and returns it, similar to a constructor. However, because it isn't an actual constructor, it doesn't run into the problem of GDScript not allowing multiple constructors and often requiring the constructor (if defined) to allow for no arguments to be passed (e.g. scenes can't instantiate Nodes unless they support an empty constructor). Note that static factory methods often have a `from` prefix to indicate that a new instance is being built "from" some other data.
      - the Fluent API / Fluent Interface: as mentioned, can have method calls that mutate the instance and then return itself, thereby letting you chain together method calls on a single line to steadily transform the object.
      - the Builder pattern: combines Fluent API with Command to effectively build an object that can be mutated, but which is ultimately responsible for instantiating new instances of a target class based on the configuration/mutation of the Builder's properties. It will have a Fluent API that modifies its own properties, but it is a data-only class. You would then call a `build()` method on the Builder that uses all of the assigned values to instantiate a new instance of the Builder's target type. So, e.g. a NodeBuilder would be an object you pass around (like a Command), and update using chained method calls (like Fluent) and which you can pass through an arbitrary pipeline of methods (lambdas, signal callbacks, whatever) before eventually calling `build()` and actually getting a Node created according to the specifications of all the methods it passed through. You can then also cache and reuse that builder to create identical nodes (or whatever the target type is) as desired. This is kinda similar to how the PackedScene class works under-the-hood to instantiate scene files.
      Since I touched on the subject, I'll also say this: there are also several conventions that come with name prefixes:
      - `from` for static factory methods.
      - `get` for accessing a property's value.
      - `set` for overwriting a property value.
      - `with` to return a NEW instance of an object with a specific change (to avoid side-effects and preserve the purity of a given function call in functional programming).
      - `to` to convert an instance's data into a new data type. `as` to provide a new view of an existing instance's data (most often in the context of custom iterators over a collection).
      - `try` to attempt an operation and return a bool true/false based on whether the attempt succeeded.
      - `using` to pass a lambda that accepts a context that provides temporary access (within the lambda) to data that is managed by the class with the `using` method, that way the class does not have to directly expose whatever the protected data is directly in its public API.
      - `find` to perform a key-based lookup of some kind.
      - `at` to perform an index/offset-based lookup of some kind.
      - many, many more, especially if you explore .NET's LINQ API

    • @longuemire748
      @longuemire748 10 місяців тому +1

      thanks

    • @NihongoWakannai
      @NihongoWakannai 8 місяців тому

      ​@@willnationsdev is there an article covering those naming conventions? I already know most of them but was still getting a little confused without code examples lol

  • @ipdramon2177
    @ipdramon2177 Рік тому +174

    The most important I learned from programming in professional environments is that performance is in many cases not the hardest part. Writing code that you and others can understand tomorrow, in a week and even after months of not working with it is more important than this one nanosecond you can save. Only think about performance if your program is currently having issues and does not meet criteria like your wanted fps.

    • @flashfreak62
      @flashfreak62 Рік тому +16

      I learned this lesson very early in my gamedev journey. I would take 1-2 month hiatuses. If my code wasn't readable sometimes it was faster to just transfer all my assets to a new project and start over from scratch.
      Since then though I've gotten really good at making very readable code. I can pick up projects I started months or over a year ago and almost immediately get a pretty strong understanding of what everything does and how they work together

    • @peezieforestem5078
      @peezieforestem5078 Рік тому +3

      That's a false dichotomy right there. If you think in terms of problems and solutions, your solutions should be clear and obvious. If that's the case, your code will automatically be readable and reasonably performant.
      If your code looks like a mess you cannot decipher in a few months, that means, in all likelihood, it wasn't a good solution to begin with.

    • @HDL_CinC_Dragon
      @HDL_CinC_Dragon Рік тому +5

      I think your post can be summed up primarily into two well established programming principles:
      1) Premature optimization is an enemy, not a friend
      2) Never write "clever" code

    • @rogthepirate4593
      @rogthepirate4593 Рік тому +14

      @@peezieforestem5078 If you think it's always this simple, you haven't worked on any complex problems yet. From years of experience in big data server backend stuff, I can assure you that more often than not, "clear and obvious" is a near-utopian luxury that has nothing to do with the real world, and code is never "automatically readable and reasonably performant", it takes hard work to get it there and keep it that way.

  • @fenilli
    @fenilli Рік тому +38

    As for the first pattern, I would say it would be better to follow composition over inheritance, instead of having a Mob scene, have a FollowComponent scene, an HealthComponent Scene, a HurtboxComponent, and that would do only a single job, of emiting signals when something specific to it happen, so you can compose those by passing an instace when needed to each of those, so now you can have as many reusable parts as you want, and any enemy that follows the pattern can use, and any that does not can use another one.

    • @jkf16m96
      @jkf16m96 Рік тому

      I've been trying my way on engineering that with my own classes.
      Inheritance isn't bad either, but one must really think well how concrete the class should be.
      What I've been doing is making the "components" folder with a type-folder structure "Node, RigidBody2D" etc, and creating small classes specific for them.
      And now when implementing my own players or enemies, I extract the needed logic units and puts them in a getter
      private RigidBody2DType.MovementControl MovementControl => new MovementControl(this,...);
      This is what I've gotten so far, but I would like to be able to export MovementControl properties into the editor...
      If I don't discover a way, I'll end up just creating base Nodes.

  • @javgroman
    @javgroman Рік тому +30

    Came from Unity and really enjoyed working in C# but the built-in editor in Godot and GDScript has won me over - it doesn't have all the bells and whistles of say VSC but I don't miss them really. Nice summary vid - always learn a lot from your team coming to Godot. Thanks!

    • @Draenal
      @Draenal Рік тому +8

      Godot supports external editors and there are VS Code plugins for GDScript.

    • @jeffreystephens2658
      @jeffreystephens2658 8 місяців тому +1

      The only thing I feel like it's lacking is Replace All.

    • @jrmillerfilms
      @jrmillerfilms 6 місяців тому

      Only thing I truly miss is being able to highlight a block of code and replace it with a function call, and have it move and create the new function.
      That or typing a function call before it's been created and a hotkey press away and VS creates the empty function with a Not Implemented Exception.

  • @BravosChannel
    @BravosChannel Рік тому +18

    Subclass sandbox is really nice and I like how easy it sounds to just put new stuff, but the way I usually do it is by creating a bunch of nodes that can be children of mob, such as "Damageable" and "Talkable" which makes it easy for me to have certain mobs require more features or less depending on the type of mob I want. If the mob is an NPC, I don't need Damageable, but I do need Talkable. If the mob is a boss, I can add Damageable since the boss will take damage, and Talkable to spice up the drama. I can then connect those signals to the owner class to do specific things like knocking the enemy back after taking damage and stuff like that. When I'm hitting the enemy, I know the player should be hitting "Damageable" so then I can call the function in there with arguments, and let Damageable do the rest of the work in whatever the mob class is meant to do

    • @Gdquest
      @Gdquest  Рік тому +5

      Going with composition like this is a good idea. Depending on the game I'll also tend towards that. The sandbox pattern, like most patterns, has its tradeoffs: very easy, you can have super transparent code, but at the same time you're really constrained by the parent class/scene's structure.
      Now, using a sandbox doesn't prevent you from using components for damage and the ability to talk. You can use it only for the behaviors that you want every e.g. AI agent to have access to.

    • @BravosChannel
      @BravosChannel Рік тому +3

      @@Gdquest honestly a combination of the two is best bet. I just wish it were easy to make certain children editable from the inspector so I can modify children by default without having to make all children editable. It'll make the whole component structure a lot more easy to work with. Usually right now I just drag component nodes into the owner which definitely does get repetitive if I want one specific enemy to do more damage than others. Sandbox definitely streamlines this process a lot better and is just good practice in general but I also do wish there was a way to make certain children editable. There's probably a proposal for that

    • @kawashinimon
      @kawashinimon Рік тому

      This is a really good idea; it really breaks down the complexity of larger scale games like RPGs into something more manageable overall. Really puts a shine on the node system of godot.

    • @jawny7620
      @jawny7620 Рік тому

      @@BravosChannel you can accomplish this in godot 4
      func _on_tree_entered():
      get_parent().set_editable_instance(self, true)
      connect that function to the on_tree_entered signal of an instantiable node, make sure it's a @tool script so it can run from editor, and it will automatically add the node to the scene as editable

  • @luke1235XD
    @luke1235XD Рік тому +6

    Another thing to note about inherited scenes is that they are slightly dangerous since you can lose nodes/properties in the child scenes by making changes in the parent scene. Personally I would only use them for simple things like projectiles were your just changing properties and don't add any additional nodes.

  • @NachoKsp
    @NachoKsp Рік тому

    This video is gold for beginners like me, thanks!

  • @sloppyy
    @sloppyy 4 місяці тому

    realizing how much i was taking for granted about having previously learned a lot of software design patterns years in advance of ever firing up godot

  • @generrosity
    @generrosity Рік тому +5

    Oh, some gems here! Just thinking of juice with the state machine "on_enter" does the juicey particles or wibbles as you move from state to state.
    And passing Self as the return just makes me think of RPG characters and scripting more complex activites far easier :o

  • @josuereis6367
    @josuereis6367 Рік тому

    Maybe I didn't understand, but the enter() and exit() functions seem to serve only to make the code more complex. A change_state() function and delegating processing to the state node is apparently enough.

  • @Daseril
    @Daseril Рік тому +7

    I think this is the first time I've really understood what a state machine is, I've heard/read explanations of it, but never really seen an example of what that means. Seeing the nodes and the scripts attached to them here in the scene tree really helped me to understand.
    Because before this I was just thought that a state machine just referred to how you would code something in a single script when something is in different states. However, seeing that there are multiple nodes and scripts, I now get that its way to break things up, so everything isn't in a single script, and therefore less crowded and difficult to search through.

    • @RenderingUser
      @RenderingUser Рік тому +1

      Wait what?
      I thought state machines were for switching out one set of code for another in a game

    • @v44n7
      @v44n7 Рік тому +1

      @@RenderingUser i am new into godot, but i am understanding state machine like for example. Lets suppose a monsters is moving around minding his own business. That can be called a state. Idle state for example, in which you write all the code for the monster, it moves around, do stuff, etc. But once a player attacks the monster, it changes to aggressive state. In which, starts looking for the player and tries to attack him.
      I think in the video example it gives stats for the 3D character, When the idle state is active, the character animation and codes all respectively to idling, when jumping for example it switches to the "Air state" in which all new animation and coding runs instead of the ones in idle

    • @ArcangelZero7
      @ArcangelZero7 Рік тому +4

      Awesome! For yourself or anybody else here: a great example of State Machine usage is with simpler game Ai.
      The first Half-Life was a big deal with how they used state machines for Ai logic.
      Like the other comment here mentioned: "If I don't see the player, I'm in a searching state and behave like this...Oh I see the player! Move to attacking state. Oh no the player threw a grenade close to me! Move to fleeing state."
      There's some really good videos on UA-cam for it if you search around. :)

  • @danieloliveira-pq4zy
    @danieloliveira-pq4zy 22 дні тому

    Awesome video, really helpful insights!
    Btw, does someone know how to get those fancy little details in the code where stuff like "->" (7:37) and "

  • @jovlem
    @jovlem Рік тому

    Ok, I'm new to classes and that kind of stuff at 2:58 Does it matter where I put/save these?
    Must the node wtih this data class in the same node tree as where I want to use them or can I "call" them from anywhere?

  • @Ash_18037
    @Ash_18037 Рік тому +9

    Fluent interface is absolutely not about being able to chain function calls on a single line as you said at 0:19 In fact fluent interface lines almost always need to be broken up into multiple lines to maintain readability (often people break the line after a . character). Fluent interface aims to improve the understandability and readability of code so that even someone not familiar with it could make a decent guess at what it is doing. The chained method calls ideally make sense if read as an everyday sentence (hence fluent). I don't actually like or recommend fluent interfaces greatly, just wanting to ensure you don't mislead people about it. The more detailed explanation later in the video is much more accurate.

    • @Ash_18037
      @Ash_18037 Рік тому

      If GDscript doesn't allow breaking lines (as is possible in C#) then using fluent interface is going to create some absolutely awful code. e.g. a 10 method chain restricted to one line.

    • @Gdquest
      @Gdquest  Рік тому +4

      Thanks for the correction! To me, it doesn't make things much more readable than setting properties or calling functions in the context of GDScript, so honestly, I never quite understood the pattern.
      Where I've seen it used, it mostly seemed to shorten code, i.e. turn:
      object.do_something()
      object.do_something_else()
      Which is explicit and accessible code, into:
      object.do_something().do_something_else()
      Which is just as explicit and accessible, but shorter.
      I guess the notion of fluent, in the sense of "making it read like a sentence" makes some sense.
      To write each call on a different like you need to write a \ at the end of the line by the way.

    • @makesnosense6304
      @makesnosense6304 Рік тому +1

      It's also called build pattern, where you build the object up with additional methods. "The intent of the Builder design pattern is to separate the construction of a complex object from its representation."

  • @lexi3077
    @lexi3077 Рік тому +2

    Just a question because of my understanding (and I have sometimes trouble seeing stuff): the sandbox pattern. The functions have the code in the Mob-Script and this iconthingie which I really cant see after the "void:" is just indicating that the code is hidden? On the first glance it looks like there is no functionality and I had to pause the video to analyze.
    So did I understand it right, that we just can't see your code? (thats fine! My brain just got confused and then I cant properly listen anymore until I figure stuff out...)

    • @Gdquest
      @Gdquest  Рік тому +3

      Yes, you can fold code blocks in the godot editor, and I folded most functions in the script to highlight one function in particular for the video.

  • @Chevifier
    @Chevifier Рік тому

    4:07 Isnt creating a new Damage class every time you pass damage causing a memory leak. Id recommend that it extends the Reference class so it clears itself after its used.

    • @jkf16m96
      @jkf16m96 Рік тому +1

      It's not a memory leak in c# or GDscript
      It is a really common pattern to use and causes almost no perceptible performance issue.
      In c++ or c, it is definitely an issue (unless you use a smart pointer in c++)

  • @warlockco13
    @warlockco13 6 місяців тому

    Curvy moments y zeno's anthology fueron juegos que me engancharon por sus tramas. Realmente los difrute, una pena que curvy moments no está completo, me quedé con ganas de saber como terminaban las historias.

  • @pranavbadrinathan6693
    @pranavbadrinathan6693 Рік тому +1

    While the subclass behaviour is good, can we do something like Interfaces and implementing multiple interfaces? That would be extremely useful to use in games.

    • @Gdquest
      @Gdquest  Рік тому

      No, GDScript doesn't have interfaces like e.g. C#

  • @soran2290
    @soran2290 Рік тому +1

    7:00 fluent pattern

  • @user-rx3xl7zn1u
    @user-rx3xl7zn1u Місяць тому

    Do you have a recent state machine tutorial?

    • @Gdquest
      @Gdquest  Місяць тому +1

      Soon hopefully but try Godotneers. Their channel is linked on ours. They do an excellent job.

  • @whyunwhite7274
    @whyunwhite7274 Рік тому

    Just saw the big "5" in the thumbnail and instantly thought... Godot 5?

  • @thechrom007
    @thechrom007 Рік тому

    What is font on 8:00 ?

  • @molotov3782
    @molotov3782 Рік тому

    i have a question: is it good toggling State's set_process method instead of using other virtual methods? or does set_process method have high performance impact or any other problem?
    also the PlayerState class can be a subclass in the Player class, so it won't be shown in the add child menu, auto completion works completely in godot 4 but idk if it works in godot 3

  • @max.marauder
    @max.marauder Рік тому +13

    A bit funny to see inheritance from base classes presented as some cool pattern, rather than one of the core OOP principles that are used by default in any code :)
    No offense to the author though, the video is cool anyway!

    • @Gdquest
      @Gdquest  Рік тому +8

      No offense taken, it's a very simple pattern.
      There's inheritance in general, where you override things and add whatever code you like, and there's the sandbox pattern, where you define pretty much all utility functions in the base class and almost exclusively call these functions. You use the base class's code in inherited classes, creating a kind of sandbox, hence the pattern's name.
      It's the constraint you put on calling functions from the parent class to implement concrete behavior that makes the pattern interesting.

    • @Ash_18037
      @Ash_18037 Рік тому

      @@Gdquest It's very understandable why max said this though. This is a very "wishy washy" pattern. I'd even say it's barely qualifies as a pattern. So often you will see code where child classes barely even touch the base class and/or access services directly. The problem is there is absolutely no "in your face" restriction that stops the developer bypassing the base class completely. Once you do that you lose all benefits of the pattern.

    • @Gdquest
      @Gdquest  Рік тому +1

      @@Ash_18037 In a language like Python, JavaScript, or GDScript, there's not much that prevents you from breaking away from lots of patterns. Most rely on your team following the same style and conventions.

    • @marcozanella9850
      @marcozanella9850 Рік тому

      Totally agree, code reuse through inheritance is so standard in OOP that it feels strange to call it a pattern.
      BUT in the context of game making (where you don't generally mess around with inheritance that much) I think it makes sense.

  • @eibriel
    @eibriel Рік тому

    Wow, most useful Godot video ever

  • @angelrubiov
    @angelrubiov 8 місяців тому

    Lol I didn't see the title at 6:56 because my subtitles were obscuring it, I got lost af

    • @Gdquest
      @Gdquest  8 місяців тому

      That's really useful feedback. I'll keep that in mind for future videos, thanks!

  • @DzotEKirill
    @DzotEKirill Рік тому

    Hi, I'm not on the topic of the video, but can you help how to implement that in an HTML5 game the sound is not played when the game is minimized or we are on another tab via OS.is_window_focused() , OS.window_minimized does not work

  • @OgGhostJelly
    @OgGhostJelly Рік тому +4

    crossover episode? 💀

  • @pashakurozeev5516
    @pashakurozeev5516 Рік тому

    Hello! Please make lessons on creating fishing in godot!

  • @user-ul2mr7cy3f
    @user-ul2mr7cy3f 28 днів тому

    X11 does NOT stand for Linux. X11 is a window system. Not every Linux system runs X11, some run Wayland. For now it doesn't matter, but when/if Wayland support will be added, this can break your game if you assume that every Linux build supports X11. It says Linux/X11 and not Linux for a reason.

  • @njnjhjh8918
    @njnjhjh8918 11 місяців тому

    I fail to see the "twist" to subclasses, that's just what subclasses are usually

  • @katkazam5246
    @katkazam5246 Рік тому

    You know have to breath manually

  • @manuelmakesartz
    @manuelmakesartz Рік тому +2

    Hello

  • @AdroSlice
    @AdroSlice Рік тому +18

    Fluent API is pretty bad. It comes from the dated getter/setter-method pattern of Java-centric OOP and is strictly worse than something like a C# object initializer. Depending on the implementation, it can add unnecessary overhead in the form of function calls, and in my opinion the syntax is neither pretty nor intuitive either, especially when you have to mix it with other parts of the code or a library that does not employ the same pattern.

    • @AdroSlice
      @AdroSlice Рік тому +3

      Example (C#):
      x = new RandomObject().SetA(1).SetB(2);
      vs.
      x = new RandomObject() { A = 1, B = 2 };

    • @Gdquest
      @Gdquest  Рік тому +7

      I don't use it personally, but quite a few developers actually love it. In any case, GDScript doesn't support the C/C#/JavaScript style object creation/initialization.

    • @AdroSlice
      @AdroSlice Рік тому +1

      There is an open proposal to introduce a feature like this to GDScript, I very much hope it sees some more attention.

    • @Gdquest
      @Gdquest  Рік тому +1

      @@AdroSlice That'd be nice! I'm not sure what's planned for the future of GDScript though, the devs and language designer are also trying to keep it simple. We'll see.

    • @kawashinimon
      @kawashinimon Рік тому +1

      @@AdroSlice I agree with this. I never liked the get/set thing. Part of it may be because I learned coding through c/c#, but just setting the OOP with a = and calling it as such instead of set/get just feels more simple and cleaner.
      It''s funny since gdscript is based on python which is based around being simple and clean and avoids get/set but for some reason gdscript went back on that.

  • @IceWolve67
    @IceWolve67 4 місяці тому +1

    yeaaa this is not for beginners

  • @WifeWantsAWizard
    @WifeWantsAWizard 8 місяців тому

    Nice video.
    (0:23) What the hell? Why not "Character.new("Juan",100,10);"?
    (2:11) "...especially in an indie game..." Always code like you're applying for a job at Epic. You never know when someone in an interview is going to say, "Can I see the code on that?".
    (3:02) Yes, that is how you pronounce "parameter". From the Greek "para-" meaning "next to" and "-metra" meaning "measure". If "x = 5", "x" is the parameter because it is "next to" the measurement of "5".
    (4:12) Never use a float unless absolutely necessary. The savings he's talking about is 20-30 floats, not 20-30 ints.
    (4:54) This is why we have game *designers* and game *programmers*. Left to their own devices, programmers will change the names of properties as they realize their mistakes causing havoc in big projects. However, designers create game docs so that every property is established in advance and then hand off the finished product to programmers to get the job done in half the time.
    (5:33) What is the point of GodotScript if there's no "Application.platform"? You're telling me that three years from now someone isn't going to come up with an amazing Javascript OS that changes the world? People, hear my voice: learn C#.
    (8:07) I'm sorry, does it filter OUT all the odds or filter FOR odds? Maybe ".filter_remove("odd")" or ".lessThan(10)" instead?

    • @eyondev
      @eyondev 7 місяців тому

      "Always code like you're applying for a job at Epic" sound like a decent way to not get anything done.
      Besides, you use the right tools for the right job. You are doing an Indie game, you solve for the indie game's requirements and limitations, not for what you think would be the requirements for a hypotetical game at Epic.
      The best code depends on the context it's in.

  • @saulnores3477
    @saulnores3477 Рік тому +2

    Playfucifer spoke do fast that I didnt understand anything. I only liked GDQuest parts of the video.

  • @rekiemr4501
    @rekiemr4501 Рік тому +2

    bro plsss make game like a growtopia i hope u can😥

  • @zitronekoma30
    @zitronekoma30 Рік тому

    Left a very politely worded criticism on play with furcifer's channel in the past and was immediately insulted by the owners of the channel, left me with a bad taste so I won't be watching this video, love your guy's content as always tho, I'm sure this is no exception.

  • @peezieforestem5078
    @peezieforestem5078 Рік тому +1

    That's a terrible advice.
    People, don't think in terms of patterns, learn to solve problems.

    • @skilletborne
      @skilletborne 7 місяців тому

      They're tools to add to the proverbial toolbelt, they were never presented as something that it was imperative to use

    • @peezieforestem5078
      @peezieforestem5078 7 місяців тому

      @@skilletborne What do you mean by "never presented"? "Must Have Code Patterns" is literally the title.

    • @JacobTeach
      @JacobTeach 7 місяців тому

      @@peezieforestem5078 I'll play devil's advocate and assume by "must have" they meant "must know"
      patterns are valuable and there's no need to reinvent the wheel

    • @peezieforestem5078
      @peezieforestem5078 7 місяців тому

      @@JacobTeach if that's what they mean, then I have no objections. However, we should be careful with interpreting other people's words.
      I think it's more productive to discuss what's actually being said as opposed to what we think is the closest match that makes sense.

  • @iivarimokelainen
    @iivarimokelainen Рік тому +1

    the accents are super annoying

    • @Gdquest
      @Gdquest  Рік тому +4

      You don't have to watch the videos, you know. No need to comment that on multiple videos.

  • @welyn5499
    @welyn5499 Рік тому

    Hey! Great video. #1 place for online marketing 'Promo sm'!!!