Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 09:12
Оценка: 34 (4)
Добрый день.

Есть такая штука: Duck typing. В языках, вроде Smalltalk, Python и Ruby она активно используется.

Еще есть несколько интересных обсуждений: Следующий язык программирования
Автор: Зверёк Харьковский
Дата: 25.09.05
и Снова о типизации :)
Автор: Зверёк Харьковский
Дата: 06.10.05
. А так же несколько интересных мнений:

VladD2 в Re[13]: Следующий язык программирования
Автор: VladD2
Дата: 04.10.05
:

Есть такой тип object. С ним можно вытварять очень много. Есть так же рефлексия с помощью которой хочть черта лысого можно динамически вызвать. Но C# — это статически типизированный язык. Если хотити динамики, то их есть у меня. Есть VB.NET с той самой "утиной типизацией", кстати в 9.0 с ней даже по круче будет. Там придумали "утиные интерфесы" — т.е. описываешь интерфейс как "утиный" и приводишь в рантайме к нему любой объект... если у объектоа методы совпадают, то можно вызвать методы через утиный интерфейс. Что это дает? А тот самый комплит ворд и подсказки среды, плюс еще возможность обнаружить ошибку при инициализации ссылки на интерфейс, а не при вызове 101-вого метода. Далее создали динамические переменные. Когда можно намисать та:

a = "SomeMethodName"
...
b.a(x, y)


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


и McSeem2 в Re[14]: Следующий язык программирования
Автор: McSeem2
Дата: 04.10.05
:

Java/C# не являются ни развитием, ни "осознанием ошибок" C++. Они взяли наихудшую парадигму из языка и возвели ее в степень догмы. А именно — идею наследования. Наследование — это самая большая провокация в индустрии. Ни в каком моделировании наследования не существует и в реальной жизни тоже — ни в электронике, ни в бухгалтерии, ни где бы то ни было еще. Есть одно — генеология. Но это не имеет ни малешего отношения к тому, что называется наследованием в программировании. Все эти многоэтажные иерархии классов только усложняют жизнь, вместо того, чтобы упрощать. И служат они одной единственной цели — раздувать и дальше этот мыльный пузырь и продолжать кормить миллиарды индусов. В результате этой идеи возникла дутая индустрия, не обеспеченная никакими реальными активами. А вся мировая практика говорит о том, что рано или поздно этот пузырь лопнет.


Так вот мне интересно, не является ли Duck typing следующей парадигмой после ООП? Ведь в duck typing нет отношения "is-a", а есть что-то типа "like-a" ("can", "respond_to"). Т.е., наследования нет, а полиморфизм, благодоря динамической типизации, есть.

Может быть ООП уже исчерпала себя (как в свое время структурное программирование) и сейчас мы наблюдаем за возникновением новой парадигмы?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Утиные истории vs ООП?
От: Кодёнок  
Дата: 07.10.05 10:19
Оценка: +2
Здравствуйте, eao197, Вы писали:

E>Так вот мне интересно, не является ли Duck typing следующей парадигмой после ООП? Ведь в duck typing нет отношения "is-a", а есть что-то типа "like-a" ("can", "respond_to"). Т.е., наследования нет, а полиморфизм, благодоря динамической типизации, есть.


E>Может быть ООП уже исчерпала себя (как в свое время структурное программирование) и сейчас мы наблюдаем за возникновением новой парадигмы?


Кстати, динамическая типизация тут не обязательна. В С++ возможно объявить шаблонную функцию, которая будет рассчитывать на наличие определенных методов у своих аргументов — и это будет то же самое (только эти требования нигде в коде явно не прописаны, что плохо). Например, в качестве итератора можно передать какой угодно объект, имеющий оператор ++ (и может быть + и -), а в качестве аллокатора соответственно передается любой класс, имеющий такой же набор методов.
Re[2]: Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 10:58
Оценка:
Здравствуйте, Кодёнок, Вы писали:

