Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

エンジン貢献者のベストプラクティス

はじめに

Godot has a large amount of users who have the ability to contribute because the project itself is aimed mainly at users who can code. That being said, not all of them have the same level of experience working in large projects or in software engineering, which can lead to common misunderstandings and bad practices during the process of contributing code to the project.

言語:

The scope of this document is to be a list of best practices for contributors to follow, as well as to create a language they can use to refer to common situations that arise in the process of submitting their contributions.

While a generalized list of software development best practices might be useful, we'll focus on the situations that are most common in our project.

貢献は、ほとんどの場合、バグ修正、機能強化、または新機能として分類されます。この考えを抽象化するために、私たちはそれらを 解決策 と呼びます。なぜなら、彼らは常に 問題 として記述できる何かを解決しようとするからです。

ベストプラクティス

#1: 問題は常に最初に来る

Many contributors are extremely creative and just enjoy the process of designing abstract data structures, creating nice user interfaces, or simply love programming. Whatever the case may be, they come up with cool ideas, which may or may not solve real problems.

../../_images/best_practices1.png

These are usually called solutions in search of a problem. In an ideal world, they would not be harmful but, in reality, code takes time to write, takes up space and requires maintenance once it exists. Avoiding the addition of anything unnecessary is always considered a good practice in software development.

#2: To solve the problem, it has to exist in the first place

This is a variation of the previous practice. Adding anything unnecessary is not a good idea, but what constitutes what is necessary and what isn't?

../../_images/best_practices2.png

The answer to this question is that the problem needs to exist before it can be actually solved. It must not be speculation or a belief. The user must be using the software as intended to create something they need. In this process, the user may stumble upon a problem that requires a solution to proceed, or in order to achieve greater productivity. In this case, a solution is needed.

将来問題が発生する可能性があり、ソフトウェアが表示されるまでに問題を解決する準備が必要であると信じることは、将来の校正 と呼ばれ、次のような考え方によって特徴付けられます:

  • 私はそれがユーザーのために有用であると思います...

  • ユーザーは最終的に必要になると思います...

This is generally considered a bad habit because trying to solve problems that don't actually exist in the present will often lead to code that will be written but never used, or that is considerably more complex to use and maintain than it needs to be.

#3: 問題は複雑または頻繁である必要があります

Software is designed to solve problems, but we can't expect it to solve every problem that exists under the sun. As a game engine, Godot will help you make games better and faster, but it won't make an entire game for you. A line must be drawn somewhere.

../../_images/best_practices3.png

Whether a problem is worth solving is determined by the effort that is required to work around it. The required effort depends on:

  • 問題の複雑さ

  • 問題の頻度

If the problem is too complex for most users to solve, then the software should offer a ready-made solution for it. Likewise, if the problem is easy for the user to work around, offering such a solution is unnecessary.

The exception, however, is when the user encounters a problem frequently enough that having to do the simple solution every time becomes an annoyance. In this case, the software should offer a solution to simplify the use case.

It's usually easy to tell if a problem is complex or frequent, but it can be difficult. This is why discussing with other developers (next point) is always advised.

#4: 解決策は他のユーザーと話し合う必要があります

Often, users will be immersed in their own projects when they stumble upon problems. These users will naturally try to solve the problem from their perspective, thinking only about their own use case. As a result, user proposed solutions don't always contemplate all use cases and are often biased towards the user's own requirements.

../../_images/best_practices4.png

For developers, the perspective is different. They may find the user's problem too unique to justify a solution (instead of a workaround), or they might suggest a partial (usually simpler or lower level) solution that applies to a wider range of known problems and leave the rest of the solution up to the user.

In any case, before attempting to contribute, it is important to discuss the actual problems with the other developers or contributors, so a better agreement on implementation can be reached.

The only exception is when an area of code has a clear agreed upon owner, who talks to users directly and has the most knowledge to implement a solution directly.

Also, Godot's philosophy is to favor ease of use and maintenance over absolute performance. Performance optimizations will be considered, but they may not be accepted if they make something too difficult to use or if they add too much complexity to the codebase.

