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

はじめに

プロジェクト自体が主にプログラミングを行う能力を持つユーザーを対象としているため、Godotには貢献する能力を持つユーザーが多数います。それにもかかわらず、すべての人が大規模プロジェクトまたはソフトウェアエンジニアリングで同じレベルの経験をしているわけではないため、プロジェクトにコードを提供する過程でよくある誤解や悪い慣行につながる可能性があります。

言語

このドキュメントの範囲は、貢献者が従うべきベストプラクティスのリストであり、貢献者の投稿プロセスで発生する一般的な状況を参照するために使用できる言語を作成することです。

これを一般的なソフトウェア開発に拡張すると便利な場合もありますが、私たちの意図は、プロジェクトで最も一般的な状況に限定することです。

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

ベストプラクティス

#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 not be actually solving any actual problems.

../../_images/best_practices1.png

これらは通常、問題を探し出す解決策 と呼ばれます。理想的な世界では、それらは有害ではありませんが、実際には、コードの記述には時間がかかり、ソースおよびバイナリとしてスペースを取り、存在する場合はメンテナンスが必要です。不要なものの追加を避けることは、常にソフトウェア開発の良い習慣と見なされます。

#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 into 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: 問題は複雑または頻繁である必要があります

ソフトウェアは問題を解決するように設計されていますが、太陽の下に存在するすべての問題 を解決することは期待できません。ゲームエンジンとして、Godotはあなたのために問題を解決するので、ゲームをより良く、より速くするのに役立ちますが、それはあなたのために ゲーム全体 を作ることはありません。どこかに線を引く必要があります。

../../_images/best_practices3.png

問題を解決する価値があるかどうかは、ユーザーがその問題を回避する必要がある難しさによって決まります。この難易度は次のように表現できます:

  • 問題の複雑さ
  • 問題の頻度

If the problem is too complex for most users to solve, the software must offer a ready-made solution for it. Likewise, if the problem is easy for the user to workaround, offering such a solution is unnecessary and it's up to the user to do it.

しかし、例外は、ユーザーがこの問題に 頻繁に 遭遇する場合であり、そのたびに単純な解決策を実行しなければならないことは迷惑になります。この場合、ソフトウェアはこのユースケースを簡素化する解決策を提供する必要があります。

私たちの経験では、ほとんどの場合、問題が複雑であるか頻繁であるかを判断するのは通常明らかですが、この線を描くのが難しい場合が発生する可能性があります。これが、他の開発者と話し合うこと(次のポイント)が常に推奨される理由です。

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

ユーザーが問題に遭遇した場合、自分のプロジェクトに没頭しているだけなので、彼らは自然に自分の観点から問題を解決しようとし、ユースケースについてのみ考えます。

このため、ユーザーが提案した解決策は、開発者がよく知っている他のユースケースを常に想定しているわけではないため、多くの場合、独自の要件に偏っています。

../../_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 user workaround), or maybe they will 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.

いずれにせよ、貢献を試みる前に、実際の問題を他の開発者または貢献者と話し合うことが重要です。そうすれば、実装に関するより良い合意に達することができます。

この場合の唯一の例外は、コードの領域の明確な(他の貢献者が同意している)所有者であり、ユーザーと直接話をし、解決策を直接実装するための知識が最も高い場合です。

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: それぞれの問題に対して、独自の解決策

プログラマーにとって、問題に対する最適な解決策を見つけることは常に最も楽しい挑戦です。しかし、物事は時々行き過ぎて、プログラマーはできるだけ多くの問題を解決する解決策を考え出そうとします。

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

../../_images/best_practices5.png

主な問題は、実際には、この方法で動作することはめったにないということです。ほとんどの場合、各問題に対する個別の解決策を書くだけで、コードはよりシンプルで保守しやすくなります。

さらに、個々の問題を対象とする解決策は、単純なタスクにのみ必要となるより複雑なシステムを学習および記憶する必要なく、ユーザーが必要なことを正確に実行できるものを見つけるため、ユーザーにとってより優れています。

Big and flexible solutions also have an additional drawback which is that, over time, they are rarely flexible enough for all users, which keep requesting more functions added (and making the API and codebase more and more complex).

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

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

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

素晴らしいと思われるものを思い付くかもしれませんが、実際に使用すると、ユーザーはその半分を使用することすらできないか、元のデザインでは十分に対応できない機能が必要になることがわかり、それを破棄してしまうか、さらに複雑にすることが必要になってきます。

そこで問題となるのは、ユーザーに 必要なことがわかっている ものを提供するソフトウェアをどのように設計するかですが、それは彼らが将来 彼らが必要かもしれないとは知らないこと をすることを可能にするほど柔軟です?

../../_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: 解決策はローカルでなければなりません

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

ここでの主な問題は、遠く離れた単一の場所からしか使用されない何かをコアレイヤーに追加すると、コードを追跡するのが難しくなる(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

これを行いたい一般的な理由は、通常、コアレイヤーにハックを追加するだけで、コードが少なくなるということです。

それにもかかわらず、この方法はお勧めしません。一般に、解決策用のコードは、コードの数が多い、複製される、複雑である、または効率が低い場合でも、問題の発生元に近い場所に配置する必要があります。より多くの創造性が必要かもしれませんが、この道が常にお勧めします。

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

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

Godotは色々なプラットフォームで出荷する必要があるため、ライブラリを動的にリンクすることはできません。代わりに、ソースツリーにバンドルします。

../../_images/best_practices8.png

その結果、私たちは何が入るかに非常にこだわりがあり、より小さなライブラリを好む傾向があります(実際、単一のヘッダーのものが私たちのお気に入りです)。他に選択の余地がない場合にのみ、より大きな何かをバンドルすることになります。

Also, 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 the only option on that platform.