Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Общие вопросы по программированию, компьютерный форум
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.05.2009, 01:21   #1
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Стрелка В поисках совершенных абстракций

Для C++ существует огромное множество библиотек выполненных в различных техниках исполнения. Программисты создавшие их следовали разным ментальным моделям. К сожалению лично мне использование этих творений неудобно, хотя они и предоставляют весь нужный функционал. Похоже проблема в том, что сами программисты создавая свои творения мыслили в парадигме обобщённого функционального, вместо обобщённого объектно-ориентированного программирования.

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

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

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

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

Последний раз редактировалось MaTBeu; 03.05.2009 в 13:12.
atomicxp вне форума Ответить с цитированием
Старый 03.05.2009, 13:16   #2
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,619
По умолчанию

Даже если математические сущности разбить по классам, арифметические, тригонометрические, комплексные и прочие - разве это придаст удобства при работе с ними? В данном случае не стоит говорить о принадлежности к обобщенному объектно-ориентированному программированию, ибо все можно, но не все НУЖНО приводить к объектам. Простой пример: как вам лучше будет писать?
Так
Код:
int a = 1, b = 2, c;
c = Math::Arithmetic::Plus(a, b);
или так
Код:
int a = 1, b = 2, c;
c = a + b;
Ответ я думаю и так ясен.
MaTBeu вне форума Ответить с цитированием
Старый 03.05.2009, 19:14   #3
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Печаль

Предположим у нас есть операция сложения. Вопрос как лучше её воспринимать, функцией, следуя парадигме функционального программирования или как сущность в объектно-ориентированном переопределяя однотипные методы.

В языке C++ существуют операторы, благодаря им есть возможность записывать последовательность определённых видов операций в кратком виде выражением, однако сути это не меняет. Для начала можно написать что-либо наподобие этого, все равно в последствии оно будет оптимизировано исключив повторные определения, потому что Addition и operator+ одно и тоже, а static Addition почти.

Код:
namespace Arithmetic
{
    // Операция сложения
    template<typename TSequence> class IAddition
    {
    public:
        // Сложение (объектное)
        // arg addend="добавляемое"
        // return "сумма"
        virtual TSequence& Addition(const TSequence& addend) const = 0;
        // Оператор сложения
        // arg addend="добавляемое"
        // return "сумма"
        virtual TSequence& operator+(const TSequence& addend) const = 0;
        // Сложение (статическое)
        // arg augend="увеличиваемое"
        // arg addend="добавляемое"
        // return "сумма"
        static TSequence& Addition(const TSequence& augend, const TSequence& addend);
    };
}
Интересен тот факт, что данный интерфейс работает прежде всего с последовательностями. Иными словами используются ли числа для полиморфного интерфейса или последовательности, но воспринимается он как единое понятие.
atomicxp вне форума Ответить с цитированием
Старый 05.05.2009, 18:55   #4
mustaf0id
 
Регистрация: 05.05.2009
Сообщений: 9
Радость

Цитата:
Предположим у нас есть операция сложения. Вопрос как лучше её воспринимать, функцией, следуя парадигме функционального программирования или как сущность в объектно-ориентированном переопределяя однотипные методы.
При рассмотрении операции сложения я бы выделил такие особенности:
1) ассоциативность - т.е. например a+b+c+d+e+f можно считать как (a+b)+(c+d)+(e+f) что на больших массивах позволило бы распараллеливать вычисления
2) a+b=b+a что может использоваться только например чтобы тестировать реализацию для каких-нибудь новых типов, хотя например для double это всё равно не выполняется
3) сложение имеет обратную операцию - вычитание

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

Хотя в практических приложениях такие сложности для сложения помоему вряд ли понадобятся, по крайней мере на С++
mustaf0id вне форума Ответить с цитированием
Старый 05.05.2009, 19:15   #5
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,619
По умолчанию