E>>Так вот мне интересно, не является ли Duck typing следующей парадигмой после ООП? Ведь в duck typing нет отношения "is-a", а есть что-то типа "like-a" ("can", "respond_to"). Т.е., наследования нет, а полиморфизм, благодоря динамической типизации, есть.


E>>Может быть ООП уже исчерпала себя (как в свое время структурное программирование) и сейчас мы наблюдаем за возникновением новой парадигмы?


Кё>Кстати, динамическая типизация тут не обязательна. В С++ возможно объявить шаблонную функцию, которая будет рассчитывать на наличие определенных методов у своих аргументов — и это будет то же самое (только эти требования нигде в коде явно не прописаны, что плохо). Например, в качестве итератора можно передать какой угодно объект, имеющий оператор ++ (и может быть + и -), а в качестве аллокатора соответственно передается любой класс, имеющий такой же набор методов.


Есть небольшое отличие: динамические языки проще адаптировать к некоторым условиям. Например, нужно прочитать из потока заголовок, определить, сколько байт нужно пропустить, а затем прочитать еще несколько байт. Если потоком является файл, то можно просто сделать seek, а если потоком является сокет, то пропускаемые данные нужно читать:
def load_header_and_data( stream )
    h = load_header( stream )
    if stream.respond_to( "seek" )
        stream.seek( h.get_length() )
    else
        stream.read( h.get_length() )
    end
    load_data( stream )
end


На C++ных шаблонах пришлось бы делать какие-то фокусы со специализацией (плагиат отсюда: Кто хотел определения наличия функции-члена?
Автор: MaximE
Дата: 13.09.03
)
template <class T, T val>
struct member_wrapper{};

template <class T>
char test_for_seek(const T&, member_wrapper<void (T::*)(size_t), &T::seek>* p = 0);

template <class T>
double test_for_seek(const T&, ...);

template <class T>
struct has_member_seek
{
    static T t;
    static const bool value = (1 == sizeof(test_for_seek(t)));
};

template<bool b>
struct seeker
{
    template <class T>
    static void seek( T & stream, size_t off )
        {
            std::vector< char > buf( off );
            stream.read( &buf[ 0 ], off );
        }
};

template<>
struct seeker<true>
{
    template <class T>
    static void seek( T & stream, size_t off )
        {
            stream.seek( off );
        }
};

template <class T>
void seek( T & stream, size_t off )
{
    seeker< has_member_seek< T >::value >::seek( stream, off );
}

template< class T >
void load_header_and_data( T & stream )
{
    Header h = load_header( stream );
    seek( stream, h.get_length() );
    load_data( stream );
}


Чесно говоря, подобный duck typing в C++ меня бы забабахал сразу же.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Утиные истории vs ООП?
От: Кодёнок  
Дата: 07.10.05 11:09
Оценка:
Здравствуйте, eao197, Вы писали:

E>На C++ных шаблонах пришлось бы делать какие-то фокусы со специализацией (плагиат отсюда: Кто хотел определения наличия функции-члена?
Автор: MaximE
Дата: 13.09.03
)

E>Чесно говоря, подобный duck typing в C++ меня бы забабахал сразу же.

Ну это недостаток лично С++ (дело все лишь в добавлении одной фичи, аналогичной typeof или sizeof), а не статически типизированных языков.
Re: Утиные истории vs ООП?
От: FR  
Дата: 07.10.05 11:11
Оценка:
Здравствуйте, eao197, Вы писали:

E>Добрый день.



E>Так вот мне интересно, не является ли Duck typing следующей парадигмой после ООП? Ведь в duck typing нет отношения "is-a", а есть что-то типа "like-a" ("can", "respond_to"). Т.е., наследования нет, а полиморфизм, благодоря динамической типизации, есть.


Так вроде Duck typing обобщенное программирование в чистом виде, а это довольно старая парадигма
Re[2]: Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 11:17
Оценка:
Здравствуйте, FR, Вы писали:

