Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Bers
Заблокирован
#1

Проектирование ОО архитектуры - C++

18.10.2011, 14:32. Просмотров 798. Ответов 18
Метки нет (Все метки)

Интересно мнение публики. "Программирование в терминах интерфейсов"
Вопрос такой: как правильно конструировать едино-образный интерфейс?

По аналогии с контейнерами STL - все они по разному решают задачи, но для удобства пользователя имеют единообразный интерфейс (что может предполагать некое родство между ними, а может и не предполагать)

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

Причем, некоторые методы классов абсолютно идентичны (и по прототипу, и по реализации), некоторые идентичны по прототипу, но с уникальной реализацией. Некоторые вообще - свои собственные:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class SomeClass1
{
public:
   void CommonMethod() {}   //идентичен методам других классов
   void UniqueMedthod() {}    //уникальная реализация
}
 
class SomeClass2
{
public:
   void CommonMethod() {}   //идентичен методам других классов
   void UniqueMedthod() {}    //уникальная реализация
}
Каким образом можно добиться единообразности интерфейсов, при условии, что некоторые методы должны будут делать нечто уникальное. И даже те методы, которые изначально планировались как дефолтные для всех классов, в последствии для отдельных классов нужно будит переделывать, заменяя их реализацию.

1 Способ: Copy-Paste

Тупо копипастим прототипы по всем классам. Где нужно - копипастим и реализации. Где нужно - пишем ручками что-то своё.

Достоинства:
Быстро и просто.
Классы получаются абсолютно никак не связанны друг с другом. Можно делать любые модификации одного класса, и они никак не отразятся на других классах.

Недостатки:
Если выяснится, что для всех классов метод CommonMethod(); должен начать работать как то иначе (а такое случается сплошь и рядом, особенно, если в нем созрел ужасссссный баг) - придется придется заного все перекопипастивать, и пере тестировать.
Кроме того - дублирование существующего кода.

2 Способ: полиморфизм.

Можно просто унаследоваться от интерфейса, и переопределить реализацию тех методов, которые у клиента должны иметь уникальную реализацию. А можно разработать целую иерархию интерфейсов и микшировать их для отдельных клиентов-потомков при помощи наследования.

Достоинства: относительно простое и по своему элегантное решение. Классы-клиенты связаны некоторыми семейными узами. Что позволяет менять поведение объекта "на лету", и тп.
Кроме того, появляется возможность пользоваться "дефолтным интерфейсом".

Недостатки: потери производительности. Там, где нет необходимости воспринимать целое семейство объектов, как одну сущность, и где нет необходимости реализовывать различное поведение объекта "на лету" - полиморф пожалуй... не вполне подходит по смыслу...

3. Шаблоны.

В общем виде, это делается так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <class Client> struct TData {};   //объявляем данные-члены будущего класса-клиента
 
template <class Client> 
class TInterface: public TData<Client> { ...  }; //объявляем интерфейс будущих клиентов
 
 
class ConcreteClient; //предварительное объявление
 
template <>
struct TData<ConcreteClient> {}; //уточняем данные члены для конкретного класса-клиента
 
//если нужно уточняем отдельные методы интерфейса для конкретного класса-клиента
 
class ConcreteClient: public TInterface<ConcreteClient> { }; //подключаем интерфейс к клиенту
Таким образом, класс клиент получит свой интерфейс, и свои данные-члены.

Недостатки:Архитектура с шаблонами значительно усложняется.
Кроме того, если класс-клиент сам является шаблоном, начнутся серьёзные траблы. Потому что нельзя выполнить частичную специализацию отдельного метода. И тогда придётся городить обходные пути. Все это в конечном счете настолько может усложнить понимание архитектуры, что начинают приходить крамольные мысли в голову: может быть копипаста - не такое уж зло?

Недостатки: иногда проще скопипастить прототип с реализацией, чем копипастить этот же самый прототип с этой же самой реализацией и ещё уродливую километровую шапку шаблона в придачу.

Достоинства: эффект как от полиморфизма, только нет потерь производительности.

Шаблоны великолепная костыле-забивалка. Через задний проход позволяют извратить любую архитектуру до неузнаваемости. Но зато, если очень нужно можно всегда переиначить что угодно и как угодно. Так же, позволяют юзать дефолтный интерфейс, а уточнять только те методы, которые для клиента должны быть уникальными.