Цитата:
1) ассоциативность - т.е. например a+b+c+d+e+f можно считать как (a+b)+(c+d)+(e+f) что на больших массивах позволило бы распараллеливать вычисления
Каким образом распараллеливать?
Цитата:
2) a+b=b+a что может использоваться только например чтобы тестировать реализацию для каких-нибудь новых типов, хотя например для double это всё равно не выполняется
Эммм... почему это не выполняется?
Цитата:
Хотя в практических приложениях такие сложности для сложения помоему вряд ли понадобятся, по крайней мере на С++
И я о том же.
MaTBeu вне форума Ответить с цитированием
Старый 05.05.2009, 20:31   #6
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Лампочка

Цитата:
Сообщение от mustaf0id Посмотреть сообщение
1) ассоциативность - т.е. например a+b+c+d+e+f можно считать как (a+b)+(c+d)+(e+f) что на больших массивах позволило бы распараллеливать вычисления
Интересная, кстати, мысль. Дело даже не в сложении, а в попытке разъединить параллельность на мельчайшие операции. Конечно, я не спец. в работе многоядерных процессоров, но думается есть некая задержка между синхронизациями потоков, которая сделает быстрые вычисления, то есть те у которых временной период меньше, чем переключение между нитями процессов, менее эффективным.

Однако все равно появляется существенный повод задуматься, над масштабируемостью, балансировкой вычислительной мощности и так далее

Цитата:
Сообщение от mustaf0id Посмотреть сообщение
2) a+b=b+a что может использоваться только например чтобы тестировать реализацию для каких-нибудь новых типов, хотя например для double это всё равно не выполняется
Сейчас появились такие технологии как CUDA, да и думаю много что ещё, о чём я не подозреваю. CPU, GPU и другие, может даже в будущем PPU, это же процессорные единицы имеющие ряд команд. Абстракция типов навроде того же double, к примеру, в Real, поможет не только управлять точностью вычислений в зависимости от выбранной архитектуры (CPU 32 бита, 64 бита; GPU nnn бит), но и подменять само вычислительное устройство, т.е. процессорную единицу.

Цитата:
Сообщение от mustaf0id Посмотреть сообщение
3) сложение имеет обратную операцию - вычитание

Можно попробовать выразить это через ООП, например пронаследовав операцию сложения от какой-нибудь абстрактной ассоциативной операции, добавить также классы, проверяющие, что некоторые операции - обратные по отношению к другим и т.д.
Понятие Antonym уже ввёл, но ещё думаю куда бы его прицепить. Наверное выход в полиморфных функция, но здесь тоже как бы надо определиться, особенно, что касается подмены имён. В общем, суть в том, какой из способов нахождения функции антонима выбрать. Ну и сами интерфейсы ещё много раз поменяются.

Код:
#ifndef AX_ARITHMETIC_ADDITION_H
#define AX_ARITHMETIC_ADDITION_H

namespace Arithmetic
{
    // Операция сложения
    template<typename TSequence> class Addition
    {
    public:
        // Сумма (объектная)
        // arg addend="добавляемое"
        // return "сумма"
        virtual TSequence& Sum(const TSequence& addend) const = 0;
        // Оператор сложения
        // arg addend="добавляемое"
        // return "сумма"
        virtual TSequence& operator+(const TSequence& addend) const = 0;
        // Сумма (статическая)
        // arg augend="увеличиваемое"
        // arg addend="добавляемое"
        // return "сумма"
        static TSequence& Sum(const TSequence& augend, const TSequence& addend);
    };
}

#endif // AX_ARITHMETIC_ADDITION_H
Код:
#ifndef AX_ARITHMETIC_SUBTRACTION_H
#define AX_ARITHMETIC_SUBTRACTION_H

namespace Arithmetic
{
    // Операция вычитания
    template<typename TSequence> class Subtraction
    {
    public:
        // Разность (объектная)
        // arg subtrahend="вычитаемое"
        // return "разность"
        virtual TSequence& Difference(const TSequence& subtrahend) const = 0;
        // Оператор вычитания
        // arg subtrahend="вычитаемое"
        // return "разность"
        virtual TSequence& operator-(const TSequence& subtrahend) const = 0;
        // Разность (статическая)
        // arg minuend="уменьшаемое"
        // arg subtrahend="вычитаемое"
        // return "разность"
        static TSequence& Difference(const TSequence& minuend, const TSequence& subtrahend);
    };
}