E>>Так вот мне интересно, не является ли Duck typing следующей парадигмой после ООП? Ведь в duck typing нет отношения "is-a", а есть что-то типа "like-a" ("can", "respond_to"). Т.е., наследования нет, а полиморфизм, благодоря динамической типизации, есть.


FR>Так вроде Duck typing обобщенное программирование в чистом виде, а это довольно старая парадигма


На момент появления C++ ООП так же было старой парадигмой

По поводу обобщенного программирования. Смотрим: http://en.wikipedia.org/wiki/Generic_programming

In computer science, generics is a technique that allows one value to take different datatypes (so-called polymorphism) as long as certain contracts such as subtypes and signature are kept. The programming style emphasizing use of this technique is called generic programming.


Duck typing -- это обобщенное программирование в терминах signatures. А обобщенное программирование в C#/Java -- в терминах subtypes, т.е. в рамках традиционного ООП с наследованием.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Утиные истории vs ООП?
От: FR  
Дата: 07.10.05 11:22
Оценка:
Здравствуйте, eao197, Вы писали:

E>Duck typing -- это обобщенное программирование в терминах signatures. А обобщенное программирование в C#/Java -- в терминах subtypes, т.е. в рамках традиционного ООП с наследованием.


Но все равно оно
Re[4]: Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 11:27
Оценка:
Здравствуйте, Кодёнок, Вы писали:

E>>На C++ных шаблонах пришлось бы делать какие-то фокусы со специализацией (плагиат отсюда: Кто хотел определения наличия функции-члена?
Автор: MaximE
Дата: 13.09.03
)

E>>Чесно говоря, подобный duck typing в C++ меня бы забабахал сразу же.

Кё>Ну это недостаток лично С++ (дело все лишь в добавлении одной фичи, аналогичной typeof или sizeof), а не статически типизированных языков.


Ok. А как бы это выглядело со статически типизированным C# и его generic-ами? Можно ли там будет добавить такое ключевое слово, которое можно будет применить к параметру шаблона?
void LoadHeaderAndData( T stream )
{
    Header h = LoadHeader( stream );
    if( stream.HasMethod( "Seek" ) )
        stream.Seek( h.GetLength() );
    else
        stream.Load( h.GetLength() );
    LoadData( stream );
}


или же там все это нужно через рефлекшен делать (только толку тогда от такой статической типизации)?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Утиные истории vs ООП?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.10.05 11:31
Оценка: 24 (2)
Здравствуйте, eao197, Вы писали:

E>Может быть ООП уже исчерпала себя (как в свое время структурное программирование) и сейчас мы наблюдаем за возникновением новой парадигмы?

Ну, возможно все-таки исчерпала. Статически типизированное ООП само по себе — штука очень простая. После длительного шатания из стороны в сторону все-таки пришли к более-менее единому знаменателю в виде классов/интерфейсов.

Дальнейшее развитие ООП-мейнстрима почему-то идет по пути
а) встраивания паттернов в язык — т.е. развитие над-ООП надстроек
б) введение ортогональных парадигм — например, generics.

Наверное, как раз оттого, что улучшать ООП уже некуда.

Duck typing, в принципе, не обязан работать динамически. Его можно было бы ввести, например, в constraintы generic. Т.е. вместо введения интерфейса ICountable { int Count { get; } } и заставления всех мыслимых параметров шаблона явно от него наследоваться при помощи
class SmartType<T>
where T: ICountable
{
  public static int q(T param) { return t.Count;}
}

мы бы вводили утиный интерфейс ICountable, который бы вынуждал выполнять биндинг на этапе инстанцирования дженерика. Вся информация в принципе есть; особой тяжести здесь нету — операция выполняется единожды для каждого типа.
В отличие от, скажем, приведения произвольного object к нашему интерфейсу, которое не удастся сделать привычным ловким методом дотнета.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 11:42
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, eao197, Вы писали:


E>>Может быть ООП уже исчерпала себя (как в свое время структурное программирование) и сейчас мы наблюдаем за возникновением новой парадигмы?


