Хотелось бы освежить себе теорию по части реализации полиморфного поведения классов. А именно, какие паттерны призваны решать нижеописанную (в общем-то, стандартную) задачу:
Есть некий иерархический набор сущностей, воплощенный в коде в виде иерархии классов, инкапсулирующий свойства и доступ к ним. (Скажем, автомобили: грузовые, легковые, волга, камаз,...). Размер иерархии не тривиальный и насчитывает порядка 20 классов. Объекты используются всегда только конечных классов, т.е. все родители только для обобщения.
Есть несколько подсистем, требующий от сущностей полиморфного поведения. Т.е., каждая подсистема принимает базовый интерфейс, состоящий из полиморфных методов, специфически реализованных для каждого класса иерархии. Размер кода реализации может быть достаточно объёмен и требовать инклуда интерфейса конкретных подсистем.
Какие крайние варианты реализации полиморфизма возможны: Классы, описывающие сущности, непосредственно сами реализуют интерфейсы для каждой из подсистем. Достоинство: все в одном месте, нет дополнительных классов. Недостаток: жуткая мешанина (мы называем это "колхоз"), жуткая связность.
Реализацию интерфейса для каждой подсистемы можно вынести в отдельный класс. Поскольку наличествует иерархия, и довольно существенная, неизбежно возникает соответствующая иерархия классов реализации. И так для каждой подсистемы. Достоинство: уменьшенная связность, реализация для каждой подсистемы в отдельном файле, уменьшив инклуды сторонних тулкитов.
Реализация интерфейса в отдельном файле через свитчи по типу сущности. Достоинства: несколько проще предыдущего варианта и подходит для относительно просто кода реализации расширения, код для данной подсистемы в одном месте для разных классов.
Собсно, у нас по факту используются и этих способа, и разные степени микса. По сути, определяющим фактором у меня явился размер кода реализации под каждую подсистему и его связка со сторонними библиотеками.
RTT>Реализацию интерфейса для каждой подсистемы можно вынести в отдельный класс. Поскольку наличествует иерархия, и довольно существенная, неизбежно возникает соответствующая иерархия классов реализации. И так для каждой подсистемы. Достоинство: уменьшенная связность, реализация для каждой подсистемы в отдельном файле, уменьшив инклуды сторонних тулкитов.
Здравствуйте, ·, Вы писали:
·>Здравствуйте, RikkiTikkiTavi, Вы писали:
RTT>>А что говорит теория? Какие паттерны перечитать? ·>Так Visitor же.
Невероятно, но похоже факт, и эт овторой раз в жизни когда я вижу применение визитора .
Здравствуйте, RikkiTikkiTavi, Вы писали:
RTT>А что говорит теория? Какие паттерны перечитать?
visitor уже посоветовали?
Тогда rulebook pattern за компанию.
У Липперта недавно была серия постов на тему.
Здравствуйте, Kernan, Вы писали:
RTT>>>А что говорит теория? Какие паттерны перечитать? K>·>Так Visitor же. K>Невероятно, но похоже факт, и эт овторой раз в жизни когда я вижу применение визитора .
Каждый раз когда видишь "через свитчи по типу сущности" — это оно и есть — double dispatch.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, RikkiTikkiTavi, Вы писали:
RTT>А что говорит теория? Какие паттерны перечитать?
Теория говорит "решайте реальную задачу". Ваш пример с автомобилями — классика того, как делать не надо.
Т.е. придумать задачу про автомобили, в которой для грузовиков и для легковых потребуются разные классы, практически невозможно.
Очень многие проблемы архитектуры возникают не сами по себе, а из-за того, что в самом начале было принято идиотское решение.
По соседству дали ссылочку на Липперта, где он говорит ровно про то же: "интуитивно очевидный" подход к программированию role-playing game, в котором Wizard и Warrior являются листьями иерархии классов, падает навзничь уже через две итерации проектирования.
А подход, в котором все персонажи — это один класс, а всё оборудование — другой, прекрасно работает.
И заодно не требует visitor и прочей наркомании для того, чтобы описать, что происходит, когда Wizard берёт в руки Sword of steel.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, RikkiTikkiTavi, Вы писали: RTT>А что говорит теория? Какие паттерны перечитать?
Почитайте Бертрана Мейера, объектно-ориентированный анализ и проектирование.
Не применяйте паттерны до тех пор пока без них действительно нельзя обойтись.
Иерархия из 20 классов это лютый аллес.
На первый взгляд, в вашем коде не хватает гранулярности и когда надо было применить SRP, это не было сделано. Тоноч также что наследование надо применять очень аккуратно.
Здравствуйте, ·, Вы писали:
RTT>>>>А что говорит теория? Какие паттерны перечитать? K>>·>Так Visitor же. K>>Невероятно, но похоже факт, и эт овторой раз в жизни когда я вижу применение визитора . ·>Каждый раз когда видишь "через свитчи по типу сущности" — это оно и есть — double dispatch.
и это косяк архитектуры. Так как под один интерфейс запихнули плохо связанные сущности. Этот косяк можно поправить, а можно использовать визитор. Косяк само собой никуда не денется(останется и усугубится) но код станет чуть более ООПэшный...