Здравствуйте коллеги!
Хотелось бы поделиться мыслями об ООЯП и ООП в целом, а также что можно (и, как мне кажется, нужно) сделать на этой основе.
Основные идеи: В современных ООЯП отсутствует чётко выделенное и обязательное ядро моделирования для создания абстракций, основанных только на "чистых" концепциях ООП. Концепция ООП "всё есть объект" не практична. Концепция обмена сообщениями жёстко связана с её реализацией.
Под объектно-ориентированными языками программирования (ООЯП) понимаются Java и C#, хотя к другим ООЯП данная тема тоже может иметь отношение.
Я не пытаюсь начать очередную дискуссию о проблемах ООП или ООП vs ФП. Цель статьи – посмотреть на ООЯП и вообще языки программирования, и показать, что у языков есть свойства, которые могут быть полезными и для ООЯП. Современные ООЯП в той или иной мере доказали свою жизнеспособность, а результатом решения данного вопроса был бы новый язык.
Практически всё, о чём пойдёт речь, так или иначе уже используется на практике, но хотелось бы, чтобы это было частью языка, хотя бы как альтернатива. Но такой альтернативы в настоящее время, похоже, просто нет.
На мой взгляд, в ООЯП отсутствует обязательная часть – ядро моделирования, на котором можно декларативно и очень абстрактно описывать предметную область, основываясь только на чистых концепциях моделирования, в данном случае – на элементах декомпозиции ООП (коллабораторы, сообщения, данные).
В качестве примера языка, в котором есть такое ядро моделирования, можно привести Haskell: грязные функции ввода/вывода требуют специального синтаксиса и взаимодействуют с чистыми функциями через чёткий протокол. Чистые функции позволяют довольно абстрактно моделировать предметную область, основываясь на функциональном подходе. (Хотя даже в функциональных языках иногда приходится учитывать реализацию, как пример – использование хвостовой рекурсии и её оптимизация транслятором).
Причина, почему чисто функциональный язык имеет такое ядро, думаю, очевидна: функциональный подход по определению основан на абстрактной математической теории (лямбда исчисление). Причины же появления ООП, на мой взгляд, чисто практические и прикладные, поэтому в ООЯП так выпукло просматривается императивный фундамент.
Ядро моделирования ООЯП должно основываться только на элементах декомпозиции ООП. Синтаксис ядра моделирования должен быть очень простой, декларативный и абстрактный. Ничего, кроме определения "топологии" объектов/коллабораторов (кто с кем взаимодействует), семантики/имён сообщений и их параметров/возвращаемых значений в ядре моделирования быть не должно. Использование такого языка возможно только начиная с ядра моделирования, преобразуя затем модели в выходной код.
Из-за того, что в ООЯП смешаны конструкции как для описания объектов (классы, интерфейсы, методы и т.д.), так и для реализации императивного подхода, в ООЯП по сути заложено фундаментальное противоречие: одновременно нужно писать и абстрактные модели, и их конкретную императивную реализацию. Это противоречие и является, на мой взгляд, причиной ключевых пунктов критики ООП.
Помимо обеспечения императивного подхода, использование ресурсов в ООЯП также не отделено от абстрактных моделей. Ресурсами являются память и алгоритмы (в смысле последовательность инструкций). На мой взгляд, память и алгоритмы как ресурсы нужно привязывать к абстрактным моделям. В моделях императивность должна быть представлена крупными ключевыми шагами, основываясь на паттерне "шаблонный метод". Далее шаги из моделей преобразуются в фактический выходной код.
Вообще, как мне кажется, оператор new
является признаком явного императивного подхода. Оператора new
вообще не должно быть в ядре моделирования для определения объектов – объекты задаются декларативно. Существование объекта декларируется, а фактический способ создания будет уточняться позже. Более того, инстанцироваться может не сам объект, а прокси к удалённому объекту.
Другим примером проблемы является реализация самой концепции обмена сообщениями. Обмен сообщениями, как абстрактная концепция, в ООЯП жёстко задаётся языком и представлен в виде вызовов методов. Обмен сообщениями должен оставаться абстрактным в ядре моделирования и позже проецироваться в конкретный механизм обмена сообщениями, например, вызовы методов или проецироваться в какую-нибудь топологию распределённых акторов.
Ещё одна проблема, которая связана с отсутствием ядра моделирования, это null значение. Тут, по-моему, самая жуткая смесь. Значением null в ООЯП обозначают разные вещи, отсюда все проблемы. Допустим, что чистое ООП это способ моделирования, отдельно стоят императивная реализация и ресурсы, и ещё есть модель данных. Тогда суть проблемы в том, что любой объект требует ресурса "память" (что есть признак императивной реализации) и null значение из императивной реализации присутствует во всех контекстах. Модель данных сама по себе допускает null значение, но с этими null значениями меньше проблем, т.к. они ожидаемы и связанны с данными. В ядре моделирования null значения для объектов должны отсутствовать по определению, хотя null значения из модели данных допустимы.
Несколько слов о самих концепциях ООП. На мой взгляд, концепция "всё есть объект" не практична, хотя выглядит, конечно, очень логично. Думаю, практика всё-таки требует, что данные не сводятся к объектам, и основные понятия ООП я бы определил как сообщения/коллабораторы/данные. Модель данных (например, реляционная) должна быть в явном виде. Моделирование предметной области заключается в представлении её в виде группы объектов (коллабораторов), которые обмениваются сообщениями. Аргументами сообщений являются данные. Это и есть основа ядра моделирования. "Всё есть объект" – это сверх-обобщение, когда теряется важная специфика базовых понятий, и они начинают выглядеть одинаково, хотя фундаментально их нужно различать.
Заключение
ООП – это способ моделирования (декомпозиция и определение абстракций), его нужно отделять от императивной реализации, управления ресурсами и модели данных. Современные ООЯП смешивают все эти понятия, и проблема решается за рамками языков, через применение принципов проектирования, паттернов, идиом, соглашений и пр.
Альтернативное решение мне видится в новом языке, построенном по аналогии с функциональными языками. "По аналогии" означает, что у нового языка будет такое же свойство, как и у функциональных: чистое и обязательное ядро моделирования.
В качестве примера похожей идеи приведу проект объектно-ориентированно языка eolang Егора Бугаенко. (Это не реклама Егора и его проекта, на момент написания статьи я не знаком с Егором лично, не имел с ним ни чатов, ни переписки, не являюсь контрибютором его проектов). То, что происходит в рамках проекта eolang, в целом поддерживаю, хотя в деталях очень много вопросов и несогласий. Тем не менее, в eolang происходит на мой взгляд то, о чём шла речь выше: из Java убрали целый набор императивных и процедурных конструкций и механизмов. Как раз удаление императивных и процедурных элементов и есть попытка выделить чистое ядро моделирования ООП.
Комментарии (64)
prostovovan
14.02.2017 06:07По поводу «все есть объект» — есть хорошая статья об этом на Хабре — https://habrahabr.ru/post/111125/
И по-моему Егор Бугаенко пережимает в этом вопросе, он хочет и сообщения делать объектами (как говорил и Алан Кей). Лично я не вижу в таком подходе пользы. А польза от ООП одна — возможность создать сложную систему с легко настраиваемыми и независимыми частями.lair
14.02.2017 11:39А польза от ООП одна — возможность создать сложную систему с легко настраиваемыми и независимыми частями.
Ну так это и без ООП можно.
prostovovan
14.02.2017 14:21Легко нельзя.
lair
14.02.2017 14:22"Легко" и "сложная" — это очень субъективные понятия, будем честными.
prostovovan
14.02.2017 21:41Нет, не совсем субъективные, иначе бы ООП не поручило бы такого распространения. Вот сейчас важна параллельность — пошло ФП.
lair
14.02.2017 22:25… или просто от ООП не единственная польза.
prostovovan
14.02.2017 22:57Интересно услышать варианты…
vlad_zay
14.02.2017 06:08+2Какие практические преимущества Вы ожидаете от вышеописанной концепции? Я, например, вижу следующую проблему. Разработчику нужно будет сперва смоделировать ОО-констуркцию в ядре декларативным способом. Затем ему всё равно придёться реализовывать поведение/общение объектов императивным методом. А если в ходе реализации выяснится, что модель не оптимальна и нужно её менять? Не будет ли это дополнительной нагрузкой, постоянно координировать изменения между реализацией и декларированной моделью?
PalladaProject
14.02.2017 09:46Очень резонный вопрос. Основное преимущество — это само по себе разделение моделирования от программирования. На мой взгляд, проблема имеено в том, что детали реализации стоят на том же уровне что и модельные концепции. Разделение даст однонаправленную зависимость реализации от моделей. Многие проблемы ООЯП именно в том, что понятия из этих двух областей жёстко связаны и отягощают друг друга свойствами, не присущими им в "чистом" виде.
Проблема, о которой Вы говорите, решается инструментами с надлежащим функционалом. Модели и декларативная реализация должны быть "близко" друг от друга, для разработчика это должна быть единая и согласованная среда. Тут даже синтаксис моделей важен, всё-таки текст а не графика. Сложность должна быть в реализации инструментов, а не в реализации моделей.
Думаю, дополнительной нагрузки не будет, т.к. это сложность которая уже существует в проектах. Идея в том, чтобы иначе с ней бороться и не вносить побочной сложности из-за связей все-со-всеми (в дополнение к сложности domain problem и solution problem).
aikixd
14.02.2017 15:40Хочу добавить, что в ФП, где модель и поведение разделены, это только упрощает разработку. Такая схема требует от вас корректоного описания модели с самого начала и зависимость однонаправленная, в отличии от ООП, где все в одной куче. Оптимизация модели с самого начала только ускоряет процесс, поскольку кодовая база еще мала, в отличии от более поздних стадий где часто приходится городить костыли.
lair
14.02.2017 15:52+1А вы не могли бы, кстати, привести пример, как именно в ФП описывается модель? На примере какого-нибудь простенького процесса "покупатель создал заказ, по заказу пришел платеж, заказ отправили на склад, на складу подтвердили, что заказ ушел, отправили письмо кастомеру".
aikixd
14.02.2017 16:46На примере F#. Основное положение это то, что можно использовать только уже объявленые элементы. Те что находятся выше или в предыдущих файлах (файлы в проекте упорядочины).
type OrderItem = { itemName: string } type Order = { id: int items: OrderItem list shipped: bool payment: Payment option } and Payment = { id: int order: Order amount: decimal }
Мне нужно явно указать (
and
), что заказ и оплата являются рекурсивными типами и для этого они должны находится рядом. Это приводит к тому, что в модели, которая изначально казалась одноранговой, теперь четко выделены слои.
Если я добавлю функции между
OrderItem
иOrder
(скажем в качестве модуляOrderItem
, где я опишу поведение этого типа), я не смогу использовать то что ниже, и если мне потребуется сослаться на заказ, то я пойму, что модель не верна и ее нужно править. Функции работают точно так-же, и взаимно рекурсивные функции обязаны находится рядом. То есть поведение тоже поделено на слои.
Выходит что чем выше находится элемент тем он более конкретен, чем ниже более абстрактен. В самом низу находится одна единственная функция которая описывает всю программу.
lair
14.02.2017 17:00Если я добавлю функции между OrderItem и Order (скажем в качестве модуля OrderItem, где я опишу поведение этого типа), я не смогу использовать то что ниже, и если мне потребуется сослаться на заказ, то я пойму, что модель не верна и ее нужно править.
… или вы просто добавили функцию не там, где надо.
в модели, которая изначально казалась одноранговой, теперь четко выделены слои.
Что это за "слои"? Какую семантику они имеют? Что такого в
OrderItem
, что ее надо объявлять первой?
Основное положение это то, что можно использовать только уже объявленые элементы.
Вообще, это положение никак не исключительно (и не определяюще) для ФП. Я могу взять ООП и повторить все то же самое. Это некое искусственное ограничение на область видимости, никак не связанное с парадигмой. И да, чем сложнее ваша модель, тем более искусственным выглядит это ограничение (например, у заказа еще есть покупатель и менеджер, и для покупателя должны быть видны его заказы, и аналогично — для менеджера).
По факту, ваша модель — это не больше чем описание структуры данных. Она никак не захватывает ничего из описанного мной процесса. Она даже не описывает допустимые переходы и состояния (хотя в ФП это прекрасно делается, кстати).
aikixd
14.02.2017 17:50или вы просто добавили функцию не там, где надо.
Может быть, смотря что я хотел сделать. Если функция должна быть описанием поведения, то проблема в модели.
Что это за "слои"? Какую семантику они имеют? Что такого в OrderItem, что ее надо объявлять первой?
Его независимость.
Я могу взять ООП и повторить все то же самое.
Собственно сделать что-то на подобие того что предлагал автор. Это ограничение не более искусственно чем видимость классов. Но это заставляет меня точнее описывать модель и ее зависимости.
По факту, ваша модель — это не больше чем описание структуры данных.
Я опустил функции. Двум экранам кода, который легко представить не место в комментарии.
lair
14.02.2017 17:53Его независимость.
А от чего он независим? Хуже того, с точки зрения доменной модели,
OrderItem
— это частьOrder
, и снаружи него смысла не имеет.
Собственно сделать что-то на подобие того что предлагал автор.
Зачем? Есть и другие средства.
Это ограничение не более искусственно чем видимость классов.
У видимости классов совершенно другие задачи, вот в чем дело.
Но это заставляет меня точнее описывать модель и ее зависимости.
Точнее ли? Вернемся к моему примеру с покупателем и поставщиком — как выглядит модель теперь?
Я опустил функции.
То есть функции — часть модели?
aikixd
15.02.2017 14:59Хуже того, с точки зрения доменной модели, OrderItem — это часть Order, и снаружи него смысла не имеет.
Вас смущает направление стрелок в диаграмме?
Зачем? Есть и другие средства.
Можно вообще программы не писать, но разговор не об этом.
У видимости классов совершенно другие задачи, вот в чем дело.
Я не понимаю, вы издеваетесь? Для разных задач — разные инструменты. Все языки, кроме асма, накладывают на вас те или другие ограничения. Они все искусственные.
Точнее ли? Вернемся к моему примеру с покупателем и поставщиком — как выглядит модель теперь?
Их нужно добавить ниже. Скорее всего они должны быть рекурсивными типами.
То есть функции — часть модели?
Функции могут описывать поведение типа, то есть выступать чем-то вроде методов в ООП или отдельно стоящими элементами модели. Например, если есть два предмета, один издает звук, другой реагирует, то среду которая будет переносить звук можно представить в виде функции.
lair
15.02.2017 15:02Вас смущает направление стрелок в диаграмме?
Нет, меня смущает видимость.
Я не понимаю, вы издеваетесь?
Нет, я совершенно серьезно. В данном случае вы приводите некое ограничение (область видимости), которое, по вашему утверждению, помогает структурировать модель. Но это ограничение никак не связано с функциональной парадигмой.
Их нужно добавить ниже. Скорее всего они должны быть рекурсивными типами.
Приведите пример, пожалуйста.
Функции могут описывать поведение типа, то есть выступать чем-то вроде методов в ООП или отдельно стоящими элементами модели.
Так все-таки, функции — это часть модели или нет?
aristarh1970
15.02.2017 05:24+1И чем приведенный фргмент принципиально отличается от аналогичного фрагмента на (любом) ООЯП?!
TheShock
15.02.2017 14:13Мне нужно явно указать (and), что заказ и оплата являются рекурсивными типами и для этого они должны находится рядом. Это приводит к тому, что в модели, которая изначально казалась одноранговой, теперь четко выделены слои.
Очевидно тем, что между «классами» надо указывать and, контролировать порядок структур и остальные усложнения. Стокгольмский синдром во всей красе
ApeCoder
14.02.2017 08:16Вообще, как мне кажется, оператор new является признаком явного императивного подхода. Оператора new вообще не должно быть в ядре моделирования для определения объектов – объекты задаются декларативно. Существование объекта декларируется, а фактический способ создания будет уточняться позже. Более того, инстанцироваться может не сам объект, а прокси к удалённому объекту.
Для этого используются dependency injection containers
PalladaProject
14.02.2017 09:09+1Да, dependency injection containers помогают в данном случае. Однако, на мой взгляд, это частный случай более общего решения через аспекты. Более того, я думаю что аспекты (в том виде как они определены в АОП) недооценены и не раскрыли свой потенциал как концепция. Аспекты как механизм трансформации позволит из чистых моделей получать выходной код. Думаю уместней аспекты называть проекциями, т.к. они определяют разные точки зрения на проект, и dependency injection это лишь один из механизмов.
Nanako
18.02.2017 17:53Я сначала хотел было написать развернутый ответ, но потом все стер. Потому что в процессе написания понял одну совершено ясную для себя вещь: я бы застрелился на таком «языке» писать. И не кладите, пожалуйста, в одну корзину аспекты и DI. Они решают совершенно разные задачи. И то что для реализации DI приходится использовать dynamic proxies это наследство внутренней реализации C# и других языков. Когда вы действительно встретите проблемы которые для решения требуют использования DI или АОП вы сразу это поймете. А использование этих архитектур в «повседневных задачах» это программирование ради программирования — overengineering чистой воды.
lair
18.02.2017 19:15Мне вот прямо стало интересно, как вы так отделяете "повседневные задачи", что для них не нужен dependency injection? Потому что у меня вот "повседневные задачи" — то есть те, которые я решаю по работе каждый день — от использования DI выигрывают.
Nanako
20.02.2017 02:49Ну как-то я поскромничал, да. У нас большая часть кода: ехал Windsor через Windsor… Но многим разработчикам это ни к чему, особенно если тестирование игнорировать.
lair
20.02.2017 11:24Тут немедленно возникает разумный вопрос: почему вам и мне DI полезен, а многим разработчикам ни к чему, и почему можно игнорировать тестирование.
Nanako
21.02.2017 07:50Я вот с кучей сторонних библиотек работаю имея исходники и если честно такое ощущение что на тестирование многие просто забивают. Причем даже если есть свои юнит тесты, они лишь для coverage-попугаев. Наши стресс тесты вышибают кучу софта даже оттестированного в совершенно невероятных местах. При этом крупные проекты, вроде PTVS хорошо оттестированы и детскими их не назовешь, однако DI в них нет. Иногда т.к. обошлись без него, иногда зависимости тащить не хотят.
PalladaProject
19.02.2017 10:56я бы застрелился на таком «языке» писать
Согласен, это резонный довод. Но мой концепт исходит из того, что по отдельности ядро моделирования и язык трансформаций будут проще чем современные ООЯП, которые смешивают моделирование и императивную реализацию и тем самым вводят дополнительную эмерджентную сложность (сложность жёстких связей). Есть намерение построить proof-of-concept прототип чтобы убедиться, т.к. идея сложновата чтобы умозрительно её подтвердить или опровергнуть целиком. Может оказаться что вы и правы, а может и нет — расчёт на простоту каждого языка по отдельности имеет смысл. Если коротко: сложность слагаемых меньше сложности суммы из-за системного эффекта.
И не кладите, пожалуйста, в одну корзину аспекты и DI. Они решают совершенно разные задачи.
Не могли бы вы всё-таки пояснить этот пункт? Хотя бы в общих чертах. Я думаю что DI (и кстати говоря, паттерн "стратегия" например) может быть обобщён до аспектов, а аспекты обобщены до проекций — именно что они все подразумевают инжектирование внешних (по отношению к целевому) понятий в некоторый контекст.
lair
19.02.2017 13:21Я вот, если честно, так и не понял, что такое "проекция" как понятие, и почему это понятие более общее чем "аспект".
(а как вы обобщаете DI до аспектов/проекций, мне и вовсе непонятно).
PalladaProject
21.02.2017 06:33На мой взгляд, общее у аспектов, DI и паттерна "стратегия" (и не только у них) — это инжектирование некоторого функционала. Идея с таким обобщением основана на том, что инжектирование применительно к императивной парадигме — довольно универсальный мета-механизм. Суть императивного подхода — последовательность шагов, каждый шаг можно рассматривать как паттерн "шаблонный метод", и инжектировать пред/пост действия для него (шага). Т.е. на любую императивную последовательность я предлагаю смотреть как на "шаблонный метод", и каждый шаг можно перехватывать/трансформировать.
Исходя из такого предположения, возникают интересные вопросы. Например, почему в ООЯП методы (и не только) имеют только одно имя? Я думаю, что альтернативные имена для обозначения альтернативных "предназначений" метода (и вообще последовательности шагов) имеет смысл обозначать явно. Потому что нам приходится на методы смотреть с разных сторон. Primary имя — из предметной области, но ещё и имена для разных контекстов. Cross-cutting concerns — это проблема не только уровня классов/методов, я её вижу на уровне блока шагов, которые требуют пред/пост действий, напр. синхронизации.
Инжектиование, я думаю, есть тот универсальный механизм, который императивные модели преобразует в выходной код на обычном ООЯП. В моделях сообщения реализуются опять же на основе "шаблонного метода", я бы так и назвал "шаблонные сообщения" — крупные абстрактные шаги. Проекциями они превращаются в код, который бы мы написали руками (или который сейчас как-то частично генерируется DI/АОП).
Если совсем обобщить идею, то мета-возможностей в наших текущих инструментах не достаточно, на мой взгляд конечно. Кода пишется руками много больше, чем генеририруется. И дело не в генерации как самоцели, а в том что ООЯП заточены под программирование, с формальными грамматикой/синтаксисом/семантикой. Т.е. на ООЯП нужно по большому счёту всё-таки писать код. Я предлагаю код генерировать из шаблонных моделей.
Nanako
21.02.2017 07:46Кода пишется руками много больше, чем генеририруется.
У кого как. Из шаблонных моделей очень много кода генерируется для передачи данных, доступа к базам данных и т.д. Но это в крупных и очень крупных проектах. Причем для генерации используется все подряд: от UML до шаблонов T4, смотря что удобнее. И пользовательского кода иногда гораздо меньше чем сгенерированного, на порядки. А во вторых, я не могу понять почему вы называете но почему DI «инжектированием». И это не парадокс, как кажется на первый взгляд. DI это скорее о подмене или предоставлении альтернатив, о выборе подходящего инструмента для ситуации. А АОП это как раз об унифицированном расширении, подчастую «post-mortem».PalladaProject
22.02.2017 06:55У кого как. Из шаблонных моделей очень много кода генерируется для передачи данных, доступа к базам данных и т.д. Но это в крупных и очень крупных проектах. Причем для генерации используется все подряд: от UML до шаблонов T4, смотря что удобнее. И пользовательского кода иногда гораздо меньше чем сгенерированного, на порядки.
Согласен, именно так и происходит. Но вы говорите, я бы сказал, о рутинном коде и генерации "в большом". Генерация доступа и схемы БД, типовых сценариев в UI и пр. — да, всё генерируется. Но я предлагаю попробовать генерацию "в малом" — на уровне классов и методов. Вместо "писать код" я предлагаю "писать модели и трансформировать их" (это не реинкарнация MDD). Инструмент для этого должен быть такой же простой и мощный как напр. IntelliJ IDEA or VisualStudio. Общий подход не "вызвать код из фреймворка" а описать "абстракцию и спроецировать из неё код".
А во вторых, я не могу понять почему вы называете но почему DI «инжектированием». И это не парадокс, как кажется на первый взгляд. DI это скорее о подмене или предоставлении альтернатив, о выборе подходящего инструмента для ситуации. А АОП это как раз об унифицированном расширении, подчастую «post-mortem».
Я думаю что функционально DI эквивалентен проекциям/инъекциям. Результатом DI является система (приложение), сконфигуренная под определённый контекст выполнения с конкретным набором зависимостей. DI позволяет иметь альтернативы и варьировать их, как вы и сказали. Так проекции/инъекции делают тоже самое — позволяют иметь альтернативы и варьировать их. По той же причине аспекты из АОП я отнёс в эту же категорию.
Nanako
22.02.2017 08:19Это не будет работать как мне кажется.На уровне классов и методов даже если взять ТОЛЬКО C# у нас и MSIL, и CER, DI, unsafe и unchecked опционально, горы атрибутов (в том же ASP.NET). Как вы будете например thread-safe конечный автомат для хранения состояния «генерировать». С учетом например что родительский класс CriticalFinalizerObject и имеет некоторые контракты с unmanaged миром, ядро работатет в dispatcher потоке, а задачи на смену состояния приходят как делегаты (и надо еще gate организовать т.к. какие-то команды могут оказаться невалидны к моменту когда диспатчер до них дойдет). У меня например такой год генерируют Razor и T4 на основании шаблонов, интерфейсов компонентов и кучи другого барахла которое я вручную писал. Я если честно всегда был за то чтобы глубоко изучить и действительно научиться пользоваться теми инструментами которые уже существуют, чем городить свой переусложненный огород.
Результатом DI является система (приложение), сконфигуренная под определённый контекст выполнения с конкретным набором зависимостей.
Вы телегу впереди лошади поставили.
lair
21.02.2017 11:21На мой взгляд, общее у аспектов, DI и паттерна "стратегия" (и не только у них) — это инжектирование некоторого функционала. Идея с таким обобщением основана на том, что инжектирование применительно к императивной парадигме — довольно универсальный мета-механизм.
Есть маленький нюанс, состоящий в том, что аспекты, DI и стратегия находятся на разном уровне абстракции относительно контракта. Аспект — это нечто находящееся снаружи контракта, объект-под-аспектом и не в курсе, что к нему применяется такой аспект (я беру экстремальный случай, конечно), и аспект ничего не знает о внутренней реализации. С другой стороны, стратегия — это нечто, явно описанное в контракте, причем контракте абстракции, а не реализации (потому что контракт метода — это контракт абстракции), и поэтому и абстракция, и реализация знают о стратегии. Наконец, DI находится посередине, потому что он описан в контракте реализации, но в абстракции не упомянут (кроме случаев, когда это method injection, но это очень странный кейс). И опять-таки, реализация в этом случае про него явно знает.
Суть императивного подхода — последовательность шагов, каждый шаг можно рассматривать как паттерн "шаблонный метод", и инжектировать пред/пост действия для него (шага).
… и вот здесь возникает вопрос, к которому я еще вернусь: ваши инъекции описываются для модели или для… чего?
Например, почему в ООЯП методы (и не только) имеют только одно имя?
Потому что у них одна ответственность.
Я думаю, что альтернативные имена для обозначения альтернативных "предназначений" метода (и вообще последовательности шагов) имеет смысл обозначать явно.
Какого рода "альтернативные предназначения" могут быть у метода, и что делать с тем, что они нарушают SRP?
Инжектиование, я думаю, есть тот универсальный механизм, который императивные модели преобразует в выходной код на обычном ООЯП.
Вот-вот, возвращаемся к вопросу: что же это за императивные модели? Откуда они берутся? Чем они отличаются от обычного императивного кода?
Кода пишется руками много больше, чем генеририруется
Это утверждение в общем случае неверно: просто посмотрите, сколько кода генерируется, когда я пишу две строчки LINQ в .net: сначала IL, потом исполняемый машинный код для конкретной среды исполнения, потом SQL-код, который уходит на целевую БД… Разница в объемах будет как бы не на порядок. А если туда добавить маппинг на представление — то и больше.
Т.е. на ООЯП нужно по большому счёту всё-таки писать код. Я предлагаю код генерировать из шаблонных моделей.
То есть вы снова предлагаете MDD.
michael_vostrikov
21.02.2017 11:58Я думаю, что альтернативные имена для обозначения альтернативных "предназначений" метода (и вообще последовательности шагов) имеет смысл обозначать явно.
Ничто не мешает сделать так:
methodPrimaryName() {} methodAlternativeName() { methodPrimaryName(); }
Заодно и изменение проще будет, если в другом контексте потом понадобится дополнительные действия делать.
PalladaProject
22.02.2017 06:27Да, согласен, так можно сделать. Но тут два нюанса.
Во-первых, к любой обобщающей и специфичной конструкции можно привести эквивалентный код на языке общего назначения (GPL) в силу именно общего синтаксиса/семантики GPL. Тут просматривается дилемма DSL vs Frameworks. Всё можно предствить на GPL, но тем не менее для удобства не помешает иметь явные и специальные механизмы. Конечно если такие механизмы полезны.
Во-вторых, ваш пример, как мне кажется, показывает как раз современный подход к композиции через "вызовы", в стиле паттернов "декоратор" или "фасад". Я же предлагаю сместить акцент на проекции и инъекции, когда функционал не вызывает другой, а "мёрджится" с разных аспектов (т.е. точек зрения). На выходе по идее должен быть тот же результат в виде кода на GPL типа C#/Java.
michael_vostrikov
22.02.2017 07:18+1Можете какой-нибудь пример привести, как вы это представляете? Мол, вот модель, вот сгенерированный код, преимущества такие-то.
Nanako
20.02.2017 02:59Я различаю паттерны исключительно по типу задачи которую они решают. И тут АОП позволяет ковровой бомбардировкой расширить похожую логику во множестве методов, малой кровью обеспечить синхронизацию и т.д. Причем достигается это по большей части перекомпиляцией, так что это скорее хак и надстройка. DI же это парадигма для развязывания контракта сервиса и его имплементации. Для юнит тестирования, запуска плагинов, развязки версий пакетов и т.д., но все в рамках стандарта языка. Как то так, но это мое субъективное мнение, я вообще не увлекаюсь теорией: что текущую задачу позволяет решить эффективно, то в бой и идет.
lair
А это точно надо в языке программирования?
… и вот тут сразу появляется вопрос: а почему у ООП именно такая декомпозиция?
Вообще, конечно, критиковать парадигму, основываясь на языке, ее реализующем — не очень хорошо само по себе. Уж, казалось бы, программист-то должен отличать реализацию от абстракции. А во-вторых, программисты как раз неплохо знают первое и основное правило любой абстрактной модели — всякая абстракция течет.
Вот точно: зачем вам язык программирования? Возьмите язык моделирования, и описывайте все, что вам нужно, в нем.
Вау. Джаст, вау. Предложите, пожалуйста, четкий и непротиворечивый критерий разделения данных и объектов. А еще лучше — всех трех сущностей из вашего списка.
workjett
Возможно вы неверно поняли статью. Под языком моделирования имеется ввиду описательная часть языка (в противовес императивной), например Haskell в основном состоит из описательных (декларативных) конструкций, в этом смысле он скорее язык моделирования, на что и указывает автор.
Вообще странно почему подобные идеи вызывают сильную защитную реакцию? Это становятся очевидными после освоения Haskell и сопутствующей математики (лямбда-исчисление, теория категорий, общая алгебра). Там всё разложено по полочкам. Я конечно могу сильно ошибаться, но по моему дело не в ООП, а в том, что большинство разработчиков к сожалению не знают математику.
lair
ФП вообще намного более декларативно, чем ООП, это известная мулька. И на этом фоне возникает логичный вопрос: а точно ли надо делать язык программирования пригодным еще и для описания?
Какие "подобные"?
А теперь расскажите мне, пожалуйста, на какой математике основано моделирование в ООП.
PalladaProject
Суть идеи в том, что ООЯП смешивают объектное моделирование и императивную реализацию, а не в том какие альтернативы бывают и что для моделирования можно взять язык моделирования. Согласен, можно взять UML и что-то объектно спроектировать. Я лишь хочу сказать, что ООЯП имею такое вот "свойство", следствием которого являются практические проблемы.
Такая декомпозиция мне кажется достаточно абстрактной чтобы моделировать в терминах объектов. Здесь я не настаиваю на этом пункте, суть всё-таки в другом: отделить императивную реализацию от объектного моделирования, на каких бы элементах декомпозиции оно не основывалось.
Тем не менее абстракции это механизм борьбы со сложностью, без абстракций понять что-либо, только на уровне реализации, будет видимо невозможно. Но есть ещё нюанс, что абстракции текут именно потому, что те инструменты, которые мы имеем, не позволяют нам удобно ими (абстракциями) манипулировать.
Данные являются элементами модели данных, коллабораторы — объекты, прямо взаимодействующие между собой через обмен сообщениями. Данным нельзя послать сообщения, но их можно обрабатывать согласно модели данных (например реляционная). Состояние объектов есть тоже данные, но состояние (как данные) никак не проецируется в какое-то внешнее поведение типа свойств. Данные имеют смысл только в контексте модели данных, а объекты в контексте топологии коллабораторов, такая вот дуальность.
Вообще, принцип "всё есть объект" привёл к тому, что данные стали восприниматься как объекты, при этом от данных оторвалась вся семантика модели этих данных. Унифицированный подход на всё смотреть как на объекты не практичен, думаю это сверх-обобщение.
lair
А смешивают ли? Вы точно уверены, что в ООЯП происходит именно намеренное объектное моделирование, а не просто эмержентная модель?
Чтобы моделировать в терминах объектов, есть и другие декомпозиции. Почему эта, а не они?
Неа. Абстракции текут просто в силу разнообразия мира, который вы пытаетесь за эти абстракции запихнуть.
Круто. "Заказ" — это данные или коллаборатор? Учитывая, что заказ есть в модели данных, и я могу послать заказу сообщение.
А если я хочу послать одному коллаборатору другой коллаборатор (паттерн "стратегия"), он в виде чего будет передан?
А какая связь между "все есть объект" и "от данных оторвалась семантика"? По мне так наоборот, восприятие данных как объекта помогает увидеть доменную семантику этих данных.
PalladaProject
Вообще да, я уверен что введение в ООЯП среди прочих понятий классов и интерфейсов было заявкой именно на объектное моделирование в том числе. Но моя уверенность никак не влияет на жиснеспособность идеи. Я пытаюсь её как-то аргументированно обосновывать, а уверен/не уверен роли не играет.
Ответить тут можно только через уточнение вопроса: какие именно другие? Приведите, пожалуйста, пример, тогда можно будет их сравнивать по каким-то критериям, и увидеть какие у них преимущества/недостатки.
Выражусь иначе: абстракции в принципе изменчивы (да, в силу разнообразия мира), это их свойство. Но эту изменичивость можно попытаться отслеживать и приводить абстракции в соответствие с миром. Проблема всё таже: отсутствие ядра моделирования влечёт за собой и отсутствие надлежащих инструментов по управлению как раз моделями и абстракциями, в т.ч. и по их поддержанию в актуальном состоянии.
Заказ — это понятие, которое проецируется либо в модель данных, либо в коллаборатор в зависимости от контекста. Я исхожу из того что если принять ядро моделирования, то в нём возможна вот такая дуальность. Суть в том, чтобы с одного понятия можно было генерировать разные предствления для определённых контекстов. Это довольно странная конструкция, и её нужно конечно ещё проверять.
Я думаю что паттерн "стратегия" (и не только его) в Вашем примере нужно обобщить до проекций, как частный случай аспектов. Паттерны проектирования определены в контексте современных ООЯП, которые имеют (с моей точки зрения) вышеобозначенные проблемы, и соответственно их (паттернов) применимость в рамках чистых моделей может оказаться неприемлемой. Там просто возникают паттерны видимо иного рода. Разумеется в современных ООЯП паттерны абсолютно пригодны.
Да, тут нет причинной связи "всё есть объект" и отсутствие явной модели данных в ООЯП. Я имел ввиду что "всё есть объект" никак не помогает в определении модели данных. Могу предположить что помогает Вам не восприятие данных как объектов, а выражение ассоциаций между понятиями через поля или свойства навигации (navigation properties) в какой-нибудь ORM, опять же посредством синтаксиса классов и соглашений для сущностей (entities). В ядре моделирования нужно иметь такую абстракцию как ассоциации, с которых можно было бы генерировать любые реализации, напр. поля данных, схемы баз данных, DTO и классы для сущностей ORM, свойства навигации в виде связей PK/FK или структур данных типа списков и пр.
lair
Неа, это было заявкой на управление сложностью кода. Интерфейс — это всего лишь контракт, позволяющий отделить абстракцию от реализации.
Для того, чтобы обсуждать жизнеспособность идеи, надо понять, какую проблему вы пытаетесь решить. И вот тут-то мы и не можем найти общего языка.
Объекты и сообщения. Объекты и отношения. Объекты, свойства и методы. Значения, сущности, агрегаты и сервисы.
Абстракция, приведенная в полное соответствие с миром, перестает быть абстракцией. И именно поэтому они и текут.
Проецируется откуда? У вас где-то должно быть одно нечто, которое вы будете проецировать.
Оу, теперь кроме коллабораторов, данных и сообщений у вас появились еще и контексты. И исходные понятия. И мы еще не закончили. Видите, как разрастается ваше "ядро моделирования"? Шаг за шагом — придете к UML или какому-нибудь аналогу/противнику.
Я не вижу, каким образом паттерн "стратегия" — частный случай аспекта. Но не суть, не важно, какой паттерн. Важно, что я хочу передать один коллаборатор другому — в виде чего он передается?
Но и не мешает.
Неа. Когда я строю модель данных в терминах сущностей и отношений, у меня нет ни ORM, ни полей, ни навигационных свойств. У меня есть объекты и их связи.
Ну вот видите, вот ваше "ядро" и еще одной сущностью пополнилось.
Понимаете, вы говорите "ядро моделирования" — и я читаю за этим "а вся реализация — она снаружи ядра", — но требуемая вами от него функциональность уже намного больше, чем понятия и возможности синтаксиса языка программирования. И именно поэтому я считаю, что ваша идея, на самом деле, реализуется через отдельные средства моделирования и отдельные средства реализации (пусть и связанные), а не один "объектно-ориентированный язык программирования", в котором одновременно будет и инструментарий моделирования — очень громоздкий, — и инструментарий разработки — тоже немаленький.
PalladaProject
Так ваш аргумент не противоречит моему, а мой вашему. ООП как парадигма призвана помогать бороться со сложностью. Очень многие конструкции в языках существуют именно по причине управления сложностью кода. В ассемблере ввели мнемонические имена команд вместо кодов, в C переменные добавили чтобы не возиться со смещениями косвенной адресации и процедуры с именами вместо адресов переходов, в C++ добавили классы, шаблоны и пр. в рамках определённых парадигм. Под всеми этими конструкциями ваш аргумент справедлив из-за своей общности. Но опять же, если взять что-то конкретное, то оно тоже будет верным.
Проблема в смешивании объектного моделирования и императивной реализации. Некоторые из симптомов проблемы я указал в статье, но есть и другие. Вопрос возник что в ООЯП не задумано моделирование как явный механизм — по этому пункту расхождение, по-моему.
Я не пытаюсь менять существующие ООЯП, а лишь считаю что у них есть вышеобозначенная проблема. Её решение я вижу в новом инструменте, состоящего из двух частей: язык объектного моделирования (ядро) и механизм трансформаций моделей. Последний может быть мета-языком или IDE, и включает императивную реализацию. Решение находится между ООЯП и UML, не в смысле синтаксиса, а совместить более-менее чистые модели с императивной реализацией.
Под ядром я имею в виду как оно будет в этом новом инструменте, опять же, не предлагаю это всё впихнуть в ООЯП. В ядре конечное число понятий, причём некоторые из них включают другие и по сути корневых понятий ещё меньше: объект, сообщение, коллаборатор, абстракция, рутина, состояние, данные, ассоциация, коллекция, переменная, тэг. Терминология конечно знакомая, но смысл предполагается абстрактный.
Согласен, что инструментарий будет, возможно, немаленький, но сложность инструмента думаю необходимое условие в повышении удобства работы с понятиями и абстракциями.
В общем согласен с вами, собственно это и есть решение проблемы. Только ядро никак не будет сложнее ООЯП. Список понятий ядра выше — это по сути всё что должно быть. Эта простота вытекает из абстрактности понятий, без какой-либо императивной конкретики (и ресурсной кстати тоже).
Частично совпадает со всеми перечисленными:
Объект — абстракное понятие с поведением в виде интерфейса сообщений.
Коллабораторы — взаимодействующие объекты, имеющие прямые связи друг с другом. Образуют потологию для проецирования в реальные структуры хостинга. Это всё те же объекты, только акцентрируется их связность.
Сообщения — абстрактный механизм коммуникации объектов.
Данные — определяются моделью данных. Состояние объекта — это данные. Состояние отделено от поведения (интерфейса сообщений).
Более внятного определения пока не вижу, да. А где-то можно узнать как авторы этих декомпозиций ответили бы на ваш вопрос "почему именно такая?"
Коллаборатор в моём концепте — это связь объекта с другими объектами. Понятия представляются только объектами, некотрые объекты яляются коллабораторами другим объектам.
Вопрос "в виде чего передаётся" в ядре не возникает в принципе. Абстрактное понятие параметра и аргумента — это всё что есть. Т.е. "объект А является аргументом сообщения объекта Б" — это всё что можно утверждать. Как имено будет передаваться — это уже зависит от того а как будут представлены объекты. Тогда агрумент будет передан через стек либо сериализован для удалённого вызова, и т.д.
Но суть даже не в этом. Многие вопросы просто отпадают в контексте абстрактых моделей. Как передаются аргументы в сообщения, как создаётся объект и пр. — это всё следствие императивной составляющей, без которой мы никуда сейчас. По большому счёту это всё речь о ресурсах.
lair
Любая парадигма программирования призвана бороться со сложностью. Собственно, управление сложностью — это основная и самая сложная задача программиста.
Ну вот видите. А если кто-то эти конструкции использует не для тех задач, для которых они были введены, то чья это вина?
… которое, как мы только что выяснили, возникает из-за того, что люди используют для моделирования то, что для него не предназначено.
Таким образом, вы не решаете проблему языка программирования — в нем все остается как было. Вы просто создаете другой инструмент сбоку.
Это уже очень много.
Посмотрите на список выше — он сложнее чем набор концепций ООП.
… или нет. Повышения удобства еще не доказано, а вот увеличение сложности уже очевидно.
Авторы этих декомпозиций нигде не говорили, что это единственная декомпозиция, которую надо использовать.
Вот в этом и проблема. Я, впрочем, сразу об этом написал.
То есть все-таки "все есть объект"? (потому что, очевидно, "все есть понятие")
… и нет разницы между передачей данных и объектов? Или, говоря иначе, передачей по ссылке и по значению?
И это очередная демонстрация того, что ваша абстракция, как и любая другая, будет течь. Потому что вопрос "мы передали объект или копию объекта" — он настолько же фундаментален, как разделение сущностей и значений.
PalladaProject
Согласен с вами, и опять же из-за общности вашего аргумента. Я не говорил что только ООП призвана бороться со сложностью.
Так вы говорите о том же самом о чём и я, но почему-то это выглятит как противоречие. Введение классов и интерфейсов — это борьба со сложностью, классы и интерфейсы это механизм по борьбе со сложностью именно объектного подхода. Но вы видите в них более общее понятие (борьба со сложностью, разделение контрактов от реализации), я же вижу в классах и интерфейсах именно ООП как один из способов борьбы со сожностью. Одно является частным случаем другого, но никак не противоречие.
В вашем вопросе в части об использовании для не тех задач, уже неявно подразумевается утвердительный ответ, с чем я не согласен. Если размотать этот топик вверх по обсуждению, отсутствие намеренности объектного моделирования в ООЯП объясняется обобщением ООП до борьбы со сожностью, что есть одно и тоже. Мне кажется, ненамеренность (т.е. эмерджентность) не доказана. Такая мелочь: сами авторы называют языки объекто-ориентрованными. Но вы видите в этом борьбу со сложностью, и ведь вы правы.
Так и не было задачи решать проблемы ООЯП в рамках самих ООЯП, это был один из базовых тезисов статьи. Более того, я считаю что некоторые важные проблемы в принципе не могут быть решены в рамках самих ООЯП, и опять по причине жёсткой связи моделирование/императивная реализация.
Тот список — это понятия ядра, а не концепции декопозиции. Ядро это язык моделирования, и этот список это элементы его грамматики, и его нужно сравнивать с грамматикой например Java как ООЯП.
Концепции это то, что вы уже упоминали: коллабораторы, сообщения, данные. Вот их можно (и нужно) сравнивать с концепциями ООП.
Вообще-то я тоже не говорил что мой вариант декомпозиции единственный. В статье он используется как простое утверждение. В моём первом комментарии я говорил о достаточности для выбора в его пользу, но ваш вопрос почему-то исходит уже из необходимости моей декомпозиции: раз она необходима (т.е. требуется), значит все остальные отменяются. Нет, всё проще: мой вариант декомпозиции просто достаточен чтобы на нём построить концепт ядра объектного моделирования.
Тут нет проблемы по теме, мне кажется это размывание обсуждения. Честно сказать, довольно трудно контр-аргументировать аргументы к обобщению, аргументы к существованию, к необходимости/достаточности и пр. К тому же, я местами криво формулирую мысли, что есть то есть.
Я стараюсь формулировать мысли по абзацам, одна мысль — один абзац. Просто чтобы не размывать тему, было бы замечательно критиковать абзац целиком (по возможности конечно), иначе топики дрейфуют местами в противоположных направлениях.
Нет, не всё есть объект: как минимум данные не есть объект. "Понятие" я употребил в смысле понятие предметной области, "заказ" в логистике например. Данные и объект это термины из моей концепции декомпозиции. "Заказ" будет объектом, или данными, или и тем и другим — это уже зависит от дизайна.
Я считаю, что "всё есть объект" это сверх-обощение, и данные должны проходить явным понятием в объектных концепциях. Простите за аналогию, но в ФП ключевая роль у отображений (т.е. функций), тем не менее данные там тоже есть.
Off-topic: интересно, как в современных концепциях ООП соотносится "всё есть объект" и упоминание в этих же концепциях понятия "сообщение", сообщение тоже объект? Какой-то парадокс Рассела в аксиоматике ООП :)
Именно, нет разницы между передачей данных и объектов, а точне в рамках моделирования нет смысла различать этот механизм для объектов и данных. Это абстрактный механизм. Говоря о передаче по ссылке или по значению — это чисто императиный подход, а точнее ресурсный что по сути одно и тоже — на уровне абстрактных моделей такие вещи просто не возникают.
lair
Упс, нет. Почему?
Ну так доказывают наличие, а не отсутствие. Поэтому и за отсутствием доказательства явных средств моделирования в ООЯП будем считать, что их там нет.
Тогда вы не решите проблемы. Более того, в вашем решении эта проблема сохранится — потому что в используемом вами ООЯП, не важно, существующем, или новом, будут все те же возможности, которыми сейчас пользуются люди.
И в момент, когда вы построите на вашем варианте ядро, этот вариант станет — в рамках этого ядра — единственным.
То есть в конкретной модели, построенной для решения конкретной прикладной задачи, "заказ" будет или объектом, или данными?
В современных концепциях ООП "все есть объект" рассматривается как недостижимый из практических соображений идеал. В рамках этого идеала сообщение — тоже объект.
Я боюсь, у нас с вами слишком разные представления о необходимом уровне абстракции. В частности, в моем представлении об описании взаимодействия между объектами необходимо знать, если объект А передал объекту Б объект Ц, а затем изменил объект Ц, изменится ли состояние объекта Ц, которым владеет объект Б.
PalladaProject
Согласен, доказывают наличие, но ваш вывод тоже некорректен — это будет аргумент к незнанию.
Попробую привести доказательство намеренности моделирования в ООЯП, мне кажется оно довольно простое. Сами авторы ООЯП добавляют классы и интерфейсы под лозунгом поддержки объектного подхода. Когда описывается семантика ООЯП касательно объектной парадигмы — в этом контексте как раз упоминаются классы и интерфейсы, и похоже ни в каком другом контексте ООЯП классы и интерфейсы не упоминаются. Почему именно классы и интерфейсы выбраны в качестве конструкций реализации концепций ООП — это отдельный вопрос, но именно классы и интерфейсы предназначены для представления domain problem, что и есть на мой взгляд заявка на моделирование. И по причине заявлений самих авторов ООЯП — "чтобы разработчики могли сконцентрироваться на решении прикладных задач".
Думаю, я понял ваш контр-агрумент по этому пункту, попробую его сформулировать чтобы убедиться что действительно понял его. В ООЯП решается главная проблема борьбы со сложностью через реализацию среди прочих обобщённого подхода разделения контрактов и реализации. Преследование этих целей привело к тому, что в ООЯП стало просматриваться некоторое соответствие "идеалистическим" концепциям ООП, т.е. конструкции классов, интерфейсов и методов стали рассматриваться как частный случай реализации понятий объектов, поведения и сообщений из ООП. Объектное моделирование явно не задумывалось. Верна ли такая формулировка?
Идея не в том, чтобы создавать ещё один ООЯП, а два языка: язык моделирования (ядро) и условно язык трансформаций (который может быть формальным языком с грамматикой, так и в виде инструментов типа IDE). Каждый из этих двоих по отдельности должен быть проще чем один ООЯП. Язык трансформаций обеспечевает в том числе и императивную реализацию, и в моём прототипе таким языком может выступать даже чисто процедурный язык типа С. Суть статьи именно в этом: ООЯП жёстко вяжут понятия и конструкции из моделирования и императивной реализации, что приводит к усложнению самого ООЯП. Причём эти усложнения уже не замечают, принимают как данность, в лучшем случае предлагают решения в рамках самих ООЯП.
Либо объектом либо данными зависит от более узкого контекста, напр. в стейменте "послать сообщение" — это объект, в выражении доступа к состоянию — это данные.
Думаю, у вас более "программисткий" взгляд, а у меня более "модельный" (в контексте которого многие понятия отсутствуют т.к. перенесены в язык трансформаций (см. выше)). Ваши вопросы в данном пункте абсолютно понятны и практичны. Но хотелось бы вытянуть тему именно в модельную плоскость.
Почему, собственно, возникает такой вопрос что будет с состоянием объекта Ц в вашем примере? Потому что вы неявно предполагаете, что объект передаётся либо по ссылке либо зо значению. Ваш вопрос неявно предполагает что объекту Ц выделена какая-то память т.е. ресурс — тогда вопрос корректен: объекты А и Б будут видеть объект Ц как один и тот же кусок памяти (Ц был передан по ссылке), либо это будут два разных куска памяти (Ц был передан по значению).
Но суть, мне кажется, в другом, а именно в идентичности — объекты А и Б что-то делают с объектом Ц, т.е. они оперируют одним и тем же объктом. На модельном уровне по идее должен быть только абстракный механиз идентичности. Но уровень императивной реализации, и в частности выделение памяти как ресурсов, добавляет вот эту сложность о которой я говорил: ссылки (или указатели) добавили ещё один нюанс — эквивалентность по ссылке. Равенство ссылок и идентичность объектов — популярная тема. Т.о. ваш пример подразумевает наличие ресурсов и добавляет один нюанс эквивалентности — что абсолютно верно на практике. Я предлагаю лишь локализовать эти две вещи в ядре и языке трансформаций.
lair
Неа, это будет использование бритвы Оккама.
… объектного подхода к программированию.
… объектной парадигмы программирования.
Интерфейсы упоминаются в контексте design-by-contract. Классы упоминаются в контексте повторного использования кода и строгой типизации.
Э? Нет. Объекты предназначены для представления domain problem.
Нет. Представление домена — это не обязательно моделирование, это еще и может быть реализация.
В рамках моего понимания — да.
В этот момент вы уходите от программирования и приходите к model-driven development. Это уже пробовали, и оно не взлетело.
Не выйдет. Язык трансформации должен содержать все целевые концепции.
Эм. У меня есть модель. В модели это объект или данные? Если и то, и другое, то как между ними обеспечивается связь?
Не в идентичности, а в состоянии. Идентичные объекты имеют разное состояние, один и тот же объект имеет (логично) одно состояние, и так далее и далее.
Да нет никакой императивной реализации, есть модель, в которой есть два стейкхолдера, имеющих информацию об одном и том же (бизнес-)объекте. И мы должно точно понимать, если эта информация между ними разделена, то процессов ее передачи и согласования — нет, а если эта информация у каждого своя, то эти процессы должны быть. И это сугубо бизнес, никакой реализации.
PalladaProject
Правильно ли я понимаю, что если бы мне удалось привести убедительные (для вас) аргументы что объектное моделирование намеренно присутствует в ООЯП, то вы бы перестали рассматривать это как избыточную сущность? Бритва Оккама слегка поставила под сомнение необходимость моего позитивного доказательства данного утверждения, если честно.
У меня кончились аргументы :) Оставлю этот пункт открытым, всё-таки считаю что в общей картине он верен, хотя вот вы не согнасны с ним как независимая идея.
Я имел в виду классы как конструкции для поддержки ООП в ООЯП. Согласен что объекты представляют domain problem. Я уже оговаривался что почему именно классы, когда ООП бывает и без классов (напр. JavaScript).
Да, MDD не пошёл. Я пытаюсь учесть это, и предлагаю не такую глобальную идею, как MDD или UML. Всё что предлагается — это по сути приложение технических подходов к самому языку, о которых мы уже упоминали. Например, отрицание принципа "всё есть объект" можно пояснить как неправильная иерархия отношения "является" (is a) с одним корнем. С моей точки зрения дополнительным корневым понятием должны быть данные.
Думаю что выйдет: язык трансформации должен позволять манипулировать моделями и в этом его смысл. Т.е. domain для него — это модели, а сам он — это уже мета уровень. Язык трансформаций должен позволять модель превратить в исходный код, привязывая ресурсы (а ресурсы это память и алгоритмы) к моделям. Чесно скажу что не уверен насколько простой (или сложной) будет семантика такого языка, но сейчас на этапе дизайна прототипа надеюсь на положительный исход.
Связи нет по причине того, что объект и данные это разные аспекты (не в смысле АОП) одного и того же понятия. Объект это контракт понятия, данные — это его аттрибуты в рамках модели данных (реляционной).
Этот пункт тоже оставлю открытым, т.е. пока без ответа. Всё-таки вижу в нём вашу и мою точки, но на разном уровне проекта. Как бы не оказалось, что мы с вами говорим об одном и том же.
michael_vostrikov
То есть в ядре моделирования смоделировать процесс чего-либо нельзя? Только сразу реализовывать на мета-уровне?
PalladaProject
В ядре моделирования происходит именно моделирование, т.е. абстрактное описание предметной области в рамках выбранного механизма декопозиции. Насколько абстракнта модель — это зависит от разработчика, модель можно описать по "шаблонному методу" с любой детальностью шагов. А язык трансформаций преобразует модели в выходной код (выходной по отношению к моделям и процессу трансформации, но сейчас бы мы назвали это исходный код напр. на C#).
Язык трансформаций я назвал мета-языком потому, что он оперирует исходным кодом на языке моделирования ядра. Поэтому реализация в нашем обычном понимании присутствует и в моделях (шаблонные сообщения), и в языке трансформаций (в виде алгоритмов и ресурсов).
michael_vostrikov
Ну вот допустим мы смоделировали процесс оформления заказа:
Чем это отличается от обычного исходного кода?
PalladaProject
По идее это отличается семантикой. Ваш пример демонстрирует только синтаксис. А какая семантика этого кода? Если это код на C# или Java, то семантика конкретна согласно грамматике C# или Java, всё однозначно, объекты, вызовы методов, стейтмент if-else. Если это модель, то что скрывается за этим синтаксисом может быть не известным, т.к. это уже абстракные конструкции, семантика и реализация которых должна определяться трансформациями в конкретный код.
Семантика это принципиальный момент. В моделях она менее чёткая и более абстрактная для того чтобы упростить понимание моделей. К тому же, абстрактность/конкретность моделей может быть разной, степень детальности зависит от дизайна. Вся сложность реализации добавится через трансформации.
michael_vostrikov
Семантика появляется в модели. Если трансформация поменяла семантику, значит это плохая трансформация.
Реализация и так определяется трансформацией в конкретный код. Процессор не выполняет конструкции if-else, он выполняет инструкции машинного языка. Один и тот же код может быть преобразован в разные наборы инструкций. Это кстати одна из причин появления языка C.
lair
Стоп-стоп, нет. Семантика определяется моделью, иначе эта модель не имеет смысла.
(вот реализация действительно может отличаться, что да, то да)
lair
Рассматривать что? Я несколько потерялся.
Класс — это (одна) из конструкций для реализации ООП в ЯП, но она не предназначена для представления домена. Нельзя проглатывать шаги.
А чем ваша идея менее глобальна?
"Все есть данные"?
Если нет связи, то как поддерживать консистентность?
Но атрибуты — это неотъемлимая часть контракта.
Исходный код на каком языке?
lair
А главное, что те самые механизмы, о которых вы говорите выше (интерфейсы, контракты, сообщения) — они действуют на каждом уровне разработки. У меня есть инфраструктурный уровень, где у меня живут обработчики, http-сообщения, очереди, конвееры и так далее, и где вопрос ресурсов в модели критичен, и у меня есть уровень бизнеса, где живут доменные сервисы, доменные сущности и тому подобное, и им вопрос ресурсов в модели не важен — но когда я использую термины ОО-языка, я использую их на обоих уровнях одинаково. А вот как жить вашему языку моделирования?
PalladaProject
И опять согласен с вами, сейчас на практике имеем именно это. Но ведь такое положение вещей основано на текущих подходах и инструментах, которые не без изъяна (опять же на мой взгляд). Современные ООЯП прямо или косвенно, но влияют на методы их использования и соответственно на процесс разработки в целом. Моя идея в том, чтобы предложить новый (альтернативный, а не исключающий) инструмент и тогда уровневая организация может замениться на, например, проекционную (про проекции отвечу в вашем вопросе ниже в коментариях).
lair
А что плохого в этом положении вещей?
Чтобы проецировать, нужно иметь некую точку для старта. Чтобы вы могли сделать проекцию всех уровней, вам нужно иметь информацию об этом — значит, вам нужно иметь способ выражения для каждого уровня.