Как стать автором
Обновить

На самом деле, ООП — это не так уж плохо

Уровень сложностиСредний
Время на прочтение10 мин
Количество просмотров13K
Всего голосов 33: ↑26 и ↓7+34
Комментарии158

Комментарии 158

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

на что только не идут забугорные писатели чтобы загнобить функциональное программирование. У ООП значит успех есть, а у функционального программирования что? Успеха, получается, как бы нет.

У всего есть своя ниша. Разные подходы по разному полезны в разных ситуациях. Иногда можно добиться цели примерно с одинаковыми трудозатратами, но разными подходами. Тут уже, как художнику и его команде удобнее и комфортнее. Все направления и подходы программирования нужны. А холивары нет ;)

Разные подходы по разному полезны в разных ситуациях.

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

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

Затащили для примера полумёртвый Хаскель и что-то решили с его помощью доказать. Да, известно этот язык - вынос мозга для тех кто не умеет на нем писать - ну и для тех кто умеет неслабый напряг. Но не столько из-за ФП сколько из-за увлеченностью теорией типов.

+1. Я могу прекрасно читать код многих языков, которые не знаю.. но от синтаксиса Haskell мозг вскипает.

Лучше бы Scala использовали в примере. В ней как раз отлично уживается ООП и ФП.

НЛО прилетело и опубликовало эту надпись здесь

полумёртвый Хаскель

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

А в академической среде он наверное уже будет всегда и переживет всё и всех, в том или ином виде (либо сам Haskell, либо какой ни будь другой язык, который появится как его эволюционное развитие)

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

Думаю, сообществу пользователей функционального программирования пойдёт на пользу, если они, наконец постараются понять ООП, и поймут, что строгая типизация — далеко не панацея.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

И ирония понятна, и статья известна. Но это ни замечание, ни статью не делают истинными.

Впрочем, я действительно, возможно, зря написал "строгая". В ООП любая типизация является инородным вкраплением. Грубо говоря, когда возникли рассуждения типа "ах, у вас в Smalltalk-е нету типов? да это же как BASIC!" возник тряпочный ответ "типизация есть, только она динамическая".

Нет там типизации. Там есть сообщения и объекты. И любому объекту можно послать любое сообщение. И он его должен каким-то образом обработать: либо "штатно" — выдать объект в ответ, либо выкинуть исключение. Всё.

НЛО прилетело и опубликовало эту надпись здесь

Не хотите — не тратьте, кто ж вас заставляет-то :)

Или вы всерьёз считаете, что без типизации невозможно отладить/оптимизировать программный код?

И ещё: отсутствие "типизации" (или чего-то подобного) в ООП означает, что её невозможно реализовать (при желании). Примеры были.

НЛО прилетело и опубликовало эту надпись здесь

Если это так, то можно такие примеры?

тут вот стало опять интересно: а классы они разве не типы?

НЛО прилетело и опубликовало эту надпись здесь

А что значит "класс проверяется"? А тип? ;)

НЛО прилетело и опубликовало эту надпись здесь

Так, проверяется-то не класс, и не тип. Я там смайлик не просто поставил. Простите :)

НЛО прилетело и опубликовало эту надпись здесь

В C++ вот во время тайпчекинга (который происходит в том числе во время компиляции) проверяется,

Так плюсовые классы это типы? А плейн С-шные структуры, тайпдефы (псевдоним полного типа это тип?), которые, кстати, никуда не делись и в С++?

Я про смалтолк кроме названия особо ничего не знаю, C#, Java пишу еще.

То же самое, только более общо, не обязательно с классами.

"более общо" можно понять как поверхостно, что вы имеете ввиду?

НЛО прилетело и опубликовало эту надпись здесь

есть много разных теорий типов

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

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

Классы — не типы.

Назначение классов — создавать объекты ("экземпляры соответствующего класса").

Назначение типов (данных) — ограничивать программиста в выполнении операций над значениями этого типа.

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

Назначение типов (данных) — ограничивать программиста в выполнении операций над значениями этого типа.

честно говоря я с очень большим недоверием отношусь к стремлению кого-то ограничивать, для меня это звучит не конструктивно.

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

честно говоря я с очень большим недоверием отношусь к стремлению кого-то ограничивать

А как понимать ваши слова про проверку (соответствия) типов?

Что происходит, если type checker обнаруживает несоответствие типов? Он не позволяет такую программу скомпилировать — это ограничивает возможность программиста запустить (неправильную) программу. Именно в этом и заключается смысл проверки типов — не дать выполнить неправильную операцию над данными, так как это может привести к непредсказуемым (в том числе разрушительным) последствиям. Нет?

все верно компилятор осуществляет проверку типов, насколько я это понимаю. И я так понимаю что вам этого недостаточно и вы хотите заменить компилятор на какой-то крутой  type checker который будет так ограничивать что кушать не захочется.

Я же наблюдаю что даже эти ограничения проверки типов иногда приходится обходить.

Вы троллите?

то есть если вам нечего ответить это значит вас затролили?

Я что-то написал не по теме?

Просто уровень вопроса не соответствует ожидаемому.

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

И то, что я изложил (включая термин "type checker") — абсолютно стандартное знание. По идее, это должен знать каждый студент соответствующей специальности, начиная (как минимум) где-то со 2-го, максимум 3-го курса.

Под "type checker"-ом понимается компонент, который осуществляет проверку соответствия типов в программе. Он может быть частью компилятора или работать отдельно.

а разве с этим кто-то спорит? Я предположил, что вы от него хотите через чур много, от этого type checker-а, не надо увиливать.

ШТА?!?

Вы меня ни с кем не путаете? :D

Если что, я как раз тот странноватый чувак, который предлагает типы вообще из языков убрать и сделать их необязательной (хотя и весьма полезной!) опцией ;)

Ещё раз: в ответе на ваш вопрос по поводу статической типизации я изложил абсолютно общеизвестную, каноническую версию.

Чего же такого особенного, по вашему мнению, я хочу от type checker-а?

Чего же такого особенного, по вашему мнению, я хочу от type checker-а?

у меня получается исходя из ваших предыдущих высказываний:

Назначение типов (данных) — ограничивать программиста в выполнении операций над значениями этого типа.

Что вы хотите что бы он (лучше) ограничивал программиста в выполнении операций над значениями типа. Как бы получается что вы не удволетворены как это сейчас происходит в компиляторах, но я не претендую на абсолютную логику, просто мне так показалось, мне показалось что вы пропустили это (лучше) в скобках, оно у вас как бы подразумевается. Мне собственно и интересно теперь правильно я вас понял или нет именно в этом смысле!

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

Назначение классов — создавать объекты ("экземпляры соответствующего класса").
Назначение типов (данных) — ограничивать программиста в выполнении операций над значениями этого типа.

Назначение у них одинаковое, класс это пользовательский тип данных. Они изначально именно для этого и создавались. Создавать экземпляры разных классов, не имея контроля типов, бессмысленно и никому не нужно. Зачем создавать экземпляр класса User, если его можно передать в метод, который принимает тип Date?

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

Вокруг — всё гвозди …если ты — молоток :D

Разбирать не буду, тут буквально каждое предложение уникально. Вам бы Церковь Строго-Cтатической Типизации открыть ;)

Разбирать не буду

Вы слишком часто уходите от ответа.

Вам бы Церковь Строго-Cтатической Типизации открыть

Я не являюсь адептом типизации. Я совершенно не против поменять точку зрения при наличии аргументов, только вы раз за разом отказываетесь их излагать.

Вы слишком часто уходите от ответа.

Вы задавали вопросы? В вашем сообщении выше их не заметил.

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

Но ещё раз замечу, что я-то собственно, ничего такого особого, что должно было бы у вас, с вашим опытом и знаниями, вызывать вопросы и не предлагал. В основном вы высказывали разные предположения о непреодолимых трудностях применения на практике "нормального" (или как мы там его называли?) ООП. Я лишь сообщал вам, что такое существует и вполне успешно используется. В чём вы можете самостоятельно убедиться, погуглив по ключевым словам Smalltalk, Pharo, VisualWorks, GemStone/S… — возможно, надо было раньше их озвучить, но всё как-то явного повода не возникало… 

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

