Информация об изменениях

Сообщение Re: Как покрасивше без “if”? от 14.01.2026 16:22

Изменено 14.01.2026 16:24 gyraboo

Re: Как покрасивше без “if”?
Здравствуйте, Hоmunculus, Вы писали:

H>Есть базовый класс A. Есть наследник В. И есть наследник наследника С.

H>Есть некая структура данный. Она парсится из файла.
H>Если в этой структуре все поля после парсинга заполнились — то на основе этой структуры создается класс С.
H>Если каких-то полей нет, но чуть больше чем совсем минимум — то создается класс В
H>А если совсем только базовый минимум полей заполнились из файла, то создается объекта класса А.

H>Ясно, что тупым «if» проверяя поля структуры можно проверять какой именно класс создавать. Но что-то некрасиво как-то. Можно как-то стильно модно молодежно, С++-но и по последним стандартам с сотней шаблонов и SFINAE разрулить создание нужного класса на основе прочитанной структуры?


Сам по себе IF в коде не является злом. Особенно если IFы сидят внутри (инкапсулированы, спрятаны от клиентского кода).
А вот если IFами обвешана бизнес-логика (т.н. "клиентский код"), это уже антипаттерн.
По GoF правильным считается архитектура, когда клиентский код использует тип A (за которым в рантайме, благодаря ООП, может прятаться любой его подкласс — B или С). Для создания экземпляра типа A клиентский код вызывает парсер, который возвращает тип A:

parser {
A parse(filename) {}
}



Внутри парсера инкапсулирована логика, которая парсит файл и вызывает GoF-паттерн "фабрика" (сигнатура вызова тоже возвращает тип A, например: A createByparams(params)), передавая ей распарсенные параметры.
Внутри фабрики инкапсулирована логика, которая в зависимости от полноты параметров, с помощью IF, инстанцирует экземпляр A, B или С. В коде фабрики IF не запрещены, т.к. это не бизнес-логика, а вспомогательная логика.

В чём профит такого подхода: в коде бизнес-логики мы соблюдаем принципы SOLID, т.к. бизнес-логика оперирует только типом А. Код бизнес-логики становится простым (не обременённым IFами), расширяемым (для добавления нового подтипа А ты просто добавляешь новый подкласс, остальной код, особенно код бизнес-логики, ты не трогаешь, тем самым минимизируя вероятность регрессионных багов) и более надёжным, чем "матрёшка из IFов".
Re: Как покрасивше без “if”?
Здравствуйте, Hоmunculus, Вы писали:

H>Есть базовый класс A. Есть наследник В. И есть наследник наследника С.

H>Есть некая структура данный. Она парсится из файла.
H>Если в этой структуре все поля после парсинга заполнились — то на основе этой структуры создается класс С.
H>Если каких-то полей нет, но чуть больше чем совсем минимум — то создается класс В
H>А если совсем только базовый минимум полей заполнились из файла, то создается объекта класса А.

H>Ясно, что тупым «if» проверяя поля структуры можно проверять какой именно класс создавать. Но что-то некрасиво как-то. Можно как-то стильно модно молодежно, С++-но и по последним стандартам с сотней шаблонов и SFINAE разрулить создание нужного класса на основе прочитанной структуры?


Сам по себе IF в коде не является злом. Особенно если IFы сидят внутри (инкапсулированы, спрятаны от клиентского кода).
А вот если IFами обвешана бизнес-логика (т.н. "клиентский код"), это уже антипаттерн.
По GoF правильным считается архитектура, когда клиентский код использует тип A (за которым в рантайме, благодаря ООП, может прятаться любой его подкласс — B или С). Для создания экземпляра типа A клиентский код вызывает парсер, который возвращает тип A:

parser {
A parse(filename) {}
}



Внутри парсера инкапсулирована логика, которая парсит файл и вызывает GoF-паттерн "фабрика" (сигнатура вызова тоже возвращает тип A, например: A createByparams(params)), передавая ей распарсенные параметры.
Внутри фабрики инкапсулирована логика, которая в зависимости от полноты параметров, с помощью IF, инстанцирует экземпляр A, B или С. В коде фабрики IF не запрещены, т.к. это не бизнес-логика, а вспомогательная логика.

В чём профит такого подхода: в коде бизнес-логики мы соблюдаем принципы SOLID, т.к. бизнес-логика оперирует только типом А. Код бизнес-логики становится простым (не обременённым IFами), расширяемым (для добавления нового подтипа А ты просто добавляешь новый подкласс, остальной код, особенно код бизнес-логики, ты не трогаешь, тем самым минимизируя вероятность регрессионных багов) и более надёжным, чем "матрёшка из IFов".

Но и правильно спроектировать такой код сложнее. Например, тебе нужно соблюсти принцип подстановки Лисковы из SOLID, т.е. чтобы бизнес-код оперировал А, даже если в рантайме за ним прячется B или С, и клиент не должен анализировать реальный подтип А, т.е. в бизнес-коде запрещены такие конструкции: if (a instanceof C) then...
Это иногда бывает не так просто.