S>Duck typing, в принципе, не обязан работать динамически. Его можно было бы ввести, например, в constraintы generic. Т.е. вместо введения интерфейса ICountable { int Count { get; } } и заставления всех мыслимых параметров шаблона явно от него наследоваться при помощи

S>
S>class SmartType<T>
S>where T: ICountable
S>{
S>  public static int q(T param) { return t.Count;}
S>}

S>

S>мы бы вводили утиный интерфейс ICountable, который бы вынуждал выполнять биндинг на этапе инстанцирования дженерика. Вся информация в принципе есть; особой тяжести здесь нету — операция выполняется единожды для каждого типа.
S>В отличие от, скажем, приведения произвольного object к нашему интерфейсу, которое не удастся сделать привычным ловким методом дотнета.

Что то похожее на: Unintrusive Retroactive Polymorphism
Автор: c-smile
Дата: 05.01.05
?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: Утиные истории vs ООП?
От: Кодёнок  
Дата: 07.10.05 11:52
Оценка:
Здравствуйте, eao197, Вы писали:

E>Ok. А как бы это выглядело со статически типизированным C# и его generic-ами? Можно ли там будет добавить такое ключевое слово, которое можно будет применить к параметру шаблона?


Теоретически — нет проблем, так же как и в С++.

void LoadHeaderAndData( T stream )
{
    Header h = LoadHeader( stream );
    if( has_method(stream, Seek) )
        stream.Seek( h.GetLength() );
    else
        stream.Load( h.GetLength() );
    LoadData( stream );
}


has_method должен быть инструкцией компилятору, т.е. полностью выполняться во время компиляции, и быть замененным на результат. Как sizeof в C++. Тогда has_method может принимать идентификаторы или строковые литералы (has_method(stream, "Seek")), т.к. разницы особой нет (разве что строковые литералы можно "склеить" с другими и потенциально ввести еще инструкции для разбора строк во время компиляции, т.е. возможностей с ними больше).

Единственное условие — чтобы код, который никогда не выполнится (if (false) ...), не проверялся на корректность. Более сложный вариант — чтобы проверялся весь код, кроме обращений к методам, которые пытались найти с помощью has_method. Т.е. если метода Seek нет, но компилятор видит, что программист использовал has_method, чтобы его найти, он не проверяет весь стейтмент. Что лучше, не знаю.
Re[6]: Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 12:05
Оценка:
Здравствуйте, Кодёнок, Вы писали:

E>>Ok. А как бы это выглядело со статически типизированным C# и его generic-ами? Можно ли там будет добавить такое ключевое слово, которое можно будет применить к параметру шаблона?


Кё>Теоретически — нет проблем, так же как и в С++.


<...код поскипан...>
Кё>has_method должен быть инструкцией компилятору, т.е. полностью выполняться во время компиляции, и быть замененным на результат. Как sizeof в C++. Тогда has_method может принимать идентификаторы или строковые литералы (has_method(stream, "Seek")), т.к. разницы особой нет (разве что строковые литералы можно "склеить" с другими и потенциально ввести еще инструкции для разбора строк во время компиляции, т.е. возможностей с ними больше).

Да в том-то и дело, если почитать Re[15]: Следующий язык программирования
Автор: VladD2
Дата: 07.10.05
, то оказывается, что в отличии от generic-ов Java, generic-и C# предназначены для инстанциирования в run-time (не compile-time). Поэтому компилятор на этапе компиляции приведенного тобой кода не сможет понять, какая сигнатура будет у метода Seek.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Утиные истории vs ООП?
От: Dyoma Россия http://www.livejournal.com/users/dyomap/
Дата: 07.10.05 12:54
Оценка: 40 (5) +1 :)))
Здравствуйте, eao197, Вы писали:

E>Есть такая штука: Duck typing. В языках, вроде Smalltalk, Python и Ruby она активно используется.


За Python и Ruby не скажу — дела с ними не имел, а Smalltalk — это одна сплошная "утиная история", подругому на нем писать нету синтаксических возможностей.


