I just learned about Law of Demeter and as I see it contradicts all the Godot youtube tutorials. The law says

An object can call methods that are apart of

  1. the same object.
  2. a parameter passed into the method.
  3. a object created within its method.
  4. an object it owns.
  5. a global variable.

This implies that any action this object takes must be by manipulating objects of no more than 1 degree away from it. A parent can tell their children what to do, but are not allowed to tell their grandchildren what to do. A manager should manage their direct subordinates, but definitely not manage their subordinates subordinates.

But in Godot something like this is considered normal (C#):

public void SetPriceText(float value)
{
	GetNode<Label>("Viewport/VBoxContainer/Price").Text = value.ToString("#.#");
	GetNode<Viewport>("Viewport").Size = GetNode<VBoxContainer>("Viewport/VBoxContainer").RectSize;
}

This method is in scene's root node script. It calles not only its child "Viewport" but event grand and grandgrandchildren. So to satisfy the law I should add script for each node of path "Viewport/VBoxContainer/Price" and create a method for each script that returns child or itself or size or whatever. It seems like a tedious and unnecessary work. Is this law not suitable for Godot? Maybe this law not applicable for engine-based game development at all?

My approach, which may not be ideal, is to declare a node-reference property within a node, and set the value of the property from an ancestor.

For example:

Scene tree:
NodeA
.... NodeB
.... .... NodeC
.... NodeD

Problem: NodeC needs to reference NodeD.

Solution:

Give NodeC a property node_d:

# injected dependency
var node_d: Node

Let NodeA, a common ancestor of NodeC and NodeD, set the value of the property:

$NodeB/NodeC.node_d = $NodeD

    In Godot basically everything is global in a sense (well, within a particular scene tree). There is no concept of private methods or properties, and any object, on any level, can be accessed at any time from anywhere. This is extremely useful, as you can always do whatever you want. But it is also dangerous if you don't know what you are doing.

    At the same time, a lot of people write what they think is object oriented code, and it's completely useless and a waste of time. For example, you see functions like this taught in classes and used by people.

    private:
        float speed_x;
    public:
        float get_speed_x() {
            return speed_x;
        }
        void set_speed_x(float val) {
            speed_x = val;
        }

    This is completely useless and offers no encapsulation. speed_x is, for all intents and purposes, a public variable. You could use the following code and there would be no difference in the safety or execution of the design.

    public:
        float speed_x;

    The code is equivalent. So a lot of times, people put these constraints on themselves, and waste time writing over-engineered code that does absolutely nothing and just makes their life harder for no benefit.

      If I were in charge of a Godot team project in which quality assurance were important, I think I would mandate that C# or C++ be used rather than GDScript, so that scoping rules and encapsulation could be enforced. (I haven't actually used C# with Godot, so I'm assuming that's possible.)

        Well, I think it's good to know what good design is, but then not be restricted by it. I do think OOP has it's place, as well a design patterns, and all sorts of architecture. But much of that research was done with stricter languages like C++, where it was more important (also with more critical applications like like military or space travel). If you are making a game, it is not as important. Also, with newer dynamic languages, things are much more flexible, and it's easier to write looser code that still works. So yes, it's important to know what the rules are, but if you have a good design in your head, at that point you don't necessarily have to follow them.

        DaveTheCoder You can do this with C#. I'm not sure to the full extent, but you can at least have some level of control, like private or protected members and static typing. Access to the engine features could still allow breaking out of it (such as using GetNode()) but you could design around this using your own structures. My point was that it's added work for questionable benefit.

          cybereality My point was that it's added work for questionable benefit.

          I agree that your example of a useless getter/setter has no benefit. I was thinking of other situations where the encapsulation actually serves a purpose.

          DaveTheCoder

          But would it be wise to force a language ?

          Think Rust: A C++ guy suddenly forced to do things in a safe(tm) way, with the inevitable (my favourite word tonight) exclusion of certain solution that went through their head, because the compiler simply won't let them. Can be tedious :-)

          One can still use C++ for performance and flexibility, but a trivial coding language has its merits for the casual coder. And, btw., C# isn't free, comes with an "MS lets you until further notice" badge.

          Edit: not a friend of absolute OOP because it narrows some options, but isn't encapsulation all about guaranteeing a well defined state at any time (and a few other side effects) ? I may be wrong.

          Don't get me wrong. I love OOP and I think everyone should learn it. For certain applications it is the best solution, particularly with languages like C++ or Java (or C#, which is MS rip-off of Java). But I just don't think it is needed as strictly with languages like Python, or GDScript which is loosely based on Python. I would still recommend using classes and methods, for example when I do getters or settings on complex objects, it is important because I will check for null, return default values, do some additional processing, etc. which can somewhat hide the internal state behind an interface. But it is not enforced by the compiler. It's still good design.

          It also depends on the project. For a simple 2D platform game, made by a beginner, I think it would be a poor choice to force them to learn undergrad computer science level programming. It's not needed. You can write a game with a couple global functions and some if else statements. It's fine. Godot was designed for beginners and for being easy to use. So that is a big part of it. If you are advanced, you can write advanced algorithms without the compiler holding your hand. If a variable is supposed to be "private" then don't access it. Or make the method names start with an underscore to remind yourself. It's certainly possible to do this.

          In godot, a lot of the "objects" are things like gui spacers. No one wants to deal with treating them like first-class objects from an engineering point of view, however correct it may be.

          And on a side note, black boxes are only useful until you have to open them. That's an unwritten law of engineering. Object orientation may help people who work with your code, but it's much less useful to an individual working in isolation. If you made the box, you've already violated the metaphor.

          I use objects because I was required to when I was working, but I don't kid myself that they make much difference. There are lots of successful development methods. Use what's appropriate to your project, which usually translates to what you're most productive with.

            duane Use what's appropriate to your project

            So much this. Usually the moment I see OOP in Data Science I know I am looking at something over-engineered by a PHD with too much time on their hands and it's going to be a pain in my ass.

            I find OOP generally annoying/harder to unpick and maintain thanks largely to it varying wildly by the person writing it. I imagine in Software Dev teams the design principles are more vigorously enforced mitigating this issue, but therein lies its own issue for small agile 'data cowboy' teams in that the very effort of enforcing styles for a project that may be over in 3 weeks or less is time-consuming/detrimental to completing the project. It is therefore generally fine to allow each individual to 'get the job done' but can lead to some seriously convoluted code to unpack down the track if someone has abstracted a bunch of stuff arbitrarily just because they think that's how it should look and not because it is needed.

            This does not mean I don't understand it is situationally useful, just largely feel Students being taught 'OOP First' as a principle is bad.

            Also, as a design philosophy, I don't think there's anything stopping you from applying this concept to Godot, But Godot isn't going to stop you from going around it if you so chose, and you might find that going around it is more productive/minimal risk anyway.

            Also, I find those PhD Data Science people never finish anything but research. If you look at real production games (such as ones that have been open sourced) they are complete hack jobs. You do what you have to do, it doesn't matter if the final product is amazing.

            Python doesn't have private either. Everything is public. A lot of complex code is written in python and it gets more popular every year, so maybe the benefits are being exaggerated. There might be a place for it, so just choose a different language. For indy games, it's probably a waste of time.