#5: それぞれの問題に対して、独自の解決策

For programmers, it is always a most enjoyable challenge to find the most optimal solutions to problems. It is possible to go overboard, though. Sometimes, contributors will try to come up with solutions that solve as many problems as possible.

この解決策をさらにすてきで柔軟に見せるために、純粋な投機ベースの問題(#2で説明)もステージに登場させてしまうと、状況はしばしば悪化します。

../../_images/best_practices5.png

The main problem is that, in reality, it rarely works this way. Most of the time, writing an individual solution to each problem results in code that is simpler and more maintainable.

Additionally, solutions that target individual problems are better for the users. Targeted solutions allow users find something that does exactly what they need, without having to learn a more complex system they will only need for simple tasks.

Big and flexible solutions also have an additional drawback which is that, over time, they are rarely flexible enough for all users. Users end up requesting more and more functionality which ends up making the API and codebase more and more complex.

#6: 一般的なユースケースに対応し、まれなケースにはドアを開けたままにする

これは前のポイントの続きであり、この考え方とソフトウェアの設計方法が好まれる理由をさらに説明しています。

前(ポイント#2)に述べたように、私たち(ソフトウェアを設計する人間)が将来のすべてのユーザーのニーズを実際に理解することは非常に困難です。一度に多くのユースケースに対応する非常に柔軟な構造を作成しようとすることは、しばしば間違いです。

We may come up with something we believe is brilliant but later find out that users will never even use half of it or that they require features that don't quite fit into our original design, forcing us to either throw it away or make it even more complex.

The question is then, how do we design software that both allows users to do what we know they need to do now and allows them to do what we don't yet know they'll need to do in the future?

../../_images/best_practices6.png

The answer to this question is that, to ensure users still can do what they want to do, we need to give them access to a low level API that they can use to achieve what they want, even if it's more work for them because it means reimplementing some logic that already exists.

実際のシナリオでは、これらのユース ケースはほとんどまれで珍しいので、独自で解決策を記述する必要があります。そのため、基本的な構成要素をユーザーに提供することが重要です。

#7: Prefer local solutions

問題の解決策を探しているとき、新しい機能の実装であれバグの修正であれ、コードのコアレイヤーにデータや新しい関数を追加することが最も簡単な場合があります。

ここでの主な問題は、遠く離れた単一の場所からしか使用されない何かをコアレイヤーに追加すると、コードを追跡するのが難しくなる(2つに分割される)だけでなく、コアAPIがより大きく、より複雑になり、一般的に理解するのがより困難になることです。

This is bad, because readability and cleanness of core APIs is always of extreme importance given how much code relies on it, and because it's key for new contributors as a starting point to learning the codebase.

../../_images/best_practices7.png

A common reason for wanting to do this is that it's usually less code to simply add a hack in the core layers.

Doing so is not advised. Generally, the code for a solution should be closer to where the problem originates, even if it involves additional, duplicated, more complex, or less efficient code. More creativity might be needed, but this path is always the advised one.

#8: 単純な問題に複雑な解決策パックを使用しない

すべての問題に単純な解決策があるわけではなく、多くの場合、サードパーティのライブラリを使用して問題を解決することが正しい選択です。

As Godot requires to be shipped in a large amount of platforms, we can't link libraries dynamically. Instead, we bundle them in our source tree.

../../_images/best_practices8.png

As a result, we are very picky with what goes in, and we tend to prefer smaller libraries (single header ones are our favorite). We will only bundle something larger if there is no other choice.

Libraries must use a permissive enough license to be included into Godot. Some examples of acceptable licenses are Apache 2.0, BSD, MIT, ISC, and MPL 2.0. In particular, we cannot accept libraries licensed under the GPL or LGPL since these licenses effectively disallow static linking in proprietary software (which Godot is distributed as in most exported projects). This requirement also applies to the editor, since we may want to run it on iOS in the long term. Since iOS doesn't support dynamic linking, static linking is the only option on that platform.