E>Так вот мне интересно, не является ли Duck typing следующей парадигмой после ООП? Ведь в duck typing нет отношения "is-a", а есть что-то типа "like-a" ("can", "respond_to"). Т.е., наследования нет, а полиморфизм, благодоря динамической типизации, есть.


Типизация и ОО — вещи абсолютно ортогональные. ОО — способ смотреть на мир. С точки зрения ОО весь мир — объекты, с все взаимодействия между объектами — посылка сообщений. О типизации ОО вообще ничего не говорит.
Типизация бывает статической и динамической.
Статическая это вид верификации. На код накладываются дополнительные ограничения и компилятор их проверяет. Выявляет некоторые ошибки до старта программы и дает некоторые гарантии. В частности, компилятор гарантирует, что объект обязался понимать посланное ему сообщение (там где отсутствует явное приведение типов).
Исторически статическая типизаия использовалась как способ дать компилятору подскази для построения эффективного кода. Например, С++ компилятор, строит vtbl для класса размером не на все возможные (в системе) сообщения, а только на определенные в этом классе. В Smalltalk, например, такой оптимизации не делается. По этому если Smalltalk объект получает "непонятное" для него сообщение, то он кидает исключение, а C++ объект начинает вести себя непредсказуемым образом (что почти всегда приводит к GPF, а иногда к порче данных или странному поведению).
Динамическая типизация это просто наличие у объекта такого свойства как тип. Отсутвие такого свойства никак не мешает ему быть объектом, т.е. реагировать на сообщения (пример — Self).
Более того, типизация несколько мешает ОО. Чистое объектное видение мира подразумевает, что любой объект потенциально может отреагировать на любое сообщение. Или другими словами есть только объекты и объекты не различаются ничем, кроме своего поведения. Например, к каждому человеку можно подойти с вопросом "Сколько ты будешь делать?" с параметром ТЗ. На что можно получить в ответ "N дней", "Чего???" или по зубам . Но коллапса с миром не случит в любом случае.

E>Еще есть несколько интересных обсуждений: Следующий язык программирования
Автор: Зверёк Харьковский
Дата: 25.09.05
и Снова о типизации :)
Автор: Зверёк Харьковский
Дата: 06.10.05
. А так же несколько интересных мнений:


E>VladD2 в Re[13]: Следующий язык программирования
Автор: VladD2
Дата: 04.10.05
:

E>

E>Есть такой тип object. С ним можно вытварять очень много. Есть так же рефлексия с помощью которой хочть черта лысого можно динамически вызвать. Но C# — это статически типизированный язык. Если хотити динамики, то их есть у меня. Есть VB.NET с той самой "утиной типизацией", кстати в 9.0 с ней даже по круче будет. Там придумали "утиные интерфесы" — т.е. описываешь интерфейс как "утиный" и приводишь в рантайме к нему любой объект... если у объектоа методы совпадают, то можно вызвать методы через утиный интерфейс. Что это дает? А тот самый комплит ворд и подсказки среды, плюс еще возможность обнаружить ошибку при инициализации ссылки на интерфейс, а не при вызове 101-вого метода. Далее создали динамические переменные. Когда можно намисать та:

Это еще один пример как можно совмещать прелести верификации с ОО.

E>и McSeem2 в Re[14]: Следующий язык программирования

:
E>[q]
E>Java/C# не являются ни развитием, ни "осознанием ошибок" C++. Они взяли наихудшую парадигму из языка и возвели ее в степень догмы. А именно — идею наследования. Наследование — это самая большая провокация в индустрии. Ни в каком моделировании наследования не существует и в реальной жизни тоже — ни в электронике, ни в бухгалтерии, ни где бы то ни было еще. Есть одно — генеология. Но это не имеет ни малешего отношения к тому, что называется наследованием в программировании. Все эти многоэтажные иерархии классов только усложняют жизнь, вместо того, чтобы упрощать. И служат они одной единственной цели — раздувать и дальше этот мыльный пузырь и продолжать кормить миллиарды индусов. В результате этой идеи возникла дутая индустрия, не обеспеченная никакими реальными активами. А вся мировая практика говорит о том, что рано или поздно этот пузырь лопнет.


С этой мыслью, я не спорю, но она imho к вопросу отношния не имеет. Скорее к вопросу, какие парадигмы есть возможность сделать mainstream.

E>Может быть ООП уже исчерпала себя (как в свое время структурное программирование) и сейчас мы наблюдаем за возникновением новой парадигмы?


"Утиные истории" появились задолго до ОО, например тот же Lisp.

Dyoma
ALMWorks
http://deskzilla.com/
Re[5]: Утиные истории vs ООП?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.10.05 13:01
Оценка:
Здравствуйте, eao197, Вы писали:
E>Ok. А как бы это выглядело со статически типизированным C# и его generic-ами?
С дженериками — никак. Потому, что такая базовая вещь, как поток, не должна вводиться через дженерик. Вот так выглядит код на реальном шарпе:

public void LoadHeaderAndData(Stream stream)
{
  Header h = LoadHeader(stream);
  if(stream.CanSeek())
    stream.Seek(h.GetSkipLength());
  else
  {
    byte[] buffer = new byte[h.GetSkipLength()];
    stream.Read(buffer, 0, h.GetSkipLength());
  }
  LoadData(stream);
}
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Утиные истории vs ООП?
От: Dyoma Россия http://www.livejournal.com/users/dyomap/
Дата: 07.10.05 13:09
Оценка: 23 (1)
Здравствуйте, Dyoma, Вы писали:

E>>Есть такая штука: Duck typing. В языках, вроде Smalltalk, Python и Ruby она активно используется.


D>За Python и Ruby не скажу — дела с ними не имел, а Smalltalk — это одна сплошная "утиная история", подругому на нем писать нету синтаксических возможностей.


Забыл сюда добавить про движение ровно в противоположную сторону — StrongTalk. Он, к сожалению, так и остался академической разработкой, замятой компанией Sun. Идея заключалась в прикручивании к Smalltalk, системы типов, для целей верификации, подсказок IDE, и может еще чего.
StrongTalk расширяет синтаксис Smalltalk, добавляя опциональные ограничения на тип параметров. Ограничения могут иметь вид:
это параметр понимает такой-то протокол
понимает список протоколов — объединение протоколов.
понимает один из списка протоколов — пересечение.

Протокол — это так в Smalltalk называется понятие более известное как interface.

Dyoma
ALMWorks
http://deskzilla.com/
Re[6]: Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 13:12
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, eao197, Вы писали:

E>>Ok. А как бы это выглядело со статически типизированным C# и его generic-ами?
S>С дженериками — никак. Потому, что такая базовая вещь, как поток, не должна вводиться через дженерик.

Это почему? Где-то потоком будет файл. Где-то строка. Где-то сокет.
Или вокруг этого какие-то обертки, реализующие некоторый интерфейс строить придется?

S> Вот так выглядит код на реальном шарпе:


S>
S>public void LoadHeaderAndData(Stream stream)
S>{
S>  Header h = LoadHeader(stream);
S>  if(stream.CanSeek())
S>    stream.Seek(h.GetSkipLength());
S>  else
S>  {
S>    byte[] buffer = new byte[h.GetSkipLength()];
S>    stream.Read(buffer, 0, h.GetSkipLength());
S>  }
S>  LoadData(stream);
S>}
S>


CanSeek -- это метод интерфейса Stream?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Утиные истории vs ООП?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.10.05 14:20
Оценка:
Здравствуйте, Dyoma, Вы писали:

E>>Так вот мне интересно, не является ли Duck typing следующей парадигмой после ООП? Ведь в duck typing нет отношения "is-a", а есть что-то типа "like-a" ("can", "respond_to"). Т.е., наследования нет, а полиморфизм, благодоря динамической типизации, есть.


D>Типизация и ОО — вещи абсолютно ортогональные. ОО — способ смотреть на мир. С точки зрения ОО весь мир — объекты, с все взаимодействия между объектами — посылка сообщений. О типизации ОО вообще ничего не говорит.


А я про типизацию-то в данной фразе и не говорил. Я имел в виду, что в ООП мы используем отношение "is-a" для определения взаимосвязи между сущностями. Отсюда и необходимость выстраивать иерархии наследования. А если брать duck typing, то наследование здесь вообще пофигу, нет никакого "is-a". Если "like-a". Т.е., если эта штука похожа на чемодан и имеет ручку, то я возьму его и отнесу. И мне не нужно при проектировании плодить сущности "багаж"-"ручная кладь"-"чего-то-там". И если я на самом деле имею дело с портфелем или дипломатом, то мне без разницы, состоит ли он в каких-то родственных оношениях с чемоданом или авоськой.

D>С этой мыслью, я не спорю, но она imho к вопросу отношния не имеет. Скорее к вопросу, какие парадигмы есть возможность сделать mainstream.


Так и я о том, что не станет ли duck typing мейнстримом.

E>>Может быть ООП уже исчерпала себя (как в свое время структурное программирование) и сейчас мы наблюдаем за возникновением новой парадигмы?


D>"Утиные истории" появились задолго до ОО, например тот же Lisp.


Да, но особенности Lisp-а и Smalltalk-а не позволили им набрать большого количества сторонников. А вот Python и Ruby популярность набирают.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[7]: Утиные истории vs ООП?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.10.05 14:21
Оценка:
Здравствуйте, eao197, Вы писали:

E>Это почему? Где-то потоком будет файл. Где-то строка. Где-то сокет.

E>Или вокруг этого какие-то обертки, реализующие некоторый интерфейс строить придется?
Совершенно верно. Потому что требовать от, скажем, строки поддержки метода Read() как-то странно.
В стандартную библиотеку FCL входят и NetworkStream и FileStream.
StringStream нету, потому что поток — это байты, а строка — это символы. Аналогом является MemoryStream.
Для работы с текстовыми данными есть отдельные классы TextReader и TextWriter.

E>CanSeek -- это метод интерфейса Stream?

Абстрактного класса Stream.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Утиные истории vs ООП?
От: Dyoma Россия http://www.livejournal.com/users/dyomap/
Дата: 07.10.05 15:00
Оценка:
Здравствуйте, eao197, Вы писали:

E>А я про типизацию-то в данной фразе и не говорил. Я имел в виду, что в ООП мы используем отношение "is-a" для определения взаимосвязи между сущностями. Отсюда и необходимость выстраивать иерархии наследования. А если брать duck typing, то наследование здесь вообще пофигу, нет никакого "is-a". Если "like-a". Т.е., если эта штука похожа на чемодан и имеет ручку, то я возьму его и отнесу. И мне не нужно при проектировании плодить сущности "багаж"-"ручная кладь"-"чего-то-там". И если я на самом деле имею дело с портфелем или дипломатом, то мне без разницы, состоит ли он в каких-то родственных оношениях с чемоданом или авоськой.


Ну не используется is-a в ООП. Is-a появляется вместе с типами (классами). Вот рассмотрим два варианта: объект используем и объект имплементим.

Когда искользуем, то посылаем ему сообщение, и тут совершенно не важно is-чего-он-там. Важно, что он объект, и послать можно. Тут скорее речь о responds-to. Вот это действительно интересно. В статически типизированых языках тип объекта дает ответ на этот вопрос. В димамически — может дать ответ класс, но не обязательно. В Smalltalk класс может дать только положительный ответ, а отрицательный — не может (см. _vovin вчера подробно про doesNotUnderstand: написал). Is-a это важно компилятору, например, C++. Если объект типа MyClass то сообщени foo() посылается через 5ю запись в vtbl.

