<commit_before>## Соглашения о кодировании на предмете "Компьютерная Графика"

## Парадигмы программирования

Разрешено использовать объектно-ориентированный или процедурный подход, раздельно или в аккуратном соединении. Также допускаются элементы функционального стиля, если это не приводит к ухудшению интерфейса классов.

#### Требования к проектированию кода

- Каждый класс, каждая функция или метод должны иметь единый и понятный уровень абстракции, моделировать только одну сущность или только одно действие
- Каждый метод или функция должен быть не длиннее 20 строк, кроме исключительных случаев, где большая длина кода оправдана
- Можно описывать несколько классов в одном файле, если они находятся на одном уровне абстракции или реализуют одну концепцию. Можно, напротив, следовать правилу "в каждом файле только один класс, и имя совпадает с именем файла".
- Поощряется грамотное применение паттернов проектирования
- Поощрается применение идиомы PIMPL, а также разделение класса-интерфейса и класса-реализации.

#### Требования к кодированию

- следует использовать возможность преобразования булевых выражений в целях упрощения
- поощряется применение алгоритмов из `<algorithm>` и `<boost/range/algorithm.hpp>` вместо сырых циклов
- нужно соблюдать "правило трёх ударов": если вы пишете один и тот же нетривиальный код третий раз в пределах одного модуля, создайте функцию или класс; это касается повторяющихся выражений, инструкций и функций.

#### Сокрытие интерфейса классов

- Следует по возможности размещать константы и вспомогательные функции в анонимном пространстве имён в CPP-файле, а не в приватной или публичной области объявления класса
- Если внутри вспомогательной функции вы вычисляете физическую величину в конкретный момент времени и в конкретных условиях, сделайте её константной локальной переменной и вычисляйте одним выражением:
```cpp
float GetImpactPower(const CParticle &one, const CParticle &another)
{
    // плохой подход: величина как будто бы меняется в процессе
    float power = COULOMB_FACTOR * one.GetCharge() * another.GetCharge();
    float /= GetDistance(one, another);

    // хороший подход: физическая величина в пределах функции не меняется
    const float power = (COULOMB_FACTOR * one.GetCharge() * another.GetCharge()) / GetDistance(one, another);

    // альтернативный способ: введение вспомогательной переменной
    const float intristicPower = (COULOMB_FACTOR * one.GetCharge() * another.GetCharge());
    const float power = intristicPower / GetDistance(one, another);

    // в итерационных методах вычисления правило можно не соблюдать:
    // изменяемые в цикле приближения величины или значения в разные
    // моменты времени могут храниться в неконстантной переменной.

    return power;
}
```
- Выражения для вычисления физических, математических и других величин должны быть простыми. Если они оказываются сложными, можно решить эту проблемы придумыванием более удачных названий, выделением вспомогательных функций, упрощением способа расчёта или изменением чересчур сложного интерфейса вспомогательных классов.

#### Выражения и инструкции

Один и тот же код внутри функции зачастую можно записать как одно выражение или как цепочку инструкций. При выборе способа руководствуйтесь внутренним чувством стиля, но не забывайте:

- в выражениях доступен тернарный оператор `x = condition ? then_value : otherwise_value`
- инструкции подчиняются изменениям потока управления и одновременно выражают смену потока управления
- выражения обычно задают либо способ вычисления некоторого осмысленного значения, либо вызов функции/метода.<commit_msg>Update coding_conventions.md<commit_after>## Соглашения о кодировании на предмете "Компьютерная Графика"

## Парадигмы программирования

Разрешено использовать объектно-ориентированный или процедурный подход, раздельно или в аккуратном соединении. Также допускаются элементы функционального стиля, если это не приводит к ухудшению интерфейса классов.

#### Требования к проектированию кода

- Каждый класс, каждая функция или метод должны иметь единый и понятный уровень абстракции, моделировать только одну сущность или только одно действие
- Каждый метод или функция должен быть не длиннее 20 строк, кроме исключительных случаев, где большая длина кода оправдана
- Можно описывать несколько классов в одном файле, если они находятся на одном уровне абстракции или реализуют одну концепцию. Можно, напротив, следовать правилу "в каждом файле только один класс, и имя совпадает с именем файла".
- Поощряется грамотное применение паттернов проектирования
- Поощрается применение идиомы PIMPL, а также разделение класса-интерфейса и класса-реализации.

#### Требования к кодированию

- следует использовать возможность преобразования булевых выражений в целях упрощения
- поощряется применение алгоритмов из `<algorithm>` и `<boost/range/algorithm.hpp>` вместо сырых циклов
- нужно соблюдать "правило трёх ударов": если вы пишете один и тот же нетривиальный код третий раз в пределах одного модуля, создайте функцию или класс; это касается повторяющихся выражений, инструкций и функций.

#### Сокрытие интерфейса классов

- Следует по возможности размещать константы и вспомогательные функции в анонимном пространстве имён в CPP-файле, а не в приватной или публичной области объявления класса
- Если внутри вспомогательной функции вы вычисляете физическую величину в конкретный момент времени и в конкретных условиях, сделайте её константной локальной переменной и вычисляйте одним выражением:
```cpp
float GetImpactPower(const CParticle &one, const CParticle &another)
{
    // плохой подход: величина как будто бы меняется в процессе
    float power = COULOMB_FACTOR * one.GetCharge() * another.GetCharge();
    float /= GetDistance(one, another);

    // хороший подход: физическая величина в пределах функции не меняется
    const float power = (COULOMB_FACTOR * one.GetCharge() * another.GetCharge()) / GetDistance(one, another);

    // альтернативный способ: введение вспомогательной переменной
    const float intristicPower = (COULOMB_FACTOR * one.GetCharge() * another.GetCharge());
    const float power = intristicPower / GetDistance(one, another);

    // в итерационных методах вычисления правило можно не соблюдать:
    // изменяемые в цикле приближения величины или значения в разные
    // моменты времени могут храниться в неконстантной переменной.

    return power;
}
```
- Выражения для вычисления физических, математических и других величин должны быть простыми. Если они оказываются сложными, можно решить эту проблемы придумыванием более удачных названий, выделением вспомогательных функций, упрощением способа расчёта или изменением чересчур сложного интерфейса вспомогательных классов.

#### Параметры и переменные

- Если вы передаёте в функцию указатель, вы должны проверять его на nullptr (за исключением случаев, когда функцию может вызывать только доверенный и близко расположенный код).
- Если вы не хотите проверять указатель на nullptr, используйте ссылку вместо указателя. Использование указателей обычно оправдано только при прямой работе с C-Style API, таким как OpenGL или OpenAL
- Локальные переменные должны быть константными, если смена их значения не имеет смысла в логике программы.
 
В примере ниже физическая величина `power` не должна меняться во время исполнения функции, т.к. функция не совершает итерации по времени и изменение `power` лишено физического смысла:
```cpp
// нелогичный код
float power = CONSTANT_POWER * distance;
if (sign)
{
    // почему величина силы меняется?
	power *= -1.f;
}
return power;

// логичный код
const float power = (sign ? -1.f : 1.f) * CONSTANT_POWER * distance;

return power;
```

#### Выражения и инструкции

Один и тот же код внутри функции зачастую можно записать как одно выражение или как цепочку инструкций. При выборе способа руководствуйтесь внутренним чувством стиля, но не забывайте:

- в выражениях доступен тернарный оператор `x = condition ? then_value : otherwise_value`
- инструкции подчиняются изменениям потока управления и одновременно выражают смену потока управления
- выражения обычно задают либо способ вычисления некоторого осмысленного значения, либо вызов функции/метода.
{'fraction_non_alphanumeric': 0.051892551892551896, 'fraction_numerical': 0.0008547008547008547, 'mean_word_length': 5.186555891238671, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3369089', 'n_tokens_mistral': 3026, 'n_tokens_neox': 3735, 'n_words': 952}