Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 28 мар 2024, 20:15

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 43 ]  На страницу Пред.  1, 2, 3, 4, 5  След.
Автор Сообщение
СообщениеДобавлено: 13 янв 2014, 01:52 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Вот тебе "параметрический полиморфизм" на КП, если так уж сильно надо:
Код: "OBERON"
  1. MODULE ParametricPolymorphism;
  2. IMPORT StdLog;
  3.  
  4. TYPE
  5. Type = BYTE;
  6. Data* = EXTENSIBLE RECORD
  7. int: INTEGER; real: REAL; string: ARRAY 256 OF CHAR;
  8. END;
  9.  
  10. CONST
  11. Int = 0; Real = 1; String = 2;
  12.  
  13. VAR
  14. a, b, c: Data;
  15.  
  16. PROCEDURE Plus (OUT res: Data; type: Type; a, b: Data);
  17. BEGIN
  18. CASE type OF
  19. | Int: res.int := a.int + b.int
  20. | Real: res.real := a.real + b.real
  21. | String: res.string := a.string + b.string
  22. END
  23. END Plus;
  24.  
  25. PROCEDURE Out (type: Type; a: Data);
  26. BEGIN
  27. CASE type OF
  28. | Int: StdLog.Int(a.int)
  29. | Real: StdLog.Real(a.real)
  30. | String:StdLog.String(a.string)
  31. END
  32. END Out;
  33.  
  34. PROCEDURE Do* ;
  35. BEGIN
  36. a.int := 1; b.int := 2; Plus(c, Int, a, b); Out(Int, c);
  37. a.real := 1.1; b.real := 2.1; Plus(c, Real, a, b); Out(Real, c);
  38. a.string := "str"; b.string := "ing"; Plus(c, String, a, b); Out(String, c);
  39. END Do;
  40.  
  41. END ParametricPolymorphism.
  42. ParametricPolymorphism.Do ~
Усложнять по вкусу. ;)

Например, если тебе нужно работать с такими типами, которые неизвестны на момент компиляции этого модуля, добавляешь работу с ними примерно так:
Код: "OBERON"
  1. (* В модуле ExtDataType: *)
  2. TYPE
  3. ExtData = RECORD (ParametricPolymorphism.Data)
  4. (* Данные: *)
  5. ext_type: POINTER TO ANYREC END;
  6. (* ... *)
  7. END;
Код: "OBERON"
  1. (* В модуле ParametricPolymorphism: *)
  2. PROCEDURE Plus (OUT res: Data; type: Type; a, b: Data);
  3. BEGIN
  4. CASE type OF
  5. | Int: res.int := a.int + b.int
  6. | Real: res.real := a.real + b.real
  7. | String: res.string := a.string + b.string
  8. (* ... *)
  9. | ExtTypeN: CallProcN(res, a, b); (* Вызываем неизвестную процедуру с неизвестными данными *)
  10. END
  11. END Plus;
Модуль, обрабатывающий новый тип, импортирует ParametricPolymorphism и устанавливает указатель процедуры CallProcN на реальную рабочую процедуру.

geniepro писал(а):
На одно моё слово у тебя десяток в ответ найдётся )))
Да я за тобой даже не поспеваю! Впрочем, надо же тебя направить на путь истинный, на это даже времени не жалко. ;) К тому же не хочу чтобы неопровергнутая чушь на форуме висела. ;)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 13 янв 2014, 06:28 
Не в сети

Сообщения: 203
Zorko писал(а):
Вот тебе "параметрический полиморфизм" на КП, если так уж сильно надо:
Хоспади! Ты привёл пример полиморфизма наследования, это не совсем то же, что и параметрический полиморфизм...

