-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upcoming C++ code style changes for 4.0+ #33027
Comments
Discussing from #16521 should likely be merged in this issue. |
About space at beginning of block: I agree it looks odd in the example given, but I actually do this as well in particular when the code inside is larger, I think it improves readability a bit by making the code inside better stand out, rather than being "glued" to the top.
I usually refer to them as I agree about the other changes. |
C# calls the
Personally I'd prefer If an instance is needed to be passed in, then the existing way makes sense. |
Many thanks for elevating this further. I would like to once again to bring up comment formatting, not just the orthography, but also the comment styling:
|
spaces
@Zylann I agree, there are cases, especially long blocks, and when In this sense though, I always found it weird, that the empty line would be after the if (some_cond) {
ERR_FAIL_COND(foo);
some_statement();
} else if (some_other_cond_that ||
breaks_over ||
multiple_lines) {
ERR_FAIL_COND(foo);
some_statement2();
) else {
some_statement3();
} Just a small consideration. r_About the |
That's great to see that code style is being discussed! I'm working with Unreal Engine for quite few years now, editing and extending it's codebase on daily basis, and I find it way more easy to work with because of being Allman based. |
Well, I've always preferred the Linux kernel style, simply because it doesn't waste a line. EDIT: (I usually work with 25-30 lines per screen on my laptop, 35-40 on my desktop) |
I see that this might become the most controversial part of the discussion. ;)
I'm not quite sure about this argument, mostly because of two reasons:
What I see on the other hand, is that it does save some space but it seems to be marginal (or non according to current Godot style). K&R standard was a thing in the 80s and 90s for C - and it made sense for a few reasons back then. For me it seems to be a habbit that doesn't quite feet to the needs of this project. There was shorter code blocks, shorter variable names, shorter lines, different language and the content overall is quite different. // I'm displaying 62 lines in my editor |
Not always, only when deemed helpful.
Again, only when needed, not when it's useless. |
E.g., all the:
which is the most common type of |
I think using Allman style for functions is fine, but I'd avoid it for control flow and loops (as is done in most PHP code styles). Otherwise, small functions with many conditions/loops can become really large as a result of all the line wrapping. |
The Linux kernel coding style guide uses the Allman style for functions:
The justification for this inconsistency is incredibly thin, citing Kernighan and Ritchie as gods:
I don't know if it's such a good idea to use a style which justifies itself as "because we're right".
Just pitching in, I usually have my editors taking up a whole screen, often on my 2nd monitor, where I typically display about 50 lines at once. My opinion may be biased as someone with plenty of screen space, but also I see @Krzycho666 has over 60 lines in their editor.
In any case, getting rid of empty lines in functions won't increase the diffs if we decide to change the brace style to Allman later, so this discussion doesn't block the changes in the OP. |
But not for
In the old times, people in CS used to be fun and liked self-mockery.
I gave you a motivation, I never said we should follow it because it's right.
Yep, people with plenty of space seems to have no problem with wasting lines, and I understand that, it's mainly a problem for people with small screens or who uses big fonts because their eyesight sucks (like me 👀 ). |
I'm actually happy to use whatever the democracy wants .. my personal preference is actually for Allman indentation for everything. I find it easier to instantly visually see where areas of code begin and end. With the Egyptian braces I find myself seeing end braces and having to waste time trying to work out where the brace starts from lol. Perhaps I just need to retrain myself 😄 . Given that the godot style can be done with a clang format, you could conceivably just have something in your IDE that converts the file to your preference on loading, and converts it back when saving... |
I agree with @Faless here, the Allman style wastes a lot of space and is thus really inconvenient for small screens. |
I think my preference for Allman comes from my habit that whenever I see an
opening or an ending brace, my instinctive behavior is to look for a
correspondingly opposite sided brace around that bit of code at the same
indentation, instead of a C++ keyword at the same indentation level, which
is mostly in any non-Allman style.
I am not saying my preference matters much but I propose that this can be
efficiently decided by doing a poll of how many people who actively
contribute to Godot prefer a particular style.
It may not be of any use to try to convert a particular party of people who
prefer a particular style, because in the end it is a preference and
preferences rarely have logically reasons behind it, instead they come from
habits and the kind of code people see everyday.
…On Tue, Oct 29, 2019, 14:07 Gilles Roudière ***@***.***> wrote:
I agree with @Faless <https://github.com/Faless> here, the Allman style
wastes a lot of space and is thus really inconvenient for small screens.
Also, IMHO, it does make things a lot harder to read since it scatters
away logical blocks (in the functional logic, not the algorithmic one). So
basically related lines might end up further away, which makes it difficult
to understand what a block of code does.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#33027?email_source=notifications&email_token=AHSUAFE4CGMCMMKDGRUX4ZLQQ7Y4DA5CNFSM4JEREH42YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECPVGIA#issuecomment-547312416>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AHSUAFDB2T6KEX3ZU3OLEJTQQ7Y4DANCNFSM4JEREH4Q>
.
|
I prefer the current brace style, for same reasons. While I think some of the style changes are good small improvements, I don't see the point in suddenly changing such a large portion of code which otherwise was already fine. |
In reality, open-source projects operate with more of a meritocracy and consensus than a democracy. Meritocracy is an idea that means those who contribute more (and therefore would be affected more by a change) get a greater say, which makes sense. Also, for consensus, it's better to have things that are inconvenient for some rather than blockers for others, and screen space can indeed be a legitimate issue, aside from the issues of changing up the entire code base. Seeing as how the lead devs prefer the current style, and many people here do, I'm 99.9% sure it will stay this way. And while it's not my favorite, this is probably for the best. |
I increased line spacing slightly in my editor, and I've started to remove empty lines in some places (coincidence?!). For really short statements which don't exceed function signature I find that I don't add empty line either. |
About the always braces for if/else blocks, is this only if there's an else block or are the following also fobidden?: if (cond)
return;
if (cond)
foo(); |
@neikeq I think these shouldn't be allowed either, due to the likelihood of making mistakes and spending hours finding them 🙂 |
I couldn't find a tool that enforces it, so I went the manual route: ``` find -name "thirdparty" -prune \ -o -name "*.cpp" -o -name "*.h" -o -name "*.m" -o -name "*.mm" \ -o -name "*.glsl" > files perl -0777 -pi -e 's/\n}\n([^#])/\n}\n\n\1/g' $(cat files) misc/scripts/fix_style.sh -c ``` This adds a newline after all `}` on the first column, unless they are followed by `#` (typically `#endif`). This leads to having lots of places with two lines between function/class definitions, but clang-format then fixes it as we enforce max one line of separation. This doesn't fix potential occurrences of function definitions which are indented (e.g. for a helper class defined in a .cpp), but it's better than nothing. Also can't be made to run easily on CI/hooks so we'll have to be careful with new code. Part of godotengine#33027.
Did the discussion every brought up Lines 63 to 102 in ea8d9c5
|
What about |
I would suggest not using i++ or ++i at all in places where both affects are different e.g, in array index. It always causes confusion and leads to typo bugs. Just using it in alone(like for incrementing or decrementing a value only) should be fine. |
Yeah I agree, my question is rather: whether to use the |
What do you think about empty lines after curly blocks? Variant ret;
if (!cond) {
return ret;
}
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
}
}
return ret; vs. Variant ret;
if (!cond) {
return ret;
}
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
// Do stuff.
}
}
return ret; I think the second one is much more compact and doesn't break the code in any way. I see these kind of empty lines sporadically throughout Godot and the codebase is quite inconsistent regarding this style, so I'd prefer to avoid those extra lines when they do not actually worsen the readability of the code. The rationale behind this is that a single closing bracket var ret;
if (!cond):
return ret
for y in height:
for x in width:
# Do stuff.
return ret; Notice that there are still empty lines in GDScript code, but it takes almost the same number of lines written as in C++ version. |
I glue lines like this in short functions or related blocks within larger functions, but I dont think it makes sense to always strip empty lines after curly closes (or even bother about them). Maybe just allow them? |
Loops that go through 2D data structures should likely use |
In the long run, we should unify the use of
I don't have a strong opinion on which option to go for, but I would prefer always using |
With this comment I would like to reignite this discussion since the inconsistencies in code style and structure make the code sometimes very hard to read or extend, especially affected are files which change quite frequently (e.g. editor_node.h/.cpp). I know, the are some controversial aspects but I am confident that we could come to a consensus or compromise for the most essential ones. I compiled some points below which I found while taking a look at various parts of the codebase. Points to discuss, most essential/general ones first:
More or less clear, but not documented:
As proposed in godotengine/godot-docs#4685, the results of these discussions should be documented in the already present "Code style guidelines" page. In addition, we should refactor the codebase piece by piece (e.g. like in #58395). Of course, this might be a very lengthy process, but I think it's worth it. |
I agree with avoiding 1-character variables whenever possible. Plain English variable names should be favored, ideally full words unless the contraction is well understood and unambiguous (e.g.
I'd say Also, using I'd say the only situation where
I agree one class per file should be the way to go, unless the class is very small (<= 100 lines in the header).
I'd say enum and struct declarations should be put at the top of the class, since they can be referred to without an instance and are immutable. I agree with reordering functions to always match between header and source files. This is probably a long and daunting task that can't be easily automated, though.
I'm not sure about this. Are there technical implications if we omit constructors and destructors (or if we add empty constructors and destructors everywhere)? If there are no downsides to having empty constructors and destructors everywhere, it sounds like a good thing to do to make refactoring easier.
Edit: The same applies to It's probably a good idea to review typedef usage and remove those that are either rarely used, or don't save enough typing to be worth the added choice paralysis. See also #50990.
Definitely. It's better to use
I'd go towards following the IWYU approach, even if it makes Build times are starting to be more and more of a problem on the
I think separator comments of that kind are counterproductive. In my experience, if your code is well-spaced and well-commented, you don't need any separator comments. Having multiple blank lines is not necessary either, especially since vertical space is precious on 16:9 displays.
For consistency, I think we should follow what we're doing in the header. This means not grouping the setter/getter with the property if we don't do that in the header.
Always putting the ternary condition operator in braces sounds good to me. Does clang-format have a way to enforce this?
I agree with all of those. |
Has there been any discussion about a convention for private member variables? In a few cases there is a |
I'm of the opinion that all member variables should be prefixed with |
What about trailing underscores? That would keep names of member variables nice and clean while it wouldn't conflict with reserved identifiers. |
These changes have been made, so closing. |
At the Godot Sprint in Poznań, we discussed a few items about our code style guidelines and how to make things more consistent.
Below is a list of items that we agreed upon. We can use comments on this issue to further discuss; the list below should be updated to reflect consensus on any changes that should be made. Input is also welcome on what tooling we can use to apply style changes and check PRs for style adequacy.
Note that to avoid increasing the maintenance burden in the
vulkan
branch, code style changes should only be applied once 3.2 is released and thevulkan
branch was merged inmaster
.Code formatting
No empty line after opening brace
Fixed with #38738. Enforced by
clang-format
.This is a habit from @reduz that many of us inherited, but there's really no good reason to justify it. If we really need vertical spacing, we can use Allman style, but since most of us really don't like it, let's stick to the expected style.
Bad:
Good:
BTW, should also apply to brace-less situations (e.g. after
case:
).Tools: Thankfully we can just rely on
clang-format
for this, as it has aKeepEmptyLinesAtTheStartOfBlocks: false
option that we can use.Enforce one line between function implementations
Fixed with #38738. Albeit manually, so contributors will have to pay attention to it to keep the style consistent.
Basically fixing #29936.
Bad:
Good:
Tools:* I couldn't find any. Help welcome to find something, enforcing this manually would be tedious.
Enforce using braces on single-statement
if
/else
blocksFixed with #38738. Albeit with
clang-tidy
which doesn't run automatically, so "bad" style could still be introduced by PRs. Reviewers should be on the lookout.This has two parts:
if
's statement on a single line, e.g.if (cond) do_some_stuff();
. We can already enforce that viaclang-format
, see second commit in (unmerged) clang-format config changes to discuss #29848.if
andelse
blocks, even if they only contain a single statement.Bad:
Good:
Tools:* For the first point we can just flip a switch in
clang-format
(AllowShortIfStatementsOnASingleLine: false
). For the second and most important one, I don't thinkclang-format
can handle this for now. IIRC it might be doable withclang-tidy
?Disallow short case labels on a single line
Fixed by #38621. Enforced by
clang-format
.This one is a relatively simple change, just toggling an existing
clang-format
option. See first commit in #29848.These situations don't arise often, but enforcing a consistent style is good.
Bad:
Good:
Tools:* We can also rely on
clang-format
'sAllowShortCaseLabelsOnASingleLine: false
option for this.Switch/case use of brackets
As described in #16521, we have inconsistent use of brackets in
switch
/case
blocks.Note sure what style we should aim for, especially since there are some semantic differences.
Other things
Feel free to refer to our
.clang-format
file to see what options we currently don't set (i.e. we use their default value) and https://clang.llvm.org/docs/ClangFormatStyleOptions.html for description on options.Please comment if you'd like to see other options enabled, or if you know of other tools that can help us enforce a more consistent style guide (both as a manual step to fix the codebase - e.g.
clang-tidy
- or as a check on PRs/pre-commit hook).Coding style
Beyond formatting, there are also some conventions in how we code in Godot's C++ codebase. This section doesn't aim at covering actual features (like C++14 usage, this will be for another issue), but more C++ style choices which don't related to pure formatting.
Enforce
p_
andr_
prefixes for method parametersWe have an implicit convention in the codebase which is more or less followed by core contributors but often missed by new contributors. We should make it explicit in the documentation, and find out how to enforce it.
This convention is that method parameters should start with a
p_
prefix (like "parameter"), unless they are modified by the function itself, in which case they start with ar_
prefix (like "return" - BTW if anyone knows the proper technical jargon to refer to this kind of parameters, that would be useful for the docs). This convention makes it easy to differentiate function parameters from local variables and members, and to spot parameters which might change state and be further used in their calling method.Bad:
Good:
Tools: This one is likely going to be tricky, I don't think we can having tooling to enforce this. Well written guidelines and good PR reviews should do the trick most of the time. If anyone has ideas on how to partially automate testing those inconsistencies, that would be welcome though.
It's also not always clear whether a parameter should be
r_
or simplyp_
, we might need precise guidelines on this (help welcome from anyone with a good understanding of all this).Naming of boolean setters/getters
We have a lot of inconsistency in the current codebase on how we name boolean setters and getters, and especially those we expose to the scripting API.
See #33026 to discuss what the convention should be.
The text was updated successfully, but these errors were encountered: