Skip to content

Best practices

Bdiebeak edited this page Jul 19, 2024 · 4 revisions

Work with project

In my opinion, working with a project when developing an application should look like playing with LEGO - the final product should be easily assembled from various modules, which can be used in another project.
To make the work more enjoyable and less painful, I will give you a list of some practices that are useful to follow.

Git workflow

Repository maintenance should be transparent, understandable, and organized into specific stages of development.
Commit names should clearly indicate what was changed or added. It's common to have several branches when maintaining a repository:

  • Main: the main branch of the project, which may be empty or correspond to the latest build version, depending on the project. A release environment is set up.
  • Develop: the primary development branch, where completed tasks are added. A test environment is set up.
  • Production: a branch for ready-to-release tasks. A release environment is set up.
  • Art: a separate branch for non-programmer contributors, such as graphic designers.
  • Features: a collection of branches in which developers create a new branch for each new task. If the project uses a task tracking system, the branch name may include the task number, for example: features/11-player-movement.

Logs

It is important to log as much of the program's code as possible.
This will help to detect strange and incorrect behavior, optimize the application, and, of course, catch bugs in time.
You may want to split the logs into different categories so that they are easier to filter and turn off if necessary.
For example: [02-02-24 17:19:29] [WEAPONS]: Damage 15.

Teamwork

It is worth avoiding conflicts. I mean, conflicts related to the work of version control. But it's not worth wasting time on personal ones either.
To reduce the number of conflicts during work, try to decompose your prefabs as much as possible when working in parallel, and initialize everything from code, if possible. This is because conflicts in code are much easier to resolve.

Profiling & Testing

Profiling and testing should be done throughout the entire development cycle, starting from the early stages.
This is important to avoid ruining a project and spending amounts of time optimizing and reworking it in the future.
It's recommended to profile and test each major feature, as well as smaller ones, on different platforms and hardware configurations.

Task Tracking

When developing a project, it's helpful to create a list of tasks - future, current, tested, and completed.
First, think about what you need to do. Then, if the task is too big, break it into smaller parts.
This will help you understand, evaluate each stage of the work, and identify potential problems. At the same time, it will prevent you from spending a lot of time trying to decide what step to do next, as you can simply move on to the next task from a pre-planned list.

Overengineering

Quite often, developers start creating a large number of currently unnecessary things.
You need to do only task requirements, without complicating or increasing the time to develop something that may not be useful now.
If the task has an implementation of something specific, you do not need to include anything else in it.

Work with code

Codestyle

Of course you should have a specific code conventions about how to write code as a team. This would help to improve the readability of the project for each developer.

Not Your Code

You need to be respectful of other devs code.
It's not necessary to change every file with code that wasn't written by you in your own way. Especially if that code works and has been reviewed.
You could risk breaking something or spending a lot of time rewriting a task that has already been completed.
The only exception to this is if you notice a major problem, in which case you should report it to your lead.

Directives

Preprocessor directives help you enable and disable certain features of a project that needs to run in a specific environment.
There are two main types:

  • Separate: disables specific features. For example, if LOGS is present in the parameters, logs will be enabled, but if it's not present, logs will be disabled.
  • Combined: disables a set of features. For example, if PRODUCTION is specified, all debug features will be disabled.

Composition Over Inheritance

Avoid large inheritance chains and use composition instead.
Composition makes it easier to change the program's structure. For example, when using inheritance, changing the base class can affect all classes that inherit from it - this is inconvenient.
Additionally, the code is easier to read when using composition, as there is no need to navigate through a large inheritance chain to understand how things work.

Assemblies

Assembly Definitions better to name with project prefix (e.g. ProjectName.Editor). This will help to avoid conflicts between builds when importing third-party plugins.

Constants

Don't hardcode values. It is better to use constants for various parameters and string messages. This approach can help avoid code duplication and make it easier to add localization or remote configurations to the project in the future.

Clone this wiki locally