Zorko писал(а):
geniepro писал(а):
На одно моё слово у тебя десяток в ответ найдётся )))
Да я за тобой даже не поспеваю! Впрочем, надо же тебя направить на путь истинный, на это даже времени не жалко. ;) К тому же не хочу чтобы неопровергнутая чушь на форуме висела. ;)
Ага-ага! "Опять в интернете кто-то не прав!" )))
Если бы твоя аська не была бы в моём списке контактов, я бы и времени на твой форум не тратил )))


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 13 янв 2014, 07:08 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Ладно-ладно, трать коли нравится. ;)


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Теология ООП
СообщениеДобавлено: 23 сен 2014, 18:07 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Овик Меликян писал(а):
В последние годы появились весьма неочевидные прогнозы, и даже чуть ли не констатация факта о провале объектной парадигмы, ООП. Крайнюю позицию высказал Ричард Гейбриэл в своем выступлении на OOPSLA под прямым названием "Объектная парадигма провалилась". Другой, более сдержанный и взвешанный прогноз — это Пол Грэм со своей статьей "Языки программирования через сто лет".

Объединяет этих двух людей то, что они приверженцы функционального программирования и языка Lisp. "А, да это брюзгливые математики, для которых высочайшим достижением программирования является интерпретатор языка Lisp на языке Lisp в 20 строк" — так бы я отреагировал на эти статьи годами раньше. Но в статье Ричарда Гейбриэла есть слишком много правды, и в ответах оппонентов (например здесь) слишком мало рационального, чтобы можно было не задумываясь пройти мимо этой дискуссии.

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



***

Вместе с миллионами других программистов и я тоже в свое время испытал радость читая первые статьи об объектном программировании, о том, что методы ООП позволяют создавать иерархии классов объектов так, как это можно делать с объектами реального мира. Есть класс плодов, от него производится класс фруктов, от него — класс цитрусовых, затем апельсины, и тут можно уже создавать объекты класса апельсин. Есть что-то общее для всех плодов, для всех фруктов, затем цитрусовых и для всех апельсинов. Спускаясь вниз по иерархии вы добавляете конкретику, когда как в верхах все ужасно абстрактно. А теперь берем абстрактный GUI объект, определяем абстрактный метод paint() — и вперед с песней. Помните?

Но именно здесь, на этапе объяснения самой парадигмы нас и ждал подвох. Вернитесь к этим текстам теперь, когда вы уже состоявшийся гуру ООП, и перечитайте их внимательно. Во-первых, тут явно попахивает одной очень старой теорией искусственного интеллекта, согласно которой знания человека можно представить в виде дерева — откуда видимо и вышла собственно парадигма ООП. Как известно, никто с тех пор так и не смог создать "мыслящей" машины на основе такого представления, потому что оно нелепо. Поняв это, создатели некоторых языков и ОО платформ попытались исправить положение (сломать дерево, так сказать) введя множественное наследование. Потом его убрали (Джава), сказав, что это слишком сложно и путает как программиста, так и сам компилятор. А потом снова вернут?

Во-вторых. Эти школьные примеры с GUI объектами на самом-то деле и есть область применения ООП. В мире реального программирования многое можно, а иногда даже нужно, делать без этого. Зачастую описывая классы мы даже не задумываемся над тем, а будут ли объекты данного класса persistent настолько, что следует вводить понятие состояния объекта, и тем самым усложнять его реализацию. Какая-то группа данных, т.е. структура, действительно может иметь состояния если того пожелать, но тогда каждая точка входа в эту структуру, т.е. методы объекта, должны прежде сверяться с состоянием и затем только выполнять какие-то действия. Мы просто-напросто усложняем наши программы вводя состояния и сверки там, где в этом не было острой необходимости. Пол Грэм в одной из своих статей писал, что если возможно реализовать что-то в виде обычной функции с самыми обычными параметрами, то следует делать именно так, поскольку функция изолируется и следовательно отлаживается гораздо лучше метода объекта.

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

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

В результате в мире плодится огромное количество очень неэффективных приложений на Си++ и особенно Джава, в противовес которым можно найти или написать более компактные и быстрые аналоги на Си. Я не стреляю в Си++, потому что на нем можно писать хорошо, но это могут делать те программисты, которые пришли из мира Си.

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



***

Еще в 1998-ом году, когда я начал писать свою кустарную альтернативу STL, как вероятно когда-нибудь делали все Си++ программисты, я не смог бы изложить все свои претензии к ООП так пространно, но уже интуитивно осознавал где есть перебор с объектами. Позже моя кустарщина переросла в open-source проект под названием PTypes.

Тогда, понимая, что не все должно иметь ОО интерфейсы, я решил экспериментально описать алгебраические интерфейсы там, где нет наследования и полиморфизма. Замечу, что внутри все по-прежнему реализовано в классах, поскольку требовалось, например, перегрузить оператор + для строк, а вне класса в Си++ такое сделать невозможно. Строка — это атомарный (в смысле фундаментальный) тип, от которого вряд ли имеет смысл производить классы с перегруженными виртуальными методами, так же как и от простого int. Следовательно, интерфейс строки для пользователя может быть алгебраическим: такую простую вещь как length(s) никто не отменял и никто не сказал, что это обязательно должно записываться как s.length().

Точно так же я рассуждал и в отношении списков, и фактически удалось даже привести интерфейсы списков и строк в некоторое соответствие. Например length() был одинаково применим и ко всем типам списков. Делалось это для того, чтобы не загружать пользователя лишними понятиями. Length(), setlength() и некоторые другие методы универсальны насколько это возможно. Позже появился еще и variant, и тоже с алгебраическим интерфейсом.

Но были и классы потоков, включая файлы, сокеты и пайпы, описанные в лучших традициях ООП: виртуальные методы, наследование и прочее. Им это очень подходило.

Далее я даже умудрился описать шаблоны списков для произвольных базовых типов, сохраняя при этом алгебраические вызовы. Все бы ничего, только со временем я начал получать письма от пользователей с такими жалобами. Они в принципе не против самой идеи, но дело в том, что после усложнения библиотеки компиляторы стали путаться с большим количеством перегруженных функций (не методов!), описанных в шаблонах. Это были на самом-то деле баги в самих компиляторах (причем баги были разные, например у MSVC и GCC). Тут я понял, что такие фокусы с Си++ мало кто вытворяет, и поэтому ошибки в компиляторах остаются незамеченными. Я пытался давать баг-репорты создателям компиляторов, но ими никто не занимался наверное из-за слишком экзотического применения перегрузок обычных функций в купе с шаблонами.

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



***

Уверен, скоро это станет нормой — равноправное использование объектных и алгебраических вызовов. Должен произойти откат от религии ООП, поскольку программирование, в отличие от наук (а программирование это еще не наука), слишком коммерциализировано, и поэтому чувствительно к неэффективным решениям.

Рынок решает все, и он сегодня все чаще жалуется как на ненадежность ПО, так и на слишком большие затраты на его разработку. И рынку наплевать на наши с вами религиозные пристрастия и теоретические баталии. Если вы способны сегодня в одиночку или очень малыми командами создавать сложные системы, в которых ООП будет применяться в сдержанных дозах, то вы начнете очень скоро выигрывать и соответственно хорошо зарабатывать. Или вам нужен не заработок и красивые, компактные решения, а вместо этого — блуждание в дебрях объектной теологии?


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Теология ООП (часть II)
СообщениеДобавлено: 23 сен 2014, 18:12 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Продолжение статьи "Теология ООП"
Овик Меликян писал(а):
В этой статье я собираюсь немного попугать вас одной историей о том, как по вине стереотипного объектного мышления в мою программу вкралась весьма неприятная ошибка; далее продемонстрирую пример того, как целый класс можно запросто заменить одной-единственной функцией; и конечно же, как всегда, будет много брюзжания и критики.

Но не сердитесь, мы с вами всего лишь пытаемся найти "срединный путь" в проектировании программ и библиотек.



***

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

Но это так, вообще, о языке математики. Так чем в принципе запись

length(s)

оличается от

s.length()

? Вероятно, принципиальных отличий тут нет за исключением того, что первый способ записи выглядит эстетичнее для тех, кто проходил в школе алгебру и учил ее хорошо. Второй же способ — это некая новая нотация, которая, будучи полностью изолированной (или очищенной — как хотите) от традиционной, приводит к таким странным вещам, как i.add(j). А ведь ОО парадигма поначалу вроде бы пыталась нас убедить в том, что все идет именно к этому: всё есть объекты и методы в них, даже числа и операции над ними.

Но постойте, нотация i.add(j) не является ни эстетичной, ни краткой в сравнении с i+j. Конечно, программирование — это уже не математика (или еще не математика?), и оно имеет право вводить собственные абстракции. (Сами математики, к слову сказать, внеся некоторые дополнения и коррективы в уже имевшийся у них язык, получили Lisp, и весьма счастливы.) Вопрос лишь в том, чтобы вновь вводимые абстракции и нотации были достаточно кратки, выразительны, красивы, и что самое главное — заставляли бы думать человека таким же образом.

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

Впрочем, перейдем от предположений к конкретным примерам.



***

Существует множество объектных библиотек-оберток для базовых системных сервисов, в том числе и для интерфейсов многопоточного программирования. Обычно сами системные API навязывают нам объектный подход: они как правило создают дескриптор (handle), через который и предполагается манипуляция неким системным объектом, например файлом, графическим элементом или потоком исполнения. Все что остается сделать разработчику "обертки" — это просто инкапсулировать дескриптор внутри класса и затем переписать вызовы системного API в методы. Другими словами, буквально перевести все на язык ООП.

И я тоже рассуждал приблизительно так же, когда описывал классы для многопоточного программирования в PTypes. Класс thread не был исключением, кроме разве что одной тонкости, связанной с запуском потока: дело в том, что системный вызов pthread_create() (или BeginThread() в Windows) не может быть в конструкторе класса, как это часто делается для дескрипторных интерфейсов. Вместо этого, создание дескпритора и запуск асинхронной функции был перемещен в отдельный метод thread::start(). Но дело, собственно, не в этом. Объекты этого класса имеют опцию autofree, которая указывает должен ли объект самоуничтожиться по окончании выполнения асинхронной функции thread::execute().

Так вот, на старых Linux-системах, базирующихся на LinuxThreads, PTypes мог вылетать со странными ошибками порчи памяти (memory corruption). Отладка показала, что LinuxThreads почему-то иногда записывает дескриптор потока в области памяти, в которых когда-то существовал мой объект типа thread, но его в этом месте уже нет. В чем же дело?

Посмотрите на описание pthread_create(). Вы передаете этой функции ссылку на место в памяти, куда система должна записать новый дескриптор потока. По поводу запуска вашей асинхронной функции start_routine не дается никаких гарантий, но вы надеетесь, что она когда-нибудь будет вызвана.

Моя ошибка состояла в том, что асинхронная функция могла быть вызвана и закончена еще до того, как LinuxThreads успевал записать дескриптор в соответствующее поле моего класса. И в случае autofree потока это приводило к порче памяти, поскольку выходило так, что объект удалялся из памяти еще до того, как основной поток вернется из pthread_create(). Интересно, что кроме старых версий Linux ни одна другая система не делала этого в таком порядке, вероятно предвидя потенциальные ошибки вроде моей.

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

Впрочем, какая-то доля вины тут должна пасть и на разработчиков стандарта POSIX Threads. Размышляя потом над всем этим я также понял, что на самом деле не только pthread_create() не является конструктором, но еще хуже: поток исполнения вообще не является объектом, и следовательно архитекторам POSIX нечего было водить нас за нос своими дескрипторами. Другие функции, использующие дескриптор потока — pthread_join() и pthread_detach() — избыточны и могли быть изъяты из интерфейса (синхронизацию с завершением потока можно реализовать в приложении при помощи семафоров). Если бы создатели PThreads были бы истинными минималистами, то они оставили бы только pthread_create() и уже без того параметра, принимающего дескриптор.