4. Препроцессор.

Делается это так:

C++
1
2
3
4
class Client
{
        #include "IClient.h" //подключаем интерфейс клиента
};
Внутри файла "IClient.h" содержится:

C++
1
2
3
#include "CommonInterface.h" //подключаем идентичные для всех клиентов методы
 
//ниже идёт перечень всех уникальных методов
Достоинства: Очень простой и элегантный по своему способ. Позволяет без каких бы то ни было особых ухищрений и дублирования кода добиться эффекта "копипасты", но с той разницей. Что если что то где-то нужно будит поменять - менять придётся только в одном месте, а не во всех файлах.

Недостатки: При таком подходе у меня в студии ассистент тупить начал. А без него работать уже не комфортно.

Недостатки: Получается, что файлы cpp уже и не нужны. Вся реализация классов оказывается в хэдерах. Это может плохо сказаться на скорости компиляции, и на сокрытии данных.

Главный недостаток: если вдруг окажется, что клиенту больше не нужен "идентичный как у всех метод", и нужно будит сделать его уникальным, то попытка отвязать класс от commonInterface.h может доставить таких лулзов, что шаблоны сказкой покажутся.

Когда инклюд начинает сидеть на инклюде, и все это инклюдится в 100500 классов - начинаешь в такой архитектуре быстро путаться. Получается каша из классов. Многие классы оказываются "как то странно друг с другом связанны".

Нельзя будит никак менять те интерфейсные методы, которые уже внедрены во множество других классов, из-за боязни их отказа.

Это способы конструирования единообразного интерфейса, которые я знаю. А как делаете вы?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.10.2011, 14:32     Проектирование ОО архитектуры
Посмотрите здесь:

Реализация архитектуры - C++
Задача такая. Есть класс строк ( десятичная , символьная и т.п.) и операции к ним. Я собрал архитектуру, и с помощью класса SWITCH я...

Немного из архитектуры ЭВМ - C++
Пусть заданы две квадратных матрицы A и B размером NxN. Они созданы с помощью двух подходов: 1 подход: int **A; A = new int*; ...

Предложения по изменению архитектуры - C++
Есть код (много но просто): #include &lt;iostream&gt; #include &lt;memory&gt; #include &lt;vector&gt; using namespace std; class SceneNode ...

Организация архитектуры движка - C++
коротко интро: Есть три компонента, они в исходниках естессно, так как пишу их я. так вот эти три компонента должны ...

Задача проектирования архитектуры - C++
добрый день. недавно дали первое моё самостоятельное задание. ну, как самостоятельное, просто мне дали в этом задании полную свободу...

Ошибка при построении архитектуры if-else - C++
Добрый день! Написал программу по условию: (см. 1 картинку) Выглядит программа так: #include &quot;stdio.h&quot; #include...

Нужна помощь в выборе архитектуры системы. - C++
Стоит задача создать довольно сложную систему. Прошу помоч в выборе архетектуры. Примерное ТЗ: Есть много (150-200) компьютеров,...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
oxotnik
1589 / 1066 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
18.10.2011, 14:39     Проектирование ОО архитектуры #2
Цитата Сообщение от Bers Посмотреть сообщение
А как делаете вы?
2-й способ самый понятный и логичный, а что касается производительности, то... как то не замечал
ЗЫ: 4-й метод смахивает на идусизм и быдлокод
Mr.X
Эксперт С++
3048 / 1693 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
18.10.2011, 14:44     Проектирование ОО архитектуры #3
1. Ну, поскольку вы ясно не сформулировали задачу, т.е. для чего именно вам нужен схожий интерфейс не связанных между собой классов, то и ясный ответ сформулировать невозможно.
2. В качестве примера вы привели контейнеры STL, и в то же время обобщенное программирование не рассматриваете в качестве варианта.
Kastaneda
18.10.2011, 14:44
  #4

Не по теме:

Цитата Сообщение от oxotnik Посмотреть сообщение
ЗЫ: 4-й метод смахивает на идусизм и быдлокод
В духе PHP

