Здравствуйте коллеги!
Хотелось бы поделиться мыслями об ООЯП и ООП в целом, а также что можно (и, как мне кажется, нужно) сделать на этой основе.
Основные идеи: В современных ООЯП отсутствует чётко выделенное и обязательное ядро моделирования для создания абстракций, основанных только на "чистых" концепциях ООП. Концепция ООП "всё есть объект" не практична. Концепция обмена сообщениями жёстко связана с её реализацией.
Под объектно-ориентированными языками программирования (ООЯП) понимаются Java и C#, хотя к другим ООЯП данная тема тоже может иметь отношение.
Я не пытаюсь начать очередную дискуссию о проблемах ООП или ООП vs ФП. Цель статьи – посмотреть на ООЯП и вообще языки программирования, и показать, что у языков есть свойства, которые могут быть полезными и для ООЯП. Современные ООЯП в той или иной мере доказали свою жизнеспособность, а результатом решения данного вопроса был бы новый язык.
Практически всё, о чём пойдёт речь, так или иначе уже используется на практике, но хотелось бы, чтобы это было частью языка, хотя бы как альтернатива. Но такой альтернативы в настоящее время, похоже, просто нет.
На мой взгляд, в ООЯП отсутствует обязательная часть – ядро моделирования, на котором можно декларативно и очень абстрактно описывать предметную область, основываясь только на чистых концепциях моделирования, в данном случае – на элементах декомпозиции ООП (коллабораторы, сообщения, данные).
В качестве примера языка, в котором есть такое ядро моделирования, можно привести Haskell: грязные функции ввода/вывода требуют специального синтаксиса и взаимодействуют с чистыми функциями через чёткий протокол. Чистые функции позволяют довольно абстрактно моделировать предметную область, основываясь на функциональном подходе. (Хотя даже в функциональных языках иногда приходится учитывать реализацию, как пример – использование хвостовой рекурсии и её оптимизация транслятором).
Причина, почему чисто функциональный язык имеет такое ядро, думаю, очевидна: функциональный подход по определению основан на абстрактной математической теории (лямбда исчисление). Причины же появления ООП, на мой взгляд, чисто практические и прикладные, поэтому в ООЯП так выпукло просматривается императивный фундамент.
Ядро моделирования ООЯП должно основываться только на элементах декомпозиции ООП. Синтаксис ядра моделирования должен быть очень простой, декларативный и абстрактный. Ничего, кроме определения "топологии" объектов/коллабораторов (кто с кем взаимодействует), семантики/имён сообщений и их параметров/возвращаемых значений в ядре моделирования быть не должно. Использование такого языка возможно только начиная с ядра моделирования, преобразуя затем модели в выходной код.
Из-за того, что в ООЯП смешаны конструкции как для описания объектов (классы, интерфейсы, методы и т.д.), так и для реализации императивного подхода, в ООЯП по сути заложено фундаментальное противоречие: одновременно нужно писать и абстрактные модели, и их конкретную императивную реализацию. Это противоречие и является, на мой взгляд, причиной ключевых пунктов критики ООП.
Помимо обеспечения императивного подхода, использование ресурсов в ООЯП также не отделено от абстрактных моделей. Ресурсами являются память и алгоритмы (в смысле последовательность инструкций). На мой взгляд, память и алгоритмы как ресурсы нужно привязывать к абстрактным моделям. В моделях императивность должна быть представлена крупными ключевыми шагами, основываясь на паттерне "шаблонный метод". Далее шаги из моделей преобразуются в фактический выходной код.
Вообще, как мне кажется, оператор new
является признаком явного императивного подхода. Оператора new
вообще не должно быть в ядре моделирования для определения объектов – объекты задаются декларативно. Существование объекта декларируется, а фактический способ создания будет уточняться позже. Более того, инстанцироваться может не сам объект, а прокси к удалённому объекту.
Другим примером проблемы является реализация самой концепции обмена сообщениями. Обмен сообщениями, как абстрактная концепция, в ООЯП жёстко задаётся языком и представлен в виде вызовов методов. Обмен сообщениями должен оставаться абстрактным в ядре моделирования и позже проецироваться в конкретный механизм обмена сообщениями, например, вызовы методов или проецироваться в какую-нибудь топологию распределённых акторов.
Ещё одна проблема, которая связана с отсутствием ядра моделирования, это null значение. Тут, по-моему, самая жуткая смесь. Значением null в ООЯП обозначают разные вещи, отсюда все проблемы. Допустим, что чистое ООП это способ моделирования, отдельно стоят императивная реализация и ресурсы, и ещё есть модель данных. Тогда суть проблемы в том, что любой объект требует ресурса "память" (что есть признак императивной реализации) и null значение из императивной реализации присутствует во всех контекстах. Модель данных сама по себе допускает null значение, но с этими null значениями меньше проблем, т.к. они ожидаемы и связанны с данными. В ядре моделирования null значения для объектов должны отсутствовать по определению, хотя null значения из модели данных допустимы.
Несколько слов о самих концепциях ООП. На мой взгляд, концепция "всё есть объект" не практична, хотя выглядит, конечно, очень логично. Думаю, практика всё-таки требует, что данные не сводятся к объектам, и основные понятия ООП я бы определил как сообщения/коллабораторы/данные. Модель данных (например, реляционная) должна быть в явном виде. Моделирование предметной области заключается в представлении её в виде группы объектов (коллабораторов), которые обмениваются сообщениями. Аргументами сообщений являются данные. Это и есть основа ядра моделирования. "Всё есть объект" – это сверх-обобщение, когда теряется важная специфика базовых понятий, и они начинают выглядеть одинаково, хотя фундаментально их нужно различать.
Заключение
ООП – это способ моделирования (декомпозиция и определение абстракций), его нужно отделять от императивной реализации, управления ресурсами и модели данных. Современные ООЯП смешивают все эти понятия, и проблема решается за рамками языков, через применение принципов проектирования, паттернов, идиом, соглашений и пр.
Альтернативное решение мне видится в новом языке, построенном по аналогии с функциональными языками. "По аналогии" означает, что у нового языка будет такое же свойство, как и у функциональных: чистое и обязательное ядро моделирования.
В качестве примера похожей идеи приведу проект объектно-ориентированно языка eolang Егора Бугаенко. (Это не реклама Егора и его проекта, на момент написания статьи я не знаком с Егором лично, не имел с ним ни чатов, ни переписки, не являюсь контрибютором его проектов). То, что происходит в рамках проекта eolang, в целом поддерживаю, хотя в деталях очень много вопросов и несогласий. Тем не менее, в eolang происходит на мой взгляд то, о чём шла речь выше: из Java убрали целый набор императивных и процедурных конструкций и механизмов. Как раз удаление императивных и процедурных элементов и есть попытка выделить чистое ядро моделирования ООП.
Автор: PalladaProject