В ядре Linux поддержка потоков долгое время ограничивалась одной-единственной функцией clone(), пока наконец начиная с версии 2.6 публике удалось убедить Линуса Торвальдса ввести полную поддержку POSIX-интерфейса в ядро. Я не в курсе какие при этом приводились доводы, но скорее всего не приводилось ничего путного кроме "POSIX это стандарт". Но стандартный интерфейс может быть таким же несовершенным, как и любой нестандартный, и наоборот. Впрочем, это отдельный разговор.

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



***

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

В той же самой библиотеке PTypes по пожеланиям пользователей пришлось ввести интерфейс для дейтаграммных сокетов. Недолго раздумывая, я описал два класса ipmessage и ipmsgserver по образу и подобию их поточных эквивалентов ipstream и ipstmserver. (Возможно, для вас непривычен стиль именования в PTypes, но использование этого стиля обосновано: его можно комбинировать с любым другим в одной программе. Если бы PTypes был написан, например, в венгерской нотации, то как минимум один класс программистов — юниксоиды старой школы — были бы жутко недовольны.) В конце концов это всего лишь обертка для системного интерфейса сокетов, и я ничего не пытался менять в этой идеологии.

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

Работа с дейтаграммными протоколами сводится к трем основным операциям: посылка пакета, привязка к порту и "слушание" его, получение пакета. Если взять только операцию посылки, то окажется, что для ее осуществления достаточно одной-единственной функции. По сути посылка, если можно так сказать, не имеет состояния, и поэтому нет необходимости описывать класс и размножать объекты; в нашем случае — это класс ipmessage, который таким образом оказывается избыточным. Что касается привязки и получения, то здесь ситуация иная: такой сокет имеет состояние, поскольку система параллельно с вашим приложением должна слушать определенный порт и буферизировать поступающие пакеты. Поэтому, такой класс как ipmsgserver на самом деле нужен, правда даже в нем в принципе есть кое-что лишнее: это методы посылки.

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



***


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 23 сен 2014, 18:32 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Овик Меликян писал(а):
Многие программисты рассматривают ООП, кроме всего прочего, как средство описания небольших модулей в рамках приложения. Любой язык программирования, имеющий даже самое неполное ОО-расширение, позволяет хорошо изолировать миниатюрные интерфейсы в общем пространстве имен программы. Такой подход помогает нам мысленно изолировать небольшую функциональную единицу и заняться ее проектированием в отрыве от всего приложения.

И тут мы временами можем сталкиваться с трудностями, связанными с семантической принадлежностью того или иного метода данному классу. Например, принадлежность метода paint() некой абстрактной визуальной компоненте почти не вызывает сомнения. Но как быть с методом, который вставляет данную компоненту в список дочерних элементов родительской компоненты? Должен ли это быть метод add_child() в родительском интерфейсе, или set_parent() в дочернем (или может и то, и другое)? Я бы предпочел первый вариант, но в GUI-интерфейсах чаще встречается как раз таки второй, потому что дочерний объект должен еще и удалить самого себя из списка предыдущего "родителя".

А что если попытаться разрешить проблему выставив этот метод за пределы класса? Представьте себе, вы имеете глобальную функцию set_affinity(parent, child), которая, возможно, вызывает защищенные виртуальные методы оповещения как в родительском классе, так и в дочернем. Не вижу в этом ничего страшного, и даже более того, мне будет легче запомнить тот факт, что set_affinity() никому не принадлежит, чем пытаться вспомнить в каком интерфейсе его следует искать: в родительском или дочернем. И все потому, что set_affinity() по сути никому не принадлежит и является "нейтральным" действием, в котором принимают участие больше одного объекта.

Другой пример: обычно базовые классы, реализующие подсчет ссылок, объявляют по крайней мере два метода: acquire() и release() внутри этого абстрактного интерфейса, которые увеличивают или, соответственно, уменьшают счетчик ссылок. Но возникает вопрос: насколько метод release() принадлежит данному объекту? Ведь в результате вызова этого метода объект может быть уничтожен, следовательно он является чем-то нейтральным скорее чем является "собственностью" объекта. В PTypes оба этих метода объявлены глобальными (правда в случае acquire() — только ради симметрии с release()).

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

Кстати говоря, вовсе необязательно, чтобы такие нейтральные функции были объявлены буквально глобальными: вы вполне можете найти для них место в каком-то другом классе, лишь бы это выглядело логично. Например, тот же set_affinity() может оказаться в объекте окна (ведь визуальные компоненты так или иначе "живут" в окне), а пара acquire()/release() — в каком-нибудь class factory, которые нынче очень модны.

Всё это вам может и не понравиться, но лучше подумайте о том, что естественность интерфейса важнее привычек. А привычки ОО методологии настолько липучи, что, как видите, мы временами можем закрывать глаза на противоестественность в нашем коде.



***

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

Но есть одна вещь, с которой вы не можете не согласиться: интерфейсы стоят того, чтобы им уделялось много времени на обдумывание. Реализация — это совсем другая стихия, которая является сутью нашего с вами ремесла, но интерфейсы библиотек — это языки, на которых мы предлагаем думать и писать другим программистам. Я никогда не жалею своего времени, чтобы оптимизировать интерфейс, сделать его более компактным и естественным, если даже ради этого придется пойти наперекор собственным объектно-ориентированным привычкам.

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


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Теология ООП
СообщениеДобавлено: 23 сен 2014, 22:39 
Не в сети

Сообщения: 108
Овик Меликян писал(а):
В последние годы появились весьма неочевидные прогнозы


Стоило писать столько много буков только для того, чтобы указать на проблемы использования инструмента не по назначению? ООП - вполне кошерный подход для решения определенного круга задач (скажем честно - большого круга). Какой смысл очернять его ("отстой") только потому, что кто-то использует ООП неправильно?


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 24 сен 2014, 00:19 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
А мне понравилось. :) И — мы не очерняем, а пытаемся разобраться.

Такое название тема получила из названия статьи, указанной в первом посте.

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

Мне всё больше нравится мысль, что нет постепенного и монотонного улучшения чего-либо. Это касается и ОС, и языков программирования, и любых других программных технологий. Любое [в чём-то] улучшение — в тот же момент и [в чём-то] ухудшение: усложнение, подводные камни, потери [времени] при переходе на новую версию/билд [библиотеки, среды разработки, API ОС], при изменении [улучшении] принятых соглашений, интерфейсов и т.п.

Вывод: 1) ООП-средства в некоторых случаях полезны; 2) ими можно пользоваться и без поддержки ООП в языке — в той или иной степени; 3) ООП-средства решая одни проблемы могут порождать другие. Даже если не принимать во внимание их неграмотное применение.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 23 окт 2014, 21:06 
Не в сети

Сообщения: 53
Откуда: Россия, Самара
Zorko писал(а):
Вывод: 1) ООП-средства в некоторых случаях полезны; 2) ими можно пользоваться и без поддержки ООП в языке — в той или иной степени; 3) ООП-средства решая одни проблемы могут порождать другие. Даже если не принимать во внимание их неграмотное применение.


В принципе логично, что мясо проще есть, когда режешь его ножом и накалываешь на вилку. А когда ешь, суп используешь ложку, а не половник или вилку.

Вот только, программирование довольно узкая дисциплина. Как был гото так остался, указатели иже с ним.

Всё, что выше абстракции, для программиста. Довольно успешные.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 26 окт 2014, 20:10 
Не в сети

Сообщения: 53
Откуда: Россия, Самара
В сущности:

Процедурное программирование
TYPE
Штуковина: ТШтуковина;

ШтуковинаЧеготоСделать(Штуковина);

ООП
TYPE
Штуковина: ТШтуковина;

Штуковина.ЧеготоСделать();


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 43 ]  На страницу Пред.  1, 2, 3, 4, 5  След.

Часовой пояс: UTC + 2 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
© VEDAsoft Oberon Club