Attention: Here be dragons
This is the
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
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.
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.
贡献大部分时间都归类为错误修复, 增强功能或新功能. 为了抽象化这个想法, 我们将它们称为 解决方案, 因为它们总是寻求解决可以描述为 问题 的问题.
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.
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.
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.
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.
另外,Godot的理念是支持易用性和维护性, 而不是绝对性能. 性能优化将被考虑, 但是如果它们使得某些东西太难使用或者给代码库增加了太多的复杂性, 那么它们可能不会被接受.
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所述)也出现在舞台上时, 情况往往会变得更糟.
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.
如前所述(第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?
这个问题的答案是, 为了确保用户仍然可以做他们想做的事情, 我们需要让他们访问一个 "低级API", 他们可以用它来实现他们想要的, 即使这对他们来说是更大的工作, 因为这意味着重新实现一些已经存在的逻辑.
在现实场景中, 这些用例无论如何都是非常罕见的, 所以需要编写一个定制的解决方案是有意义的. 这就是为什么仍然要为用户提供基本的构建块来实现这一点很重要.
当寻找一个问题的解决方法时, 例如实现新特性或者修复一个BUG, 有时最简单的方式是在核心代码层中, 添加数据或是一个新的代码函数.
这里的主要问题是, 在核心层中添加一些只在很远的地方使用的东西, 不仅会使代码更难理解(一分为二), 而且还会使核心API更大, 更复杂, 更难理解.
这是不好的, 因为核心api的可读性和干净性总是非常重要的, 因为它是新贡献者学习代码库的一个起点.
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.
并非每个问题都有一个简单的解决方案, 很多时候, 正确的选择是使用第三方库来解决问题.
由于 Godot 需要在大量的平台上发布，我们无法对库进行动态链接。相反，我们将它们捆绑在我们的源代码树中。
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.