Вы задавали вопросы? В вашем сообщении выше их не заметил.

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

В основном вы высказывали разные предположения о непреодолимых трудностях применения на практике "нормального" ООП.

Если под "нормального" вы имеете в виду Smalltalk, то я не говорил о непреодолимых трудностях. Я в курсе, что он существует и используется. Я сказал, что отсутствие типизации создает трудности. Они преодолимые, но людям обычно это неудобно, поэтому они добавляют типизацию там, где возможно.

Только желательно в форме вопросов

Ну ок. По каким причинам вы считаете, что у классов и типов разное предназначение, если класс это пользовательский тип, и они изначально именно для задания пользовательских типов и создавались?
Приведите пожалуйста ссылки на источники, в которых поддерживается ваша точка зрения. (<- обратите внимание, это не вопрос, но на это высказывание можно ответить)

Я сказал, что отсутствие типизации создает трудности. Они преодолимые, но людям обычно это неудобно, поэтому они добавляют типизацию там, где возможно.

Во-первых, как с блеском иллюстрирует ваш же пример, это неудобно людям, которые "haven't understood the concepts of smalltalk enough". А вот у тех, кто понял, таких трудностей почему-то не возникает. О чём, например, свидетельствует очень низкий уровень интереса к попыткам привнести типы в Smalltalk (хоть в виде "бибилотеки", хоть путём изменения языка — как в Strongtalk-е).

Во-вторых, я никогда и не утверждал, что типы вообще бесполезны. Как раз наоборот. Моя же мысль — и я неоднократно излагал — заключается, в том, что их желательно не "встраивать" в язык, а сделать отдельной "библиотекой", подключаемой и используемой по желанию.

По каким причинам вы считаете, что у классов и типов разное предназначение, если класс это пользовательский тип

Всё же вы смогли изумить меня своими логическими построениями :) Вы действительно считаете, что на вопрос

а классы они разве не типы?

допустимо отвечать "…если класс это пользовательский тип"? O.o

Если же отбросить эту вводящую нас в бесконечную рекурсию посылку, то на вопрос

По каким причинам вы считаете, что у классов и типов разное предназначение,

я уже дал ответ, обозначив назначение классов и типов.
Как я понимаю, что-то в этом вас не устраивает? Что именно?

Если это именно предназначение классов, поясню сразу.
Есть ОО-языки, в которых явно есть классы, но явно нет типов. Пример вы уже знаете — Smalltalk.

Опровергнуть это утверждение очень легко — найти в грамматике языка слово "тип."

Сразу обращу внимание: именно в грамматике, а не в разговорах о том, что Smalltalk — это "динамически типизированный" язык. Утверждение про типизацию легко опровергается в соответствии с предложенным вами же критерием

Если у класса нет метода "bark", то вы не сможете сделать с ним такую операцию.

Создайте класс YouCanStillBarkEvenIfYouAreNotADog, в него методе #doesNotUnderstand: с таким исходным кодом

YouCanStillBarkEvenIfYouAreNotADog >> doesNotUnderstand: aMessage

	aMessage selector = #bark ifTrue: [
		Transcript
			cr;
			show: 'bark' ].

и убедитесь, что

YouCanStillBarkEvenIfYouAreNotADog new bark.

Выполнится и напечатает то, что нужно.

Есть в классе YouCanStillBarkEvenIfYouAreNotADog метод #bark?
Можем послать экземпляру этого класса сообщение #bark?
Где тут контроль типов?

В Smalltalk-е классы нужны именно для того, чтобы создавать новые объекты — как класс YouCanStillBarkEvenIfYouAreNotADog позволяет создать (свой) экземпляр через посылку ему сообщения #new.

То, что классы в Smalltalk нужны именно для создания объектов, подтверждается, например, языком Self. Если вы почитаете про этот язык, то увидите что, по сути, это Smalltalk, но без классов. И какую ответственность пришлось возложить на объекты вследствие отсустсвия классов? Не создание своих клонов, случайно?

это неудобно людям, которые "haven't understood the concepts of smalltalk enough"

Вариант "have understood the concepts of smalltalk enough and do not like them" дает такой же результат. Но вы без всяких аргументов отказываетесь его рассматривать. Это говорит о том, что ваша логика неправильная.

О чём, например, свидетельствует очень низкий уровень интереса к попыткам привнести типы в Smalltalk

В изначально нетипизированном Smalltalk к типизации низкий уровень интереса, а в изначально нетипизированных JavaScript и PHP высокий. Уже два примера против одного.
О чем это свидетельствует? Например, о том, что Smalltalk интересен малому количеству людей, и те, кому нужна типизация, используют другие языки. Это подтверждается большей распространенностью языков с типизацией.
И даже среди использующих Smalltalk нашлись люди, которые захотели сделать Strongtalk.

Вы действительно считаете, что на вопрос "а классы они разве не типы?" допустимо отвечать "..."?

Нет. Поэтому я и не отвечал на этот вопрос таким образом. Я вообще на него не отвечал. Я отвечал на ваше утверждение про назначение типов и классов.

я уже дал ответ, обозначив назначение классов и типов.
Как я понимаю, что-то в этом вас не устраивает? Что именно?

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

Утверждение про типизацию легко опровергается в соответствии с предложенным вами же критерием
"Назначение классов — ограничивать программиста в выполнении операций над экземплярами этого класса. Если у класса нет метода "bark", то вы не сможете сделать с ним такую операцию."
[Добавим обработчик для сообщения bark]

Ну так если вы добавили обработчик, значит вы сами решили не ограничивать, не так ли?
Давайте теперь уберем код вашего метода. Будет ли ваш класс все еще выполнять выполнять операцию bark? Если не будет, значит вы ограничили вызывающий код в выполнении операций над экземплярами этого класса, не так ли?

Где тут контроль типов?

Мое утверждение про классы было "Назначение классов — ограничивать программиста в выполнении операций над экземплярами этого класса". Там нет выражения "контроль типов".
Какие операции вы разрешили, такие он и будет делать. Как вы их разрешили, в рамках данной дискуссии совершенно неважно. Например, в PHP есть магический метод __call, он работает аналогично вашему примеру.

Не создание своих клонов, случайно?

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

Мое утверждение про классы было "Назначение классов — ограничивать программиста в выполнении операций над экземплярами этого класса". Там нет выражения "контроль типов".

vs.

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

У вас по существу есть что сказать?

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

Можем послать экземпляру этого класса сообщение #bark?
Где тут контроль типов?

В наборе операций, которые можно сделать с объектом. Что вы можете послать и обработать, а что будет выдавать ошибку. По вашим же словам это является частью контроля типов.

В Smalltalk-е классы нужны именно для того, чтобы создавать новые объекты

Метод new можно прекрасно поместить вне класса, классы для этого не нужны. Можно сделать один класс Object с произвольным набором полей, как это сделано в начальных версиях JavaScript и PHP. Создавать новые объекты можно и с ним. Раз есть разные классы, значит они зачем-то нужны.

У вас по существу есть что сказать?

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

Я вообще ничего не говорил про лучше или хуже.

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

Но тут вы опять провоцируете:

Но в типизированных ОО-языках за неимением лучше альтернативы классы нагрузили обязанностями типов.

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

Я думаю, что и красота, и уродство — они в глазах смотрящего. Или иначе, если человек хочет почувствовать себя оскорблённым или обиженным, он найдёт способ этого добиться.

Поясню, что я имел ввиду.

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

И среди этих двух понятий нет понятия "тип данных" — оно просто тут не нужно.

Понятие "класс" в ОО-языке — тоже не является обязательным. Но обязательным является наличие какой-то способа порождения новых объектов. Классы тут становятся одной из альтернатив. Собственно, я знаю две:

  • либо все объекты могут порождать другие объекты — такой подход привёл к идее клонирования объектов (т.н. прототипирование)

  • либо мы вводим некие специальные объекты, которые умеют создавать другие объекты.

Вот, второй подход нас приводит к понятию классов: те объекты, которые неким образом умеют создавать объекты назвали классами.

Теперь, если мы хотим сделать ОО-язык, в котором сразу (не как некоторая "библиотека", а именно как часть языка) присутствует статическая типизация, то нам надо как-то ввести в язык понятие типа. Как мы можем это сделать?

Есть два варианта:

  • либо мы вводим тип данных в язык как новую сущность,

  • либо мы привязываем тип к уже имеющейся в языке сущности.

Первая альтернатива, возможно, имеет какое-то право на существование (прямо сейчас не могу вспомнить, но смутно кажется, что я где-то такое видел… а может и нет — не важно), но второй вариант выглядит явно более привлекательным, если у нас уже есть классы.

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

И именно в этом смысле следует понимать слова "за неимением лучше альтернативы".

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

Вот так это должно выглядеть со стороны.

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

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

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

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

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

Меня например никак ни трогает что

А лагеря "ООП-шников" и "типизаторов", к сожалению пока только расходятся

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

Но по крайней мере вы ответили на свое же обвинение ранее, что вас кто-то тролит.

Удачи вам и мудрости отделять содержательную часть от всего остального.

Я, пожалуй, даже не буду комментировать. Замечу только, что совет про GoF — просто бесценен! :D Всего доброго.

(Вторая попытка ответить. Первую, как я только что с удивлением обнаружил, Хабр благополучно куда-то выбросил…)

Вероятно, у вас там пропущена частица «не». Если это так, то можно такие примеры?

Да пропущена. Ключевые слова: type inference, за которыми следует нужной степени уточнение, например in dynamic languages или название конкретного интересующего вас языка.

В случае, если это Smalltalk, то можно начать с RoelTyper, Strongtalk.

Я всерьёз считаю, что это ложная дихотомия

Не понял, где вы увидели ложную дихотомию?

/…/  поэтому в вашей философии заставляет объективная реальность.

У вас тут тоже что-то пропущено?

Ну вообще ваш первый комментарий в этой ветке начался с формулировок «пойдёт на пользу» и «поймут, что [...] не панацея», которые говорят об этом как об объективном факте,

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

Я не собирался и не собираюсь разжигать какие-либо холивары на тему типизации и/или ООП vs ФП. И "продавать" вам или кому бы то ни было ООП в мои планы не входило.

Я всего лишь обратил внимание на тот факт (и это именно факт), что очень часто поклонники ФП не совсем адекватно воспринимают суть ООП. Этим страдают далеко не только они, но в данном контексте речь именно о них. И данная статья, как и ваши комментарии, является тому прекрасным примером.

И это не обвинение. В том, что поклонники одного подхода не очень хорошо знают другой, нет ничего удивительного или плохого. И даже в том, что поклонники ФП регулярно "нападают" на ООП (обратное — по моему личному (sic!) опыту — происходит гораздо реже, что, кстати, вполне объяснимо) я не вижу ничего плохого. В конце концов "всем известно" (хотя это и не так уж подтверждается опытом), что "в споре рождается истина".

И в ООП (особенно в его настоящем виде, а не в том изуровдованном, который на сегодняшний день стал мейнстримом), и в ФП заложено очень много крутых идей и решений. При этом ООП вобрало в себя массу идей из ФП, а затем ФП взяло много из ООП. Было бы здорово, если бы вместо расходования сил и времени на битвы вокруг возникших вследствие банального недопонимания проблем, этот процесс взаимного обогащения продолжился, и в один прекрасный день мы бы получили язык, вобравший в себя лучшие качества Smalltalk-а и Haskell, при этом лишённый их же недостатков.

НЛО прилетело и опубликовало эту надпись здесь

Я за всю свою практику не видел ни одного проекта, ни в стартапах, ни в фаангах, ни от относительно свежих выпускников профильных вузов, ни от чуваков с 30-летним стажем, нигде, короче, не видел проекта, сделанного по канонам ООП, в котором при этом можно было бы разобраться

я бы вам посоветовал с DirectX-ом что то попробовать поделать, но действительно, найти правильно написанный код в свободном доступе наверно не возможно, я последний раз видел больше 20-ти лет назад, но и он был проприетарный. Там было много описания чего этот код может делать и раз в 10 меньше кода который все это делал. Такой критерий я даже вынес из того опыта: если количество кода в текстовом виде намного меньше чем описание функциональности реализованной в нем, код должен быть хорошим.

Тогда я вообще не понял, в чём смысл отсылки к этому: ну, да, можно прикрутить к языку там как-то сбоку какие-то новые фичи, которых там изначально не было (и получится, конечно, не так хорошо, как если язык изначально разрабатывать с учётом этих фич

В 1963-м (если не ошибаюсь) году был создан специализированный язык Simula (сейчас его обычно называют Simula I), предназначенный для создания дискретных имитационных систем. Simula являлся расширением ALGOL-60 — в язык были добавлены языковые конструкции, позволявшие более удобно создавать модели дискретных систем.

В 1967-м году появился Simula-67. Это было новый язык общего назначения, в основе которого лежали концепции объектов, классов, сопрограмм. На этом языке те же средства моделирования уже были не частью языка, а библиотекой.

В начале 2000-х некий Avi Bryant занимался разработкой интересной идеи по созданию web-сервиса, обеспечивающего работу с "дружелюбной к рефакторингу" базы данных (не буду вдаваться в подробности — суть не в этом). Разработка велась на Ruby. В какой-то момент, Avi решил, что ему очень помогут континуации (почему и как — опять же, не важно). Он обратился к сообществу Ruby-стов, с просьбой добавить поддержку этой конструкции в язык. На что получил отказ, так как это существенно усложняло язык и требовало серьёзных усилий.

Тогда Avi взял Squeak ("диалект" Smalltalk-а) и просто реализовал континуации там. Для этого не пришлось ничего менять в языке — просто написать один (небольшой) класс, реализующий данную концепцию. Не помню точно, сколько времени это заняло, но что-то порядка дней.

Понимаете, о чём я?

НЛО прилетело и опубликовало эту надпись здесь

Программистам нужно очень много всего — не только типизация. Если добавлять всё такие "фишки" в язык, получим монстра похуже C++. Но есть другой путь: сделать простой, но мощный язык, позволяющий реализовать те же "фишки" в виде внешних модулей и подключать их по мере надобности.

НЛО прилетело и опубликовало эту надпись здесь

Это какое-то непреодолимое свойство системы типов?

"Система типов" же тоже написана на каком-то языке программирования, не так ли?

НЛО прилетело и опубликовало эту надпись здесь

Система типов — это и есть ваш язык.

Зачем было писать столько текста, котороый базируется на такой шаткой посылке? Тем более, что всё здесь сводится к "заколдованному кругу": язык без типов невозможен, потому что… язык без типов не возможен!

Но вы же не берёте на себя смелость утверждать, что не существует языков программирования, где нет типов?

НЛО прилетело и опубликовало эту надпись здесь

Утверждение «Или вы всерьёз считаете, что без типизации невозможно отладить/оптимизировать программный код?» — ложная альтернатива исходному утверждению о том, что типизация помогает писать код.

У вас, видимо, какое-то собственное, отличное от общепринятого понимание термина "ложная дихотомия".

Вместе с тем, вы тут же подменяете собственные утверждения:

исходному утверждению о том, что типизация помогает писать код

совсем не эквивалентно

я всерьёз считаю, что [сильная] типизация помогает отлаживать и оптимизировать код (вплоть до того, что подавляющая часть багов ловится на этапе написания кода, и отлаживать становится нечего).

и тем более

я не хочу тратить время ни на обработку внутри объекта «преобразователь строки в число» сообщения «преобразуй жсон в число», ни на попытки отправить такое сообщение снаружи этого объекта.

Последнее (первое хронологически) просто настолько бессмысленно, что я даже не захотел тратить время на его разбор.

Только без обид — его бессмысленность продиктована тем самым непониманием сути ООП, которое, как я понял из ваших же слов, и привело к ФП. Ваше же непонимание является стандартным следствием массового непонимания, которое в свою очередь приводит к такому:

Я за всю свою практику не видел ни одного проекта, ни в стартапах, ни в фаангах, ни от относительно свежих выпускников профильных вузов, ни от чуваков с 30-летним стажем, нигде, короче, не видел проекта, сделанного по канонам ООП, в котором при этом можно было бы разобраться, не было бы ненужного оверинжиниринга и паттернов ради паттернов с десятью слоями абстракций, и так далее. При этом в ФП-проектах всё было сильно проще, понятнее и приятнее, хотя intrinsic-сложность ФП-проектов была куда выше таковой для ООП (ну, какой-нибудь компилятор в ФП и какой-нибудь более скучный перекладыватель жсонов в ООП). И если, приходя в ФП-проект, я мог продуктивно контрибьютить со второго дня, то в ООП обычно куча времени уходит на разбирательство в гроздьях архитектурных абстракций архитектурных астронавтов, которые при всём этом направления развития и расширения кода не угадали совсем, поэтому все эти гроздья разлагаются и воняют совсем не вином.

Я прекрасно понимаю, о чём вы тут пишете, и полностью согласен с тем, что количество говнокода в ООП-проектах зашкаливает. Столкнувшись с этим, вы сделали вывод, что проблема в ООП. И да — проблема в ООП, только не в том, который был придуман изначально, а в том искажённом ООП, который массово насаждают в книгах, ВУЗах, на практике.

Лишена ли ФП аналогичных проблем? Не факт. В данной статье, кстати, это тоже показано. И даже не занимаясь ФП, я наслышан о разных решениях, казалось бы элементарных задач, по сравнению описанные вами "гроздья абстракций" кажутся просто невинным детским амбре. Разумеется, просить меня привести примеры — бессмысленно, вы наверняка про них в курсе получше меня. Или я здесь ошибаюсь? Но, если что, у меня в загашнике всегда есть вопросы про монады ;)

В прочем, это отдельная тема, в данный момент не особо мне интересная. Просто я, столкнувшись с ООП на том же C++, имел неосторожность не переключиться на другую "парадигму", а попытаться разобраться — что же не так с ООП? И оказалось, что проблема, как обычно, не в ООП, а в людях. На этом основании подозреваю, что если жгучее желание поклонников ФП получить всеобщее признание и сделать этот подход более популярным, сбудется, то через пару-тройку десятков лет ФП ждёт примерно та же участь "неоправдавшей надежды парадигмы". И на мой взгляд, единственное, что может помешать этому — гораздо более высокая сложность ФП по сравнению с ООП, что просто не позволит ФП стать такой же массовой.

НЛО прилетело и опубликовало эту надпись здесь

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

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

НЛО прилетело и опубликовало эту надпись здесь

Вам не кажется, что моё высказывание «помогает писать код» является общим случаем «помогает отлжаивать и оптимизировать код» (моё высказывание, которое я писал изначально),

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

не привнося существенных изменений в тезис о том, что ваше утверждение о том, что без типизации невозможно отладить/оптимизировать программный код, является ложной альтернативой что исходному озвученному мной на этой странице тезису «помогает отлаживать и оптимизировать код», что его сокращённой форме «помогает писать код»,

Вы согласны с тем, что у любого (технического) решения есть "сильные" и "слабые" стороны? Утверждение довольно сильное, поэтому уточняю. Такое утверждение часто приходится слышать (в разных формах), и мне не приходилось встречаться с опровергающими его примерами — поэтому я принимаю, что (с высокой долей вероятности) оно является истинным.

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

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

Кстати, про "отлаживать и оптимизировать", если не ошибаюсь, разговор завёл именно я. Это стало моей попыткой разобраться в семантике ваших слов про

не хочу тратить время ни на обработку внутри объекта «преобразователь строки в число» сообщения «преобразуй жсон в число», ни на попытки отправить такое сообщение снаружи этого объекта

Чтобы не "душнить" объяснением про то, что (по моему опыту) при использовании "динамических" языков программирования (типа Smalltalk) процент возникновения подобных проблем ничтожно мал, а при использовании TDD сводится практически к нулю. Отлаживаться, конечно приходится, но совсем по другим поводам.

Отвечал, не дочитав…

поэтому с моим исходным утверждением о «помогает отлаживать и оптимизировать код» это утверждение о моём нежелании тратить время ни на обработку внутри объекта «преобразователь строки в число» сообщения «преобразуй жсон в число», ни на попытки отправить такое сообщение снаружи этого объекта вообще не обязано быть связано, не согласны?

…но этот момент объяснил.

почему бессмысленно? Вы же сами написали на этой странице, что «любому объекту можно послать любое сообщение. И он его должен каким-то образом обработать». Если я знаю, что какой-то объект /…/ имеет строго ограниченный набор операций /…/, то в чём бессмысленность?

Самый простой частный пример: proxy-объекты — например, mock-и. У них (почти) нет своего поведения, их основная задача — "изображать" какой-то другой объект. Реализация такого в криво, но всё же статически типизированной Java — задача далеко нетривиальная. На динамическом Smalltalk-е — это не особо трудная задачка для студентов.

Но, конечно, если бы всё ограничивалось только этим, игра бы не стоила свеч. В ООП была изначально заложена идея создания динамических систем. Любой объект, с которым вы взаимодействуете, может в любой момент изменить своё поведение или быть заменён на другой объект. И для внесения изменений в такую систему не требуется полная остановка и перезапуск. Да, это сложнее, чем статическая система. Но и возможностей такой подход даёт несоизмеримо больше.

А бессмысленность заключается в том, о чём я написал выше: в реальной практике описанные вами проблемы просто не возникают! Судя по всему, у вас недостаточный опыт разработки в таких системах, а озвученные вами проблемы являются лишь фантазией, не имеющей отношения к реальности.

НЛО прилетело и опубликовало эту надпись здесь

Тут в предлагаемой мной парадигме тоже есть варианты

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

зависящие от того, зачем конкретно что-то изображать

Например, чтобы работать с удалёнными объектами так же, как с локальными.

Кстати, иронично, что приводимый вами пример — он для тестов, «автогенерация» которых (как иначе ваши абстрактные созданные динамически в отрыве от конкретного тесткейса моки будут работать?)

Вы опять очень туманно изъясняетесь. Динамические моки не "автогенерируются". Идея моков заключается в том, чтобы прямо в "тесте" (мне более подходящим кажется термин "выполняемая спецификация") описать ожидаемое поведение "коллаборантов".

не нужна в T(ype)DD.

TypeDD исключает необходимость обеспечивать соответствие программы требованиям? Или там все формулируются в самом общем виде и формулировки типа "в случае, если…" исключены? Или же я всё пропустил и соответствие статически типизированной программы требованиям доказывается автоматически?

НЛО прилетело и опубликовало эту надпись здесь

«правильные вещи должно быть делать просто, неправильные вещи должно быть делать сложно».

А решает, что правильно, что нет… конечно, же type checker! Или — точнее — какие-то дяди, которые познали всё!

Но если эти дяди познали всё, то почему же существует столько теорий типов? Хотя, я догадываюсь, что вы ответите :)

НЛО прилетело и опубликовало эту надпись здесь

С удалёнными объектами (функциями)

Давайте всё-таки оставаться в рамках одной парадигмы, а не перепрыгивать в произвольно с одной на другую. А то с вашими скачками получается такая логика: "<что-то> не соответствует этике/нормам ФП, следовательно это плохо". Не забывайте, мы не принимаем за аксиому подходы ФП. И мы вообще не обсуждаем ФП. Вы пытаетесь доказать, что чистый ООП не имеет права на существование, потому что это плохо не по нормам ФП, а по каким-то другим, общезначимым причинам. Да?

НЛО прилетело и опубликовало эту надпись здесь

Вам, по-моему, сейчас уже придраться бы просто ради того, чтобы придраться.

facepalm!

У вас плохой дизайн, если вам это нужно. Почему функция, которая занимается бизнес-логикой, занимается ещё какой-то работой с коллаборантами?

Ещё раз: почему тут плохой дизайн? Потому что я попросил другие объекты выполнить за меня часть работы?

А вот если бы я данные из этих объектов выделил в отдельные структуры, и вызывал бы на них функции без состояния, то мой ООП-дизайн был бы хорошим?

Вы же это тут сказали? И это не есть утверждение "ваш ООП-дизайн не соответствует моим представлениям о хорошем ФП-дизайне, поэтому он плохой"?

НЛО прилетело и опубликовало эту надпись здесь

Это не значит, что такая идея хороша. Я не могу рассуждать статически о динамической системе и не могу сказать, какое поведение у неё будет (и какого не будет).

Точно! Я же не могу каменным топором расщепить атом. Значит идея расщепления атома не хорошая.

У меня достаточно опыта разработки с «неправильным» ООП, чтобы

…представлять, что в «правильном ООП» (где вообще всё возможно) проблем будет ещё больше.

…или чтобы заблуждаться насчёт "правильного ООП" :)

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

НЛО прилетело и опубликовало эту надпись здесь

Вопросов, как я понимаю, тут не осталось. Ветка закрыта.

Просто на будущее — попытайтесь чуть меньше придираться к словами на уровне «проверяется не класс и не тип)))))»

Я же уже написал, что это была не совсем удачная шутка, даже попытался извиниться за неё.

Что касается вашего ответа, на поставленный вопрос, то он мне действительно не понравился. Я собирался дать на него ответ, но (слишком) увлёкся нашей с вами дискуссией. Тем не менее, постараюсь найти время и ответить-таки.

Когда я вам на это указываю, то вы говорите, что никто опять ничего не понимает. Это уже какая-то религия.

Вы опять фокусируетесь исключительно на одном (очевидном или удобном или ещё каком-то) варианте трактовки происходящего и даже не пытаетесь допустить существование других.

Может быть вы плохо указали на что-то? Ну, в том смысле, что вас не поняли?

А насчёт религии… Ваши высказывания относительно ФП для меня выглядят гораздо более похожими на религию, чем мои относительно ООП. Но я этому особого значения не придаю и как аргумент использовать даже не собираюсь ;)

Кстати, почему же искажённый ООП победил?

Что значит "победил"? Почему в 30-е годы в Германии победил нацизм? Вы действительно хотите переключаться здесь на обсуждение проблем массового сознания?

НЛО прилетело и опубликовало эту надпись здесь

Тогда ответ напрашивается сам собой.

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

Я даже не знаю… Эта логика требует комментариев, или и так с ней всё понятно?

НЛО прилетело и опубликовало эту надпись здесь

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

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

НЛО прилетело и опубликовало эту надпись здесь

Подавляющее большинство людей, профессионально занимающихся разработкой ПО, плевать хотели как на нюансы ООП, так и на ФП — они просто хавают, что дают зарабатывают деньги написанием кода.

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

НЛО прилетело и опубликовало эту надпись здесь

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

Чем продиктованы такие ожидания?

Днище.

Согласен.

Ну хоть такого количества UB нет, как в C++, и на том спасибо.

Согласен.

Теперь смотрим на рейтинг популярности ЯП:

Java — 3-е место.

Странно, это же днище?

C++ — 2-е место!

Это же даже хуже, чем днище!!!

О чём это говорит? Не о том, что "пипл хавает — и ладно"? Или же о том, что ФП и нормальная типизация — это… пардон, дерьмо?

В соседней ветке к той же дилемме пришли. Наверное, она ложная…

НЛО прилетело и опубликовало эту надпись здесь

Я за всю свою жизнь не видел ни одного проекта, где бы использовался канонический ФП. Более того, я даже не видел определения канонического ФП. И я не видел мест с чистым-правильным-хорошим ФП. А в местах с чистым ООП я работал. Вывод делайте сами :D

Что бы вы добавили из Smalltalk в хаскель?

Вообще не так. Почему всё надо воспринимать на столько прямолинейно. Haskell как язык уж точно за основу я бы не брал. Но даже вопрос "что бы я добавил из Haskell в Smalltalk" — был бы чуть ближе к сути, но совсем чуть-чуть.

Если фантазировать по-крупному (в порядке бреда), то я бы хотел взять за основу идею ООП (объекты и сообщения), очистить её (даже в Smalltalk-е с его минималистичным синтаксисом очень много инородных вкраплений), построить бы новый (абсолютно) чистый ОО-"язык" (именно в кавычках — так как это был бы не совсем язык, поскольку там было бы минимум синтаксиса, если бы он вообще был), на котором и для которого можно было бы создавать расширения и DSL-и с нужной семантикой и синтаксисом: классы, статический анализ, ФП-шные конструкции, многозадачность, многопоточность и т.д.

Это, конечно, с вероятностью 99% бред, но пока не доказана невозможность такого, 1% оставляет надежду.

НЛО прилетело и опубликовало эту надпись здесь

Вы опять не видите возможных альтернатив? Вряд ли же нужно объяснять, что всё программирование не крутится вокруг ФП? Вы наверняка в курсе, но почему-то вопрос свой сформулировали именно так, словно не понимаете этого.
А я просто не стал бы брать за основу ФП и добавлять туда что-то. Я бы взял за основу совершенно другую концепцию и добавил бы туда что-то полезное из ФП. Или, что ещё лучше, реализовал бы ФП во всей его полноте на базе этой концепции — в виде одного из множества расширений/плагинов. Только и всего :)

НЛО прилетело и опубликовало эту надпись здесь

Я разве ещё не дал понять, что… не скажу "никакого", но очень поверхностно-хлипкий. Именно поэтому я выше про "в порядке бреда". Но по образованию я "прикладной" математик ;)

А у вас?

НЛО прилетело и опубликовало эту надпись здесь

я бы хотел взять за основу идею ООП (объекты и сообщения)
там было бы минимум синтаксиса, если бы он вообще был
но пока не доказана невозможность такого, 1% оставляет надежду.

Это давно уже есть.

var obj = {
  send(anyMessage) {
    console.log('do something with:', anyMessage);
    
    let anyValue = ['abcd', 1, {data: 'data'}][Math.floor(Math.random()*3)];
    return anyValue;
  }
};

var r1 = obj.send('test');
var r2 = obj.send(2);
var r3 = obj.send(new Date());

console.log('response:', r1, r2, r3);

/*
do something with: test
do something with: 2
do something with: Date Tue Oct 29 2024 ...
response: Object { data: "data" } abcd 1
*/

Только почему-то так никто не пишет. Наверно по каким-то причинам людям это кажется неудобным?

Это давно уже есть.

Что "это"?

Вывод типов? var-ы? Я так пишу. И множество моих знакомых так пишет. И это очень удобно. Но это вообще другое. Или вы о чём?

О том, что процитировано в цитате - вы сказали, что хотите сделать язык без типизации, где любой объект может обработать любое сообщение, как в Smalltalk. Я сказал, что для этого не нужно изобретать новый язык, это легко сделать в JavaScript или любом другом языке с динамической типизацией. Только люди придумали TypeScript, потому что понимать и поддерживать такой код сложно для того, кто его не писал. И в умных книгах авторы по опыту советуют использовать типизацию где возможно.

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

Я так пишу. И множество моих знакомых так пишет.

Ну так вы-то сокрушаетесь о том, что другие так не пишут, и используют современный ООП, а не как в Smalltalk-е.

Мне надоело указывать вам на ваши логические ошибки. Оставлю это без комментариев.

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

вы мне написали только один комментарий с вопросами. Возможно, вы не следите, кому отвечаете.

Простите, действительно. Уже не ожидал, что здесь могут появиться новые участники. Да ещё с похожим стилем аргументации.

Отвечаю по существу.

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

Нет, я не это сказал. Языков без типизации достаточно много. Я сказал совершенно другое.

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

Ну так вы-то сокрушаетесь о том, что другие так не пишут, и используют современный ООП, а не как в Smalltalk-е.

Опять неверная интерпретация моих слов.

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

Язык JavaScript с моей точки зрения вполне может претендовать на звание одного из худших языков в истории Сomputer Science. Если уж говорить про чистый ОО-язык без классов, то в первую очередь стоит упомянуть Self. Однако, ещё раз повторю: смысл моей фантазии на тему нового языка заключался не в этом.

Ок, тогда можете подробнее объяснить, чем ваш гипотетический язык отличается от современного ООП?

С моей точки зрения ООП недостает одной конкретной вещи - сужение ответственности вида "Rectangle -> Square", и соответствующие преобразования "r as Square". С обычным наследованием сужение ответственности в наследнике создает неудобства, и поэтому есть принцип подстановки Лисков, который это запрещает. Но это расширение возможностей ООП, а не что-то принципиально другое.

Ок, тогда можете подробнее объяснить, чем ваш гипотетический язык отличается от современного ООП?

Я не очень понимаю, что вы имеете ввиду под "современным" ООП. Сюда можно отнести и (тьфу-тьфу-тьфу) C++, и (тьфу) Java, и Ruby с Python-ом… даже PHP. Но и Smalltalk ещё живёт, и даже почти "развивается".

Вот, относительно последнего — поскольку (на пару с Self) это самая чистая (из известных мне) объектных систем — я могу пояснить. Очень кратко, так как вряд ли вас интересуют детали моих смутных фантазий.

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

Вижу, как минимум, следующие направления дистилляции:

  • Поиск минимальной "жизнеспособной" объектной системы: какой минимальный набор (необъектных) примитивов позволит "вырастить" полноценную объектную систему?

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

  • Возможно, такая очистка позволит создать некий "бессинтаксический" язык для обмена сообщениями.

    Тогда, может быть, получится выйти на идею "многоязычия" — к чему-то подобному сначала пришёл Алан Кэй (что воплотилось в Smalltalk-72), но потом от этой идеи отказались из-за её сложности. Есть подозрения, что этой сложностью на самом деле можно управлять. В чём-то это может напоминает микросервисную архитектуру, но на различных архитектурных уровнях и (в идеале) без лишних сложностей.

Я не очень понимаю, что вы имеете ввиду под "современным" ООП.

Это вы употребили фразу "И в ООП (особенно в его настоящем виде, а не в том изуродованном, который на сегодняшний день стал мейнстримом)". "Современным" это синоним вашего выражения "на сегодняшний день". Поэтому у вас и надо спрашивать, что вы имели в виду.

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

Вообще-то про детали я и спрашивал.

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

Описанное далее не является ответом на заданный вопрос. То есть опять уход от ответа.
Если вы попробуете привести примеры, как это может выглядеть, то придете либо к моему примеру на JavaScript без типов, либо к ООП в том виде, который на сегодняшний день стал мейнстримом.

какой минимальный набор (необъектных) примитивов позволит "вырастить" полноценную объектную систему?

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

Такой необъектной конструкцией, например, является возврат из метода — она не ложится на концепцию "посылки сообщений".

Вызов метода с аргументами и возврат результата из метода это один из вариантов реализации посылки сообщений.
Другой вариант это использовать очереди сообщений, но тогда вместо конструкции возврата придется добавлять конструкции для работы с очередями, в том числе для ожидания результата. Примеры - Erlang или async/await. Без возврата результата в каком-то виде любой результат вычислений нельзя будет использовать, в том числе поместить в переменную.

В чём-то это может напоминает микросервисную архитектуру

Микросервисы отличаются только тем, что каждый микросервис работает в отдельном процессе. Вы конечно можете послать сообщение для вычисления синуса другому процессу, но вам будут нужны конструкции для ожидания результата. Event loop с async/await в JavaScript это однопоточная имитация такой параллельной работы. Или сообщения между процессами в Erlang, там многопоточность обеспечивается на уровне виртуальной машины.

Знакомая песня манера. Я тоже в курсе, что задавать вопросы проще, чем на них отвечать. И тоже так умею. И даже заявлять

Описанное далее не является ответом на заданный вопрос. То есть опять уход от ответа.

тоже могу. Брезгую, но при необходимости могу ;D

Например,

> Я не очень понимаю, что вы имеете ввиду под "современным" ООП.

Это вы употребили фразу "И в ООП (особенно в его настоящем виде, а не в том изуродованном, который на сегодняшний день стал мейнстримом)". "Современным" это синоним вашего выражения "на сегодняшний день". Поэтому у вас и надо спрашивать, что вы имели в виду.

"Описанное далее не является ответом на заданный вопрос. То есть опять уход от ответа. " (c)

То есть, вы не знаете, что я имел ввиду под "на сегодняшний мейнстримовым ООП", но при этом вы заявляете

Если вы попробуете привести примеры, как это может выглядеть, то придете либо к моему примеру на JavaScript без типов, либо к ООП в том виде, который на сегодняшний день стал мейнстримом.

Не знаете, о чём речь, но утверждаете, что что я получу именно это, так получается?

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

Если вы берёте на себя труд оспаривать данное утверждение, будьте добры обосновать своё мнение. Сможете, или будете опять уходить от ответа?

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

Я тоже в курсе, что задавать вопросы проще, чем на них отвечать.

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

То есть, вы не знаете, что я имел ввиду под "на сегодняшний мейнстримовым ООП", но при этом вы заявляете

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

Не знаете, о чём речь, но утверждаете, что что я получу именно это, так получается?

Да, потому что в вопросе "Есть ли у переменных типизация" только 2 варианта ответа, независимо от того, что вы имели в виду. И потому что есть причины, по которым люди пришли к типизации в виде современного ООП.
Кроме того, я сказал это лишь в 4 комментарии, чтобы пояснить мою точку зрения и не ходить вокруг да около, так как вы сами на протяжении 4 комментариев отказываетесь отвечать, о чем речь.

и поэтому могу заявлять, что мои идеи про "дистиллированный ООП" от этого будет отличаться

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

будьте добры обосновать своё мнение. Сможете, или будете опять уходить от ответа?

Я уже его обосновал в рамках той информации, которую вы захотели сообщить. Хотите более подробных ответов, приводите более подробную информацию. Я совершенно не против вам ответить, и не буду уходить от ответа, как это делаете вы. Даже одного примера кода с вычислением синуса будет достаточно - код метода sin и код его вызова в середине некоторого алгоритма.

но делать это под руководством человека, который даже не собирается вникать в суть происходящего

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

Так вы приведете примеры, как выглядит ваш гипотетический язык и чем он отличается от ООП, чтобы можно было обсуждать конструктивно, или конструктивная дискуссия вас не интересует?

Или какую цель вы перед собой в этом обсуждении ставите?

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

> какой минимальный набор (необъектных) примитивов позволит "вырастить" полноценную объектную систему?

Как раз на это я привел пример кода. 

О, да вы ещё и предсказываете будущее?

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

…Но вы опять даже не попытались понять, о чём речь. Может быть попробуете, если не понимаете, сначала уточнять, а не начинать с (бессмысленных) "наездов и (необоснованных) выводов? ;)

Если вы попробуете привести примеры, как это может выглядеть, то придете либо к моему примеру на JavaScript без типов, либо к ООП в том виде, который на сегодняшний день стал мейнстримом.

Я могу привести пример аналогичный вашему. Держите:

obj := Object clone addMethod: ( anyMessage >> ( console log: "do something with: ", anyMessage. return: ["abcd", 1, (#data -> #data)][(1 to: 3) random]. ) ). console log: ( 'response:', (obj send: "test"), (obj send: 2), (obj send: Date new) );

…Тут я удалил свои пояснения — захотите, спросите.

Только я — вслед за вами :D — предсказываю, что вы не попросите комментариев, а скажете "да это же мой код пример на JavaScript!" (и это будет правдой — именно его я взял за основу) и сделаете (неверный) вывод, о том, что это эквивалентно тому самому JS.

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

Вызов метода с аргументами и возврат результата из метода это один из вариантов реализации посылки сообщений.

Во-первых, вы опять не поняли, о чём я говорил.

Во-вторых, если вызов метода — один из вариантов реализации посылки сообщений, то скажите, какой метод будет вызван здесь?

object someMessage.

Другой вариант это использовать очереди сообщений, но тогда вместо конструкции возврата придется добавлять конструкции для работы с очередями, в том числе для ожидания результата. Примеры - Erlang или async/await. Без возврата результата в каком-то виде любой результат вычислений нельзя будет использовать, в том числе поместить в переменную.

Да, объектную модель можно строить как на синхронной, так и на асинхронной обработке сообщений, но речь вообще не об этом, а о том, чтобы в случае синхронной обработки сделать возврат именно сообщением. В таком случае, кто должен быть получателем этого сообщения и как он должен это сообщение обрабатывать. (Это вам в качестве подсказки к вопросам по примеру выше. Там ещё много подобных вопросов должно возникнуть.)

Микросервисы отличаются только тем, что каждый микросервис работает в отдельном процессе.

Отличаются от чего?

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

Ещё одно отличие — то самое многоязычие: микросервис в принципе может поддерживать несколько протоколов для обмена сообщениями.

какой минимальный набор примитивов позволит "вырастить" полноценную объектную систему?
О, да вы ещё и предсказываете будущее?

Нет, в вашем комментарии, на который я отвечал, есть фраза "там было бы минимум синтаксиса, если бы он вообще был".

Может быть попробуете, если не понимаете, сначала уточнять?

Я так сделал 2 комментария назад, вы отказываетесь отвечать на этот вопрос.
"Ок, тогда можете подробнее объяснить, чем ваш гипотетический язык отличается от современного ООП?"

- можете подробнее объяснить?
- Тут я удалил свои пояснения — захотите, спросите. Только я — вслед за вами :D — предсказываю, что вы не попросите комментариев

Я их уже попросил. Но вы опять сделали противоположное. Видимо, конструктивное обсуждение вам неинтересно.

и сделаете (неверный) вывод, о том, что это эквивалентно тому самому JS

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

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

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

Ну так кто ж виноват в том, что вы решили ответить кратко?) Я вас просил объяснить подробнее.

то скажите, какой метод будет вызван здесь?
object someMessage.

Если это Smalltalk, то не знаю, я с ним не работал. Насколько я понял из информации в Интернете, то обработчик либо someMessage, либо doesNotUnderstand. Вы опять вместо конструктивного обсуждения переводите разговор на другие темы, загадки какие-то загадываете.

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

Я именно для этого случая и привел пример с вычислением синуса. Это вам надо подумать о том, как вы будете получать сообщение с результатом, чтобы использовать его в следующих вычислениях некоторого алгоритма.

Это вам в качестве подсказки к вопросам по примеру выше.

На эту подсказку я вам и намекал примером синуса. И именно поэтому уже неоднократно просил написать примеры кода. Потому что я вижу, что вы не видите сложностей, которые при этом возникнут.

class A {
  function someAlgorithm(x) {
    // y = sin(2*x) * 4;
    tmp1 = x * 2;
    tmp2 = Math.sin(tmp1);
    tmp3 = tmp2 * 4;   // <
    
    return tmp3;
  }
}

class Math {
  function sin(x) {
    // ... вычисление ряда для синуса
    
    return res;
  }
}

Теперь подумайте, как с посылкой соoбщений вместо return продолжить выполнение с точки tmp3 после вычисления синуса. Покажите, как будет выглядеть этот код. Если у вас многопоточное выполнение, как остановить выполнение в A на точке tmp2?

Я сам отвечать на эти вопросы не буду, хотя знаю ответ, потому что вы опять скажете, что я вас не так понял.

Отличаются от чего?

Это вас надо спрашивать, потому что это вы их привели как аналогию. Я лишь объясняю в тех терминах, которые вы предпочитаете использовать. При этом мои объяснения не зависят от того, что конкретно вы имели в виду, я умею работать с абстракциями.
Отличаются от однопоточного монолита с библиотеками вместо микросервисов.

никакой тайпчекер не может запретить послать микросервису, пусть даже в рамках поддерживаемого микросервисом протокола, любое сообщение

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

и микросервис уже сам решит, как именно его обрабатывать: например, выдать ошибку или вызвать "основную" бизнес-логику.

Как я и сказал, это уже возможно в существующих языках. Можно делать в любом объекте метод send и обрабатывать там сообщения как захотите.
У микросервиов тут нет отличия от не-микросервисов, что бы вы под этим ни подразумевали.

микросервис в принципе может поддерживать несколько протоколов для обмена сообщениями.

Если вы говорите именно про язык протокола, а не про язык программирования микросервиса, то тут опять же нет никаких отличий от не-микросервисов. Никто вам не мешает вызывать метод не так a.method(arg1, arg2), а вот так a.http('POST', 'method', JSON.stringify({'arg1': arg1, 'arg2': arg2})), где метод "http" своими механизмами будет вызывать метод "method".
Просто при выполнении в одном процессе это не нужно.

Что, кстати, является свидетельством в пользу предыдущего тезиса — то ли ООП обречён выродиться, то ли его никто не понимает.

Вот это как раз — ложная дихотомия. Как насчёт третьей альтернативы: люди (так сказать "в массе"), наконец поймут ООП?

люди (так сказать "в массе"), наконец поймут ООП?

как вы считаете люди (в массе) понимают теорию относительности? И если нет, есть ли надежда, что они ее (именно в массе ) начнут понимать в обозримом будущем?

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

А теория относительности почему появилась? А ФП/ООП почему появилось?

Ветка закрыта.

НЛО прилетело и опубликовало эту надпись здесь

Вы троллить изволите?

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

Я же вам с самого начала написал:

Не хотите — не тратьте, кто ж вас заставляет-то :)

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

Ещё раз: не нужно, так не нужно – кто ж вас заставляет-то? :)

НЛО прилетело и опубликовало эту надпись здесь

Выходит, вообще мертворождённый?

Нет.

А, коммунизм хороший — люди плохие?

Кстати, да — отличная аналогия. Всё именно так. Как люди не доросли до коммунизма, так же люди не доросли до ООП.

Потому что единственная явно озвученная альтернативная гипотеза — что ну просто вот люди всё не те, массово не понимают ООП, а так-то сама парадигма огого. Просто, ну… опять же, люди не те.

Отлично. …А какой процент рынка занимают функциональные языки? На каком там месте Haskell в индексе популярности нынче? На 32-м? (А, например, (Visual) FoxPro — на 25-м) А почему так? Видимо, ФП — дерьмо похуже "современного ООП" получается… Ну, на том и остановимся.

> а затем ФП взяло много из ООП

Интересно, кстати, что, ну да ладно.

Например, модель акторов, которую Хьюитт во многом перенял у Кэя. А Кэй до этого многое взял из Хьюиттовского же Planner-а.

НЛО прилетело и опубликовало эту надпись здесь

"Ортогональны" — это такой способ сказать, что "не имеют отношения и не нужны"? Почему же статьи про модель акторов публикуют в журналах по ФП, а саму модель реализуют в ФЯП?

НЛО прилетело и опубликовало эту надпись здесь

То есть, parser combinator-ы и акторы на ФП делают потому, что это приятно. :D

Хорошо. Тогда фразу про то, что ФП что-то там взяло из ООП трактуем как "ФП из ООП почерпнуло как не надо делать" и забываем.

Жёсткий тайпчекинг, применяемый в ФП это ни что иное, как Test Driven Development на максималках. Когда вы при написании любого фрагмента кода автоматически создаёте механизм его тестирования. Отсюда следует 1) более медленная скорость написания такого кода 2) его повышенная надёжность 3) простота рефакторинга 4) большая скорость компиляции (т.к. компилятор одновременно и компилирует, и "тестирует" во время тайпчекинга).

И по большому счёту это единственный способ применять TDD на практике, все остальные подходы к TDD разбивают о то, что на него быстро забивают.

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

Жёсткий тайпчекинг, применяемый в ФП это ни что иное, как Test Driven Development на максималках.

"Рак — небольшая красная рыба, которая плавает хвостом вперёд". Не рыба, не красного цвета, не плавает, и не хвостом вперёд. А так — да, всё правильно.

Типы — это обобщение. Если вы сначала придумываете типы, то вы идёте от общего к частному. Вопрос только в том, откуда взять эти обобщения?

Тесты — это частное. С TDD вы идёте от частного к общему. А ответить на вопрос, откуда эти частности взялись — элементарно просто: по дедукции из требований.

…А так да, "всё правильно".

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

вот вам оптимизированный под SSE код (код с векторизацией):

смотри параграф: "3. SIMD (SSE + NEON)"

интересно как вы его проверите с помощью типизации и тайпчекинга ?

Можно проверить что он действительно оптимизированный? Неплохо бы проверить что он выдает тот же результат что и исходный, как вам тут поможет функциональное программирование, интересно?

Можно проверить что он действительно оптимизированный?

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

optimizer :: Unoptimized Code -> Optimized Code

И при этом создать тип данных Optimized Code кроме как с помощью этой функции никак невозможно, т.к. конструктор данных Optimized недоступен. Тогда получив на вход Optimized Code вы получаете уверенность, что код прошел процедуру оптимизации.

А вот насколько оптимизация была удачной или или неудачной (вы же наверное подразумевали это?). Но это уже другой вопрос. И ответ на него зависит от того, какими метриками и критериями измерять. Тогда нужна функция

perfMeasure :: Unoptimized Code -> Optimized Code -> OptimizeMetrics -> IO (Maybe (SuccessfullyOptimized Code), PerfMeasureResults)

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

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

В теории с помощью типизации можно так проверить логику работы любого алгоритма. На практике, зачастую это довольно сложно по понятным причинам. Как тут поможет ФП? Там где тяжело проверять логику тайпчекингом, есть прекрасный механизм property based test. Те есть мы описываем не то, какой ожидаем результат на выходе, а то, какими свойствами должен обладать этот результат. А т.к. любая функция в ФП представляет из себя всего лишь композицию других, более простых функций, а те в свою очередь тоже композиция ещё более простых, то для того, чтобы убедиться в коректности работы функции достаточно описать свойства ожидаемого результата всех функций из которых она состоит. А так как те функции - простые, то и свойства их ожидаемого результата достаточно простые и могут быть легко описаны.

Да, это очень просто. Достаточно обернуть код в контейнер, который на уровне типов говорит о том - оптимизированный код или нет.

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

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

НЛО прилетело и опубликовало эту надпись здесь

Почему? newtype в хаскеле не имеет никакого оверхеда.

не имеет оверхеда по сравнению с чем? С отсутствием newtype ? То есть без newtype тоже все работает? Зачем тогда он нужен, не совсем понятно. Я вообще не совсем понимаю как может существовать тип если там данных нет, а только одни функции. Подход основанный на противоречии как будто специально создан чтобы разрушить любое начинание которое на него полагается.

Покажете тест, который делает этот взгляд на код?

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

НЛО прилетело и опубликовало эту надпись здесь

А чем вам Int -> Double плохой тип?

По моему это преобразование типов, а не тип. Типами являются Int и Double , здесь по моему. Интересно как вы объявите тип структуры с 5-ю полями? Это кстати интересный вопрос: можно объявить какой то не примитивный тип средствами функционального программирования?

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

НЛО прилетело и опубликовало эту надпись здесь

Это тип функции, которая принимает Int и возвращает Double. Преобразовывать типы в смысле условного C она не обязана, она может делать и что-то поинтереснее.

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

Я только не понял почему вы представляете это как отличие от условного С, потому что для функции на условном С никто также не сможет запретить автору плясать в момент исполнения его функции.

Кстати, какие типы и куда преобразовывает вот эта функция?

я попробую догадаться, это функция, которая делает из переменной (или как это надо называть по ФП правилам? я теряюсь) список с одним элементом из переменной, круто конечно, но меня такой синтаксис напрягает, так как у меня слишком много вариантов как компилятор должен перевести это в машинный ассемблер. Я оптимизацией занимаюсь.

НЛО прилетело и опубликовало эту надпись здесь

Интереснее может быть,

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

Нет, это функция, которая для Person возвращает всех его внуков.

как и ожидалось я не догадался, но если я вам составлю выражение на С++ с интерфейсами и указателями на функции, будет вам интересно его разбирать, если вы знаете что оно вам в ближайшие годы не пригодится? (заметьте я не спрашиваю поймете ли вы его, если серьезно к нему отнесетесь - я исхожу из того что разберетесь!)

Кстати, мне такие конструкции (операторы, как это назвать?)

>=>

очень напоминают стиль Perl-а, вы наверно в курсе где теперь Perl, а он мне очень нравился в свое время для задач по анализу текста.

НЛО прилетело и опубликовало эту надпись здесь

А если написать double (*)(double(*)(int));

вместо (Int -> Double) -> Double то вообще заживём.

так не надо так писать то! Вы думаете если вы придумали синтаксис как записать страшное выражение чтобы оно не казалось вам таким страшным оно вас не укусит?

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

НЛО прилетело и опубликовало эту надпись здесь

Значит вы идейный сторонник ФП и вас на мякине не проведешь! Идейные всегда готовы к любым испытаниям.

Успехов вам, было интересно почитать вашу аргументацию.

Newtype имеет значение лишь на этапе компиляции (для работы тайпчекинга). А дальше, при условии удачного тайпчекинга, во время компиляции данные извлекаются из него автоматически, т.е. будет сформирована одна и та же последовательность бит независимо от того, была ли обёртка в newtype или нет. Ну а вообще это всё такие делали, которые ни о чём. Даже если бы у newtype не было такого свойства, из него же можно извлечь содержимое самостоятельно, если понадобится.

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

Написали вы функцию f. Допустим она сложная, состоит из композиции пары десятков других функций. Потом вы её решили оптимизировать, проводите рефакторинг. Скорее всего заодно вы рефачите и некоторые функции её составляющие. А тайпчекинг помогает вам убедиться в том, что все ваши функции остаются согласованными. И это с довольно высокой вероятностью говорит о том, что ошибок нет. Идеальная система типов даст 100% гарантию, что ошибок нет, точно также, как и идеальное покрытие юнит тестами. Но понятно, что разработать идеальную систему типов очень и очень сложно, так же как и идеальные юнит тесты. Обычно каждый из этих методов говорят лишь о том, что скорее всего ошибок нет, но не даёт абсолютной гарантии. А вот если вы какой то критически важный участок кода покроете и типизацией и юнит тестами, то это будет уже супер надёжно.

НЛО прилетело и опубликовало эту надпись здесь

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

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

Они не позволяют достигнуть одного результата.

Тест в Test-Driven Development — это спецификация требуемого поведения на примере. Этот пример позволяет добавить в систему новую функциональности, и доработки систему так, чтобы эта новая функциональность "хорошо легла". То, что тест в дальнейшем позволит проверить, что система по-прежнему соответствует реализованной ранее спецификации — важный, но побочный эффект.

В Test-Driven Development мы идём от частного к общему: на примерах "накапливаем опыт" и постепенно обобщаем его, формируя дизайн. При этом мы мало зависим от того, кто и как сформулировал требования — мы всё равно должны сначала разбить их на примеры, что позволяет упростить (частные примеры проще обобщённых утверждений) и "не идти на поводу" у дизайна, заложенного автором формулировок требований.

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

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

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

В типизированной системе я сначала вынужден "доказывать" компилятору, что моя гипотеза может применена ко всей системе (что даже не всегда требуется), и только потом смогу запустить проверку. Долгие глобальные изменения — проверка. Если гипотеза окажется ложной, мои усилия на доказательства окажутся пустой тратой времени.

Я примерно представляю, как может работать Type-Driven Development, но никогда не практиковал этот подход. Не практиковал потому, что сама идея кажется противоречивой. Тип — уже обобщение. Откуда возьмутся основания для обобщения в начале разработки? Я вижу только два источника: формулировка требований и фантазия разработчика. Оба источника мне не кажутся надёжными, легко могут привести к неудачному решению.

НЛО прилетело и опубликовало эту надпись здесь

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

НЛО прилетело и опубликовало эту надпись здесь

в типах всё выражаем, потом функции пишем, им удовлетворяющие.

Тест — пример, конкретный случай, частное.

Тип — обобщённое правило, общее.

Правильно?

Мне кажется или автор оригинальной статьи осуждает микроскоп за то,что тем неудобно забивать гвозди?

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

Можно сделать это без рефакторинга, используя композицию:

fileLogger2AutoFlushLogger :: FileLogger -> Logger
fileLogger2AutoFlushLogger fileLogger = MkLogger
    { _log = \message severity -> do
        logFileLogger fileLogger message severity
        _flush fileLogger
    }

Советую посмотреть обсуждение этого здесь.

НЛО прилетело и опубликовало эту надпись здесь

Type Classes — это механизм абстракции в функциональном программировании (ФП), который действительно можно считать аналогом интерфейсов из ООП, но с ключевыми отличиями в реализации и философии. Давайте разберемся, как они работают и чем отличаются от классических интерфейсов.

Что такое Type Classes?

Type Class — это абстракция, которая:

Задает набор операций (функций), которые должны быть реализованы для конкретного типа данных.

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

Отделяет реализацию поведения от самого типа данных (в отличие от ООП, где класс "принадлежит" объекту).

Зарегистрируйтесь на Хабре, чтобы оставить комментарий