Теперь про имплементим. Тут надо написать как объект реагирует на сообщения. Возьмем Self или JavaScript. Никакого is-a. Хватаешь объект и давай ему добавлять/удалять поведение. Опять приходим к response-to.
Но если используем типы (классы), то появляется возможность добавить поведение отнаследовав его от другого класса. Так же тут появляется необходимость в объявлении поддерживаемых наборов сообщений (протоколов, интерфейсов, или как это еще кто назвал). А нужно это только для системы типов, что бы с ее помощью проверить код, или сделать какие-то выводы, но сама идея ОО тут ни при чем.

В твоем примере, что бы таскать багаж типы действительно не нужны. И грузчику ты действительно скажешь "беги за ручку и неси туда". А вот что бы такую процедуру записать на статически типизированном языке тебе понадобится тип "ШтукаСРучкой".

D>>С этой мыслью, я не спорю, но она imho к вопросу отношния не имеет. Скорее к вопросу, какие парадигмы есть возможность сделать mainstream.


E>Так и я о том, что не станет ли duck typing мейнстримом.


Ну от чего же? А VB, особенно VBA, VBscript? Опять же JavaScript? А если еще C#3.0 выйдет?

D>>"Утиные истории" появились задолго до ОО, например тот же Lisp.


E>Да, но особенности Lisp-а и Smalltalk-а не позволили им набрать большого количества сторонников. А вот Python и Ruby популярность набирают.


Я про Lisp написал, как еще один аргумент, что ОО — концепция ортогональная.

Dyoma
ALMWorks
http://deskzilla.com/
Re[3]: Утиные истории vs ООП?
От: Зверёк Харьковский  
Дата: 07.10.05 15:38
Оценка: 4 (1) +4
Здравствуйте, eao197, Вы писали:

E>Есть небольшое отличие: динамические языки проще адаптировать к некоторым условиям. Например, нужно прочитать из потока заголовок, определить, сколько байт нужно пропустить, а затем прочитать еще несколько байт. Если потоком является файл, то можно просто сделать seek, а если потоком является сокет, то пропускаемые данные нужно читать:

E>
E>def load_header_and_data( stream )
E>    h = load_header( stream )
E>    if stream.respond_to( "seek" )
E>        stream.seek( h.get_length() )
E>    else
E>        stream.read( h.get_length() )
E>    end
E>    load_data( stream )
E>end
E>


Уникально мерзопакостный вариант
Для читателя кода — stream.respond_to( "seek" ) — выглядит как грязный хак.
Код должен (в идеале, естественно) читаться как постановка задачи.

С этой точки зрения, финальный вариант на C++

E>template< class T >
E>void load_header_and_data( T & stream )
E>{
E>    Header h = load_header( stream );
E>    seek( stream, h.get_length() );
E>    load_data( stream );
E>}
E>


...читается существенно лучше. Другое дело, что для этого тебе потребовалось неимоверное количество усилий. Однако же. Ты реализовывал не свою постановку задачи "Если потоком является файл, то можно просто сделать seek, а если потоком является сокет", а другую постановку задачи "если у объекта, каким бы он ни был, есть метод seek, то..."

Наиболее изящным решением на C++ было бы — либо А:
template<typename T> seek(T,int);
template<> seek<File>(File _f, int _bytes);
template<> seek<Soket>(Soket _s, int _bytes);


либо Б:
class File
{
...
void skip(int _bytes){seek(_bytes);}
...
}
class Socket
{
...
void skip(int _bytes){read(_bytes);}
...
}



А твое решение (как на Руби, так и на С++) совершенно нерасширяемо — завтра у тебя появится еще один тип потока, у которого надо будет вызвать вообще функцию, скажем, move, и что?
def load_header_and_data( stream )
    h = load_header( stream )
    if stream.respond_to( "seek" )
        stream.seek( h.get_length() )
    else if stream.respond_to( "move" ) //и такие хаки - еще в 18 местах...
        stream.move( h.get_length() )
    else
        stream.read( h.get_length() )
    end
    load_data( stream )
end


Бррр!
FAQ — це мiй ай-кью!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.