Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class SkyLaunch : public Superpower

> В частности это значит что в исходнике каждого такого подкласса будет только один `#include`, подключающий базовый класс.

Между этими двумя крайностями лежит некое среднее решение, когда часть операций предоставляется базовым классом, а остальные используются из других систем напрямую. Чем больше операций вы представляете, тем меньше у вас связности подклассов со внешним системами, но зато _больше_ связность с базовым классом. Мы снижаем связность у классов наследников, но увеличиваем ее у самого базового класса.
Между этими двумя крайностями лежит некое среднее решение, когда часть операций предоставляется базовым классом, а остальные используются из других систем напрямую. Чем больше операций вы представляете, тем меньше у вас связности подклассов со внешними системами, но зато _больше_ связность с базовым классом. Мы снижаем связность у классов наследников, но увеличиваем ее у самого базового класса.

Это очень выгодно, когда у вас есть множество классов наследников, связанных со внешними системами. Перенося ее в предоставляемые операции, вы концентрируете связность в одном месте: в базовом классе. И чем чаще вы это делаете, тем больше и сложнее для поддержки становится базовый класс.

Expand All @@ -225,7 +225,7 @@ class SkyLaunch : public Superpower

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

> Я не зря беру слово"безопасность" в кавычки, потому что технически даже получение данных может добавить вам проблем. Если ваша игра многопоточная, вы можете пытаться читать какое-то значение в то время когда оно изменяется. И если не будете достаточно осторожны, у вас окажутся некорректные данные.
> Я не зря беру слово "безопасность" в кавычки, потому что технически даже получение данных может добавить вам проблем. Если ваша игра многопоточная, вы можете пытаться читать какое-то значение в то время когда оно изменяется. И если не будете достаточно осторожны, у вас окажутся некорректные данные.
>
> Еще один хитрый случай - это когда состояние вашей игры строго детерминировано (что практикуют многие онлайновые игры для сохранения синхронизации между игроками). Если вы получаете доступ к чему либо за пределами синхронизированного состояния игры, у вас могут образоваться крайне опасные недетерминированные баги.

Expand Down Expand Up @@ -357,7 +357,7 @@ class Superpower
};
```

Здесь видна очевидная проблема. Каждому классу наследнику придется иметь конструктор, вызывающий конструктор базового и передающий в него этот аргумент. А это значит что каждый класс наследник буде частью состояния, о котором мы хотим чтобы он вообще не знал.
Здесь видна очевидная проблема. Каждому классу наследнику придется иметь конструктор, вызывающий конструктор базового и передающий в него этот аргумент. А это значит что каждый класс наследник будет частью состояния, о котором мы хотим чтобы он вообще не знал.

Для поддержки это тоже сплошная головная боль. Если позже мы захотим добавить еще одну часть состояния в базовый класс, нам придется изменить и все конструкторы всех унаследованных от него классов.

Expand Down Expand Up @@ -413,23 +413,23 @@ class Superpower

Что еще лучше, теперь `particles_` является статической переменной и нам не нужно сохранять ее в каждом экземпляре `Superpower`, так что наш класс будет расходовать меньше памяти.

- **Использование поиска службы(service locator):**
- **Использование поиска службы (service locator):**

Предыдущий вариант требовал чтобы внешний код обязательно не забывал о том, чтобы передать состояние в базовый класс, прежде чем его можно будет использовать. Таким образом на окружающий код налагаются определенные обязанности. Еще как вариант можно позволить базовому классу обрабатывать это, получая нужное состояние самостоятельно. Для этого можно использовать [поиск службы (Service Locator)](../shabloni-snizheniya-svyaznosti-decoupling-patterns/poisk-sluzhbi-service-locator.md).
Предыдущий вариант требовал чтобы внешний код обязательно не забывал о том, чтобы передать состояние в базовый класс, прежде чем его можно будет использовать. Таким образом на окружающий код налагаются определенные обязанности. Еще как вариант можно позволить базовому классу обрабатывать это, получая нужное состояние самостоятельно. Для этого можно использовать [поиск службы (Service Locator)](../shabloni-snizheniya-svyaznosti-decoupling-patterns/poisk-sluzhbi-service-locator.md).

```cpp
class Superpower
{
protected:
void spawnParticles(ParticleType type, int count)
{
ParticleSystem& particles = ServiceLocator::getParticles();
particles.spawn(type, count);
}
```cpp
class Superpower
{
protected:
void spawnParticles(ParticleType type, int count)
{
ParticleSystem& particles = ServiceLocator::getParticles();
particles.spawn(type, count);
}

// Метод песочница и другие операции...
// Метод песочница и другие операции...
};
```
```

Здесь для `spawnParticles()` нам нужна система частиц. Вместо того чтобы нам ее _давали_ из внешнего кода, мы сами получаем ее через поиск службы.

Expand Down