Bers
Заблокирован
18.10.2011, 14:47  [ТС]     Проектирование ОО архитектуры #5
Цитата Сообщение от oxotnik Посмотреть сообщение
2-й способ самый понятный и логичный, а что касается производительности, то... как то не замечал
ЗЫ: 4-й метод смахивает на идусизм и быдлокод
А вы можете подробнее раскрыть этот момент: почему смахивает на быдлокод?
oxotnik
1589 / 1066 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
18.10.2011, 14:56     Проектирование ОО архитектуры #6
Цитата Сообщение от Bers Посмотреть сообщение
А вы можете подробнее раскрыть этот момент: почему смахивает на быдлокод?
ну я так представил, что мне подобный код от кого нибудь достанется, брр.. мое имхо было бы при взгляде на это, что автор не владеет принципами ООП, либо их намеренно игнорит, дабы запутать. К стати обфускаторы примерно по такому принципу работают, только больше на дефайнах.
Bers
Заблокирован
18.10.2011, 15:45  [ТС]     Проектирование ОО архитектуры #7
допустим есть два контейнера:

TGameContainer<T>
TContainer2D<T>

Оба контейнеры, но служат для разных целей. Выполняют их по разному, имеют разные данные-члены.

Игровой контейнер - пул для игровых объектов, а контейнер2д - тот же вектор, только позволяет сделать имитацию, якобы элементы хранятся в двух мерной матрице, а не просто в каком нибудь векторе.

Несмотря на значительные отличия, для удобства пользования хочется сделать им максимально схожий интерфейс. Оба они имеют метод GetElement(); или метод Clear(); или метод Resize();

Есть шаблонный метод: ConvertArg() который на входе может принимать число, символ, строку (в общем на то он и шаблон), а на выходе рожать стринг. И этот метод нужен обоим контейнерам, и он блин, абсолютно одинаковый что там, что там.

Как сделать лучше?

Полиморфизм использовать там, где он не нужен в рантайме - это мне видится фейлом.

Шаблоны - у меня классы-клиенты через одного шаблоны. Я уже экспериментировал - чуть мозг себе не спалил. Там все либо резко усложняется, либо ведёт к хардкорной копипасте.

Остаётся либо копипаста, либо препроцессор.

Думаю препроцессор лучше сразу исключить.

Остаётся копипаста?
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
18.10.2011, 16:32     Проектирование ОО архитектуры #8
Bers, именно для таких вещей в джаве и шарпе используются интерфейсы. Поскольку в чистом виде в плюсах их нет, то надо использовать абстрактные базовые классы (которые по сути своей те же интерфейсы, только возможностей у них чуть больше).
А вообще, там, где нужна реальная производительность, забивают на ООП и пишут на структурных языках. Если вам действительно нужна производительность - так и поступите. Если же вы о производительности говорите лишь постольку-поскольку - забейте и используйте полиморфизм.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1286 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
18.10.2011, 16:52     Проектирование ОО архитектуры #9
Цитата Сообщение от Bers Посмотреть сообщение
Недостатки: потери производительности. Там, где нет необходимости воспринимать целое семейство объектов, как одну сущность, и где нет необходимости реализовывать различное поведение объекта "на лету" - полиморф пожалуй... не вполне подходит по смыслу...
Потери производительности не будет в этом случае. Если полиморфного использования нет, то компилятор может очень эффективный код генерировать. Даже при наличии полиморфизма, в некоторых случаях удаётся встраивать виртуальные функции. При использовании наследования без полиморфного использования у компилятора очень много возможностей для оптимизации.
И вообще, до первого запуска ты точно сказать не сможешь, "медленно или быстро".)
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
18.10.2011, 16:54     Проектирование ОО архитектуры #10
Цитата Сообщение от Deviaphan Посмотреть сообщение
до первого запуска ты точно сказать не сможешь, "медленно или быстро"
А зачастую и после него)) Было бы с чем сравнивать))
Bers
Заблокирован
18.10.2011, 16:54  [ТС]     Проектирование ОО архитектуры #11
Цитата Сообщение от silent_1991 Посмотреть сообщение
Bers, именно для таких вещей в джаве и шарпе используются интерфейсы. Поскольку в чистом виде в плюсах их нет, то надо использовать абстрактные базовые классы (которые по сути своей те же интерфейсы, только возможностей у них чуть больше).
А вообще, там, где нужна реальная производительность, забивают на ООП и пишут на структурных языках. Если вам действительно нужна производительность - так и поступите. Если же вы о производительности говорите лишь постольку-поскольку - забейте и используйте полиморфизм.
Ладно хорошо. Допустим, я забил на производительность. Но я же не могу забить на здравый смысл.

Если в рантайме не требуется полиморфизм?
Что из этого вытекает? Из этого вытекает, что есть несколько методов с идентичными реализациями, и есть кучка одноименных методов с уникальными реализациями.

Что значит переопределить виртуальный метод?
Это значит:
1. КОПИПАСТА ЕГО ПРОТОТИПА.
2. В ручную пишется реализация этого метода.

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

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

Я же хотел избавиться от необходимости каждый раз в новом классе заново копипастить весь набор прототипов, которые я хочу сделать уникальным.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1286 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
18.10.2011, 16:58     Проектирование ОО архитектуры #12
Цитата Сообщение от Bers Посмотреть сообщение
Полиморфизм использовать там, где он не нужен в рантайме - это мне видится фейлом.
Наследование и полиморфизм это не одно и то же. Наличие виртуальных функций не обязывает использовать полиморфизм.

Добавлено через 41 секунду
Цитата Сообщение от silent_1991 Посмотреть сообщение
А зачастую и после него)) Было бы с чем сравнивать))
С ощущениями и мировозрением.)
Жопой чую, медленно работает! Как-то так.)

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Я же хотел избавиться от необходимости каждый раз в новом классе заново копипастить весь набор прототипов, которые я хочу сделать уникальным.
Но уникальную реализацию всё равно придётся писать. А это "несколько дольше".
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
18.10.2011, 16:58     Проектирование ОО архитектуры #13
Bers, что-то вы всё диким образом утрируете... копипаста прототипов... таким макаром можно дойти и до того, что в коде слишком много повторяющихся символов, и что это тоже копипаста...
Bers
Заблокирован
18.10.2011, 17:03  [ТС]     Проектирование ОО архитектуры #14
Цитата Сообщение от silent_1991 Посмотреть сообщение
Bers, что-то вы всё диким образом утрируете... копипаста прототипов... таким макаром можно дойти и до того, что в коде слишком много повторяющихся символов, и что это тоже копипаста...
Вы хотите сказать, что копипастить реализации - это не хорошо. Но копипастить просто прототипы, и писать уникальную их реализацию не возброняеццо?

И что это лучше, чем извращаться с препроцессором и шаблонами?

(а то у меня тут в арсенале есть ещё одна мыслишка, как организовать имитацию частичной специализации отдельного метода шаблонного класса с помощью наследования + препроцессор. Но чота у меня такое лёгкое подозрение, шо это уже паранойя)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.10.2011, 17:07     Проектирование ОО архитектуры
Еще ссылки по теме:

Программа проверки знания истории архитектуры - C++
Напишите программу проверки знания истории архитектуры. Программа должна вывести вопрос и три варианта ответа. Пользователь должен выбрать...

Эмуляция х86 архитектуры для работы borland 3.1 - C++
Тема в сабже, собственно. Подскажите хороший эмулятор. DosBox - не совсем устраивает. слишком много багов. либо посоветуйте...

Посоветуйте литературу или статьи по правильному составлению архитектуры кода программ - C++
Здравствуйте программисты. Посоветуйте пожалуйста литературу или статьи по правильному составлению архитектуры кода программ. А то...

Написать курсовую по теме "Разработка архитектуры и компонентов системы и автоматизации автосервиса" - C++
Добрый день! Есть такая проблема, учусь в колледже, задали написать курсовую по теме &quot;Разработка архитектуры и компонентов системы и...

Проектирование программы - C++
Здравствуйте! Подскажите пожалуйста, какими средствами эффективнее проектировать и рекодить программу? Тема стала актуальна с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
18.10.2011, 17:07     Проектирование ОО архитектуры #15
Bers, я же вам сказал, что в других языках (которые по сути ближе к ООП, чем плюсы) для этого выделен даже специальный механизм - интерфейсы. Специальный-то он специальный, но по сути своей это те же базовые абстрактные классы. Так что можете смело использовать их - не возбраняеццо.
Yandex
Объявления
18.10.2011, 17:07     Проектирование ОО архитектуры
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru