gdquest-demos / godot-kickstarter-2019

Create your Own Games with Godot, the Free Game Engine: sources from the January Kickstarter project from GDQuest
MIT License
244 stars 270 forks source link

On the use of "private" members/variables #4

Closed razcore-rad closed 5 years ago

razcore-rad commented 5 years ago

Lately I'm leaning towards not using any convention to distinguish between public & pseudo-private members/variables apart from the ones that come as guidelines & necessary from Godot. I mean the virtual functions of course (_ready, _process etc.), but also functions "expected" to follow this convention like functions that link to signals: func _on_some_node_signal().

Apart from these I don't really see any benefit from playing the public/pseudo-private game. If I were to force someone to work with a particular interface (API), I'd do it differently. I'd use a parent/child node relationships, where the parent will expose the API while the child/children nodes implement the nitty-gritty stuff. Of course, there's no real way to prevent anyone from accessing the child properties/methods directly, but I think it's a much better way than relying on this public/pseudo-private convention.

NathanLovato commented 5 years ago

Turns out member variables and methods that start with a leading underscore are auto-completed, so I understand. Agreed

NathanLovato commented 5 years ago

I'd add that we can follow the convention of using a leading underscore for virtual methods. This way when you see _update or something (e.g. with the State pattern) you know you're overriding something or using an interface.

What do you think?

razcore-rad commented 5 years ago

I'm not convinced it's a good idea to have _ in custom base classes to signify override-able functions for two reasons:

  1. there might be clashes with Godot's virtual functions
  2. it looks ugly :)

We can work around 1. but an example will make these clear. If we're gonna work with the State pattern for example, one thing we do is delegate work to it:

var state = MoveState.new()

# later: this is Godot's virtual function
func _input(event: InputEvent) -> void:
    state.input(self, event)

Now here, if MoveState would derive from State, if we were to follow the _ convention, we'd end up having an _input method in State which shouldn't override Godot's. In the above example we name it input, not _input so it doesn't override anything Godot-specific.

Now there's ways around 1. sure, say we'd have _handle_input instead. That fixes it, but it's ugly then: state._handle_input. I'd rather just have state.input honestly.

I don't think there's a problem with remembering the base class interface. The interface class is usually super small and with almost no functionality, it's most likely a NoOp class or something close too it so looking at it at a glance we can easily spot what functions need to be overridden.

NathanLovato commented 5 years ago

Agreed then :)