#endif // AX_ARITHMETIC_SUBTRACTION_H
Код:
#ifndef AX_ARITHMETIC_SHORT_H
#define AX_ARITHMETIC_SHORT_H

#include <Mathematics\Arithmetic\Addition.h>
#include <Mathematics\Arithmetic\Subtraction.h>

namespace Arithmetic
{
    // Короткие арифметические операции
    template<typename TSequence> class Short
        : public Addition<TSequence>, public Subtraction<TSequence>
    {};
}

#endif // AX_ARITHMETIC_SHORT_H
P.S. Вообще-то я уже убрал тут кое-где пространства имён и запихнул их в отдельный класс, просто до этих классов руки ещё не дошли. Сложно не закодировать, сложно выявить зависимости.

Вот интересные ресурсы:
http://www.ietf.org/rfc.html
http://www.w3.org/

Задокументировано множестов стандартов (например,w3.org именнованные цвета и т.д.).

Последний раз редактировалось atomicxp; 05.05.2009 в 20:43.
atomicxp вне форума Ответить с цитированием
Старый 05.05.2009, 21:56   #7
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,619
По умолчанию

Если вы делаете вычитание, то логично было бы сделать класс Substraction наследованным от Addition. Так как свойства у них одинаковые, у разности, просто один из аргументов - отрицательный, а сложение делается так же.
MaTBeu вне форума Ответить с цитированием
Старый 05.05.2009, 22:18   #8
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Стрелка

Цитата:
Сообщение от MaTBeu Посмотреть сообщение
Если вы делаете вычитание, то логично было бы сделать класс Substraction наследованным от Addition. Так как свойства у них одинаковые, у разности, просто один из аргументов - отрицательный, а сложение делается так же.
У меня проходили подобные же мысли, но я решил, что сложение такое же вычитание с отрицательным знаком, как и вычитание с отрицательным знаком - сложение. Иными словами непонятно, что является первичным, а ведь есть ещё и длинные арифметические операции - умножение и деление.

Здесь гораздо интереснее вопрос, каким же шаблоном проектирования реализовать антоним, то есть получать обратную операцию по текущей.
atomicxp вне форума Ответить с цитированием
Старый 05.05.2009, 22:58   #9
mustaf0id
 
Регистрация: 05.05.2009
Сообщений: 9
По умолчанию

Цитата:
Сообщение от MaTBeu Посмотреть сообщение
Эммм... почему это не выполняется?
Из-за округлений, но для этого просто при сравнении можно допускать маленькую разницу (епсилон).

Цитата:
Каким образом распараллеливать?
Можно например выделить в отдельный интерфейс, а там разными способами (например, там будет паттерн стратегия, одна стратегия не будет вообще распараллеливать, другая через open-mp (когда достаточно большой массив чисел нужно сложить), и т.п.). Тогда эти же стратегии можно применять для других ассоциативных операций - умножение, поиск минимального значения и т.д.

Последний раз редактировалось mustaf0id; 05.05.2009 в 23:02.
mustaf0id вне форума Ответить с цитированием
Старый 05.05.2009, 23:39   #10
atomicxp
Форумчанин
 
Аватар для atomicxp
 
Регистрация: 01.05.2009
Сообщений: 110
Печаль

Цитата:
Сообщение от mustaf0id Посмотреть сообщение
другая через open-mp (когда достаточно большой массив чисел нужно сложить)
Посмотрел что за open-mp, мне лично совсем не понравился принцип, убивает все абстракции. Например, метакомпилятор в Qt я тоже считаю недостатком, а не преимуществом.
atomicxp вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
в поисках органайзера crazy horse Софт 6 11.02.2008 16:56
Нахождение совершенных чисел. Паскаль NikLik Помощь студентам 3 23.11.2007 22:19