Посмотрите на мой класс Silo. Сам по себе он прост как гвоздь, это при том, что, он работает в сетях связи, управляет неким автоматическим объектом реального мира, выводит свои настройки в два интерфейса, синхронизирует себя двумя способами по сети, работает как веб-сервер и веб-клиент в зависимости от настроек, и прочее.
Если потенциально возможна смена ГУИ — значит надо так строить абстракции, чтобы код не «ломался». Это называется планирование функционала перед проектированием. В данном случае, требуются абстракции для работы с ГУИ. Это ни в коем случае не противоречит тому, о чём я говорил в статье.
Получается сложный класс? Делим функциональность, в класс добавляем объекты-помощники, либо (более осторожно) используем классы подмешивания.
Вот и вся мысль.
Не понимаю, где вы увидели говнокод, где конкретно в данном случае вы разглядели потенциал к полному перелопачиванию чего-либо вообще.
Наоборот, всё что я предлагаю в статье, сводится к изоляции классов, делению функционала до уровня «простых гвоздей».
Если речь идёт о синтетическом тестировании операторов взаимодействия между этими классами, то ничто не мешает сделать тесты функциями-членами (в т.ч. статическими), точно также, как и сами операторы вычитания и т.д. Либо — да, вспомогательными, отдельными дружественными функциями (что, по сути, другой вид записи закрытой статической функции-члена).
Если речь идёт о каком-то конкретном применении объектов этих классов в рамках другого класса, то тест вполне можно сделать внутри этого класса.
На мой взгляд, спор перешёл в чисто эстетическую плоскость. Предлагаемый подход, думаю, вам понятен. Применять или не применять — решать вам.
Будут конкретные вопросы по практическому применению подхода — пишите, готов обсуждать.
Первое. Данный код не имеет никакого отношения к геймдеву. Так что тут немного промахнулись: здесь другие абстракции. Никто не предлагает объекту сцены работать напрямую с джойстиком. Везде своя специфика, свои абстракции.
Второе. Что касается этого кода, то нет вообще ничего ужасного в привязке к конкретному контролу. При желании я этот контрол могу поменять на другой. При этом не изменится ни один внешний интерфейс. Понимаете?
Взаимодействием объектов заведует другой класс. Класс более выского уровня в иерархии. В него можно точно также включать код для проверок взаимодействия дочерних объектов.
Или я что-то упускаю?
Виртуалки приведены лишь «для красоты». Основная идея — не в них, а в инкапсуляции внутренней кухни.
Что касается смешивания в одну кучу. Я предлагаю такую связку:
класс {внутренние данные; проверка;}
только потому, что это короче, читабельнее, и не минимизирует число изменений по сравнению с этим:
класс {внешние данные;} + класс_проверки {указатель_на_объект_класса; вызов_внешних_данных_класса; проверка; }
При очень большом желании «не смешивать в одну кучу», определение функций-членов для тестирования класса можно вынести в отдельный файл. Это, на мой взгляд, всё равно лучше связки №2.
Почему бы тогда классу не заняться самотестированием? В конечном итоге, мы всё равно три раза перепишем функционал. Но по ходу, зачастую, не будем переписывать интерфейс обмена между классом и его «проверщиком» по ходу изменений внутри класса. По вашему примеру это будет примерно так:
class SelfTested
{
protected:
virtual void SelfTest() = 0;
};
class DeepThought : SelfTested
{
protected:
virtual void SelfTest()
{
int answer = Calculate();
assertEquals(42, answer);
}
private:
int Calculate();
};
В этом случае, если даже логика изменится и внутри я Calculate поменяю на AskAnotherSupercomputer, либо буду ожидать строковый ответ, вовне объекта ничего не поменяется.
К сожалению, в данном случае конкретная реализация будет сильно заслонять собой идею. Выложил для примера код Бункера, возможно, это будет хотя бы немного полезнее общих слов из статьи: habrahabr.ru/blogs/cpp/111120/#comment_3548011
Спасибо за критику. Согласен с тем, что слишком упрощённо описал перенос объектов реального мира в С++. Чуть дополнил соответствующее место в статье. К сожалению, их взаимоотношения настолько разнообразны и разноплановы, что я бы не рискнул сказать что даже ваша статья описывает их достаточно полно.
Что касается езды по одному маршруту — не претендую на Истину, Светоча и т.п. ) Учусь также, как и вы, до сих пор. С моей точки зрения, мне удалось более или менее свести наработки в некую законченную систему, пусть и сумбурно изложенную. В этом смысле я и вижу свою заслугу, а ни в коем случае не в особых, эксклюзивных знаниях.
С другой стороны, для начинающих требуется сформулировать более или менее законченное и простое правило. Что я и пытаюсь сделать. Если сможете сформулировать более простое и точное — напишите, возьму его на вооружение.
Спасибо за поддержку!
Буду рад любым отзывам попробовавших на практике. Предлагаю честно обсуждать все спорные вопросы, которые возникают при практическом их применении.
С моей точки зрения, хотя я возможно и не прав, для новичка оба подхода одинаково сложны. А вот для тех, кто привык к стандартному подходу, переключиться на другую концепцию непросто.
В этом смысле, третья часть, в которой я планирую затронуть многопоточность, будет такой же неуютно-непривычной.
Всё что я предлагаю — постараться, попробовать самим и оценить на практике, какой из подходов лучше. Конечно, непросто привыкнуть. Но если подход оправдан, то как знать — возможно он стоит затраченных усилий.
Не понимаю, в каком месте ваших мыслей идёт выброс исключения.)
Я предлагаю некий подход. Ссылаюсь на свой личный опыт, а также на автора книги, которого очень уважаю.
Если для вас достаточно мнение неких других уважаемых личностей, и вы, не попробовав лично, считаете подход нерабочим — просто не пользуйтесь им.
Со своей стороны, готов обсуждать конкретные примеры из реальных приложений, по мере своих сил и времени, помогу чем могу.
Получается сложный класс? Делим функциональность, в класс добавляем объекты-помощники, либо (более осторожно) используем классы подмешивания.
Вот и вся мысль.
Не понимаю, где вы увидели говнокод, где конкретно в данном случае вы разглядели потенциал к полному перелопачиванию чего-либо вообще.
Наоборот, всё что я предлагаю в статье, сводится к изоляции классов, делению функционала до уровня «простых гвоздей».
Если речь идёт о каком-то конкретном применении объектов этих классов в рамках другого класса, то тест вполне можно сделать внутри этого класса.
На мой взгляд, спор перешёл в чисто эстетическую плоскость. Предлагаемый подход, думаю, вам понятен. Применять или не применять — решать вам.
Будут конкретные вопросы по практическому применению подхода — пишите, готов обсуждать.
Второе. Что касается этого кода, то нет вообще ничего ужасного в привязке к конкретному контролу. При желании я этот контрол могу поменять на другой. При этом не изменится ни один внешний интерфейс. Понимаете?
habrahabr.ru/blogs/cpp/111120/#comment_3543213
habrahabr.ru/blogs/cpp/111120/#comment_3543799
Каким именно боком, по-вашему, и откуда вылезет простота?
Или я что-то упускаю?
Что касается смешивания в одну кучу. Я предлагаю такую связку:
класс {внутренние данные; проверка;}
только потому, что это короче, читабельнее, и не минимизирует число изменений по сравнению с этим:
класс {внешние данные;} + класс_проверки {указатель_на_объект_класса; вызов_внешних_данных_класса; проверка; }
При очень большом желании «не смешивать в одну кучу», определение функций-членов для тестирования класса можно вынести в отдельный файл. Это, на мой взгляд, всё равно лучше связки №2.
В этом случае, если даже логика изменится и внутри я Calculate поменяю на AskAnotherSupercomputer, либо буду ожидать строковый ответ, вовне объекта ничего не поменяется.
habrahabr.ru/blogs/cpp/111120/#comment_3548011
Что касается езды по одному маршруту — не претендую на Истину, Светоча и т.п. ) Учусь также, как и вы, до сих пор. С моей точки зрения, мне удалось более или менее свести наработки в некую законченную систему, пусть и сумбурно изложенную. В этом смысле я и вижу свою заслугу, а ни в коем случае не в особых, эксклюзивных знаниях.
С другой стороны, для начинающих требуется сформулировать более или менее законченное и простое правило. Что я и пытаюсь сделать. Если сможете сформулировать более простое и точное — напишите, возьму его на вооружение.
Буду рад любым отзывам попробовавших на практике. Предлагаю честно обсуждать все спорные вопросы, которые возникают при практическом их применении.
В этом смысле, третья часть, в которой я планирую затронуть многопоточность, будет такой же неуютно-непривычной.
Всё что я предлагаю — постараться, попробовать самим и оценить на практике, какой из подходов лучше. Конечно, непросто привыкнуть. Но если подход оправдан, то как знать — возможно он стоит затраченных усилий.
Я предлагаю некий подход. Ссылаюсь на свой личный опыт, а также на автора книги, которого очень уважаю.
Если для вас достаточно мнение неких других уважаемых личностей, и вы, не попробовав лично, считаете подход нерабочим — просто не пользуйтесь им.
Со своей стороны, готов обсуждать конкретные примеры из реальных приложений, по мере своих сил и времени, помогу чем могу.