2. Явное и точное имя предпочтительнее короткого и двусмысленного.
3. KISS применяется по умолчанию: выбирается самое простое решение, которое корректно выполняет текущую задачу и сохраняет архитектурные границы.
4. Сложность допускается только там, где она следует из предметной области, формата, протокола, производительности или совместимости 3.3.5a.
5. Неизбежная сложность должна быть локализована, протестирована и документирована.
## Имена
Не нужно бояться длинных имён переменных, функций, типов, сигналов и файлов. Имя должно позволять понять назначение сущности без поиска всех мест использования.
Длина не является самоцелью. Не повторять контекст, который уже однозначно задаётся типом или модулем:
```gdscript
# Внутри TerrainStreamingService:
funcenqueue_finalize(tile:TerrainTile)->void:
pass
```
Такое имя допустимо, если `finalize` в этом классе имеет только одно значение. Если существуют terrain mesh, material и liquid finalization, имя должно уточнять конкретную операцию.
- Units указываются в имени: `_milliseconds`, `_seconds`, `_bytes`, `_meters`, `_tiles`, `_radians`, `_degrees`.
- Coordinate space указывается, если возможна путаница: `canonical_wow_position`, `godot_world_position`, `adt_tile_coordinate`.
- Версия/build/profile указывается в типе или namespace, если semantics различаются: `Wotlk335ProtocolProfile`.
Допустимые устоявшиеся доменные сокращения:
- WoW, MPQ, BLP, DBC;
- ADT, WDT, WDL;
- M2, WMO;
- GUID, SRP, API, UI;
- LOD, RID, GPU, CPU;
- SQL, TCP.
Новые локальные сокращения из двух-трёх букв без общеизвестного значения запрещены.
## Запрещённые размытые имена
Избегать без уточнения:
```text
data
info
item
object
value
temp
result
state
manager
helper
utils
process
handle
do_work
```
Они допустимы только когда тип и ближайший scope делают значение полностью однозначным. Например, `parse_packet() -> PacketParseResult` может использовать локальную переменную `result`, если функция мала и другого результата нет.
`Manager`, `Helper`, `Utils` почти всегда скрывают несколько обязанностей. Предпочтительны названия по роли:
```text
WorldSession
StreamingTargetPlanner
RenderBudgetScheduler
CoordinateMapper
AssetRepository
QuestValidator
ServerSchemaAdapter
```
## KISS decision order
При выборе реализации двигаться по порядку:
1. Простая typed function с явными inputs/outputs.
2. Маленький value object или immutable result.
3. Небольшой service с одной ответственностью.
4. Composition нескольких services.
5. Interface/strategy только при реальной вариативности или boundary.
6. Generic framework только после нескольких подтверждённых use cases.
7. Native/low-level optimization только после измеренного bottleneck.
Не переходить на следующий уровень, если предыдущий решает задачу без нарушения correctness и architecture.
## Простота функций
- Одна функция выполняет одну логическую операцию.
- Название функции описывает observable effect.
- Inputs и outputs явные; hidden global state минимален.
При этом `StreamingTileLoadRequest` оправдан только если параметры действительно образуют устойчивый contract. Для двух простых аргументов не нужно создавать объект только ради архитектурности.
## Простота data flow
- Один владелец mutable state.
- Один канонический тип для одной концепции.
- Один mapper для coordinate conversion.
- Один authoritative source для content/runtime state.
- Изменения передаются commands/events/read models, а не чтением чужих внутренних dictionaries.
- Не создавать второй cache, registry или event bus без описанной отдельной ответственности.
- Не использовать строки и `call()` как основной type system.
- Dictionary допустим на binary/dynamic boundary; внутри domain данные переводятся в typed representation.
## Простота архитектуры
- Не вводить interface только потому, что «когда-нибудь может появиться второй backend».
- Interface обязателен на реальной внешней границе: renderer facade, protocol profile, Lua VM, server schema adapter, asset repository.
- Не создавать base class с одним наследником без конкретного boundary/invariant.
- Предпочитать composition inheritance.
- Не строить универсальную ECS, service container, message broker или plugin framework до подтверждённых требований OpenWC.
- Не переносить архитектуру reference-проекта целиком; извлекать только проверенное решение конкретной проблемы.
## Работа со сложностью
Сложность считается оправданной для:
- binary formats и build-specific layouts;
- encrypted/framed network protocol;
- incremental world streaming;
- animation/material compatibility;
- Lua/FrameXML/taint semantics;
- cross-core schema mappings;
- async jobs, cancellation и deterministic cleanup;
- performance-critical batching после profiling.
Если сложность неизбежна:
1. Изолировать её в одном модуле.
2. Дать точные имена промежуточным этапам.
3. Разбить pipeline на небольшие transformations.
4. Добавить data-flow/sequence/state diagram.
5. Зафиксировать invariants и ownership.
6. Создать fixtures для edge cases.
7. Объяснить, почему более простое решение недостаточно.
- как проверить fidelity, correctness и performance;
- какие части реализованы, запланированы или известны как gap.
Правила именования, KISS и локализации неизбежной сложности определены в [`CODING_STANDARD.md`](CODING_STANDARD.md). Документация и ясные имена дополняют друг друга: комментарий не должен компенсировать неудачное имя.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.