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

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

>> Такой подход обычно гораздо лучше воспринимается на консервативных рынках, а именно таким рынком, на мой взгляд, и является рынок разработки информационных систем

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

Во-первых — маркетинг, нам самим будет проще заходить на новые / существующие рынки с готовыми / custom-made бизнес-решениями, когда есть комьюнити платформы, на которой построены эти решения. Это снимает опасения вендор-локов, дает много дополнительных лидов и т.п.

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

Мне кажется, что это очень дорого стоит, вряд ли потянете

Все относительно. Понятно, когда вы выводите на рынок еще один клон продукта, вам нужен огромный бюджет на маркетинг. Но если вы выводите что-то принципиально новое, да и еще на рынке (скажем ERP-платформ и продвинутых СУБД) где все стоит очень дорого, а вы предлагаете open-source, то в конечном итоге все может быть не настолько дорого. Но жизнь покажет.
>> возможно, сделаем ultimate edition, облачную версию, ну и…

Версию чего? Язык, вроде, облачным не бывает. Платформы? Но это для разработчиков — рынок мал. А вот если готового приложения, тогда понятно, но вы ведь про язык, ну и что-то про платформу, но не про продукт типа ERP.

>> несколько статей в стиле: «Почему не ...?»

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

Вообще, грамотные специалисты привыкли излагать грамотно, но так они слона никогда не продадут, вот в чём проблема. Нужно «по быстрому», бодренько, с анекдотами, что бы пипл хавал с удовольствием, что бы был драйв, фан и прочее у.г. В итоге имеем массовость для дебилов, а потом удивляемся отсутствию качества, плачемся об отсутствии профессионализма и т.д. и т.п. Но по другому нельзя, если нужна массовость. Хотя когда-то профессиональную массовость умели получать при помощи усилий государства по обучению граждан…
Версию чего? Язык, вроде, облачным не бывает. Платформы? Но это для разработчиков — рынок мал. А вот если готового приложения, тогда понятно, но вы ведь про язык, ну и что-то про платформу, но не про продукт типа ERP.


Рынок разработки как минимум включает в себя рынок СУБД и ERP (причем что касается ERP там основная стоимость в платформах, а не в решениях, посмотрите например политику лицензирования 1С). А это на секунду Oracle + Microsoft + SAP (а у них и 10% не факт что на всех есть). Не говоря уже о «мелочевке» типа 1С, MongoDB и т.п. Вообще объем этого рынка где-то триллионов 5 долларов.

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

Вообще, грамотные специалисты привыкли излагать грамотно, но так они слона никогда не продадут, вот в чём проблема. Нужно «по быстрому», бодренько, с анекдотами, что бы пипл хавал с удовольствием, что бы был драйв, фан и прочее у.г. В итоге имеем массовость для дебилов, а потом удивляемся отсутствию качества, плачемся об отсутствии профессионализма и т.д. и т.п. Но по другому нельзя, если нужна массовость. Хотя когда-то профессиональную массовость умели получать при помощи усилий государства по обучению граждан…

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

Про выбор платформы тоже не понял. IT вообще меняется достаточно с быстрой скоростью, MongoDB за 10 лет стала многомиллиардной компанией, массовый переход в веб начался лет 10 назад. Да че уж там SQL массово начал применяться лет 20 назад максимум. И это я еще про всякие React'ы молчу. Хотя да, до сих пор есть кучу систем на COBOL написанных, только что это меняет.
Рынок разработки как минимум включает в себя рынок СУБД и ERP

То есть вы одним продуктом одновременно целитесь на два совершенно разных рынка?

Вы первую статью (а точнее ее заключение) я так понимаю не читали :)

Но вообщем да. Понятно, что про рынок СУБД не очень очевидно, но я сейчас допишу статью Почему не SQL, и там будет лучше понятно почему мы целимся и в рынок СУБД (если совсем вкратце то lsFusion решает и кучу задач СУБД, которые они не решают / решают в частных случаях или которые решают только Oracle MSSQL но не решают Postgres / MySQL)

PS: Картинка в первой статье была выбрана не случайно ;-)
Но вообщем да.

Весьма амбициозная заявка, учитывая, что вашей системе для работы нужна РСУБД.


Картинка в первой статье была выбрана не случайн

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

Весьма амбициозная заявка, учитывая, что вашей системе для работы нужна РСУБД

А для работы программ нужен компьютер. Какая по большому счету конечному пользователю СУБД разница что там внутри: РСУБД, файлы или еще что-то.
Я надеюсь, вы помните, чем история закончилась.

Ну так это же художественное произведение. А в жизни все заканчивается далеко не всегда так как в фильмах / книжках. :)
Какая по большому счету конечному пользователю СУБД

Конечному пользователю — никакой. Но рынок СУБД ориентирован не на конечных пользователей, а на разработчиков, а вот им разница очень большая.


Ну так это же художественное произведение.

One ring to rule them all — тоже.

>> Рынок разработки как минимум включает в себя рынок СУБД и ERP

То есть вы говорите о потенциально возможной расширенной версии платформы. Понятно.

>> причем что касается ERP там основная стоимость в платформах, а не в решениях

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

>> Не понял вашу мысль

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

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

Ну как говорил Эйнштейн: «Всё следует упрощать до тех пор, пока это возможно, но не более того».
Хотя здесь все же основная мысль была перейти на чужую терминологию, так как ее уже знают.
CLASS ItemGroup;
name = DATA ISTRING[100] (ItemGroup);

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


CLASS ItemGroup {
    name: DATA ISTRING[100];
}

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


//#game
CLASS Game 'Игра';

date 'Дата' = DATA DATE (Game);
hostTeam = DATA Team (Game);
guestTeam = DATA Team (Game);
hostTeamName 'Хозяева' (Game game) = name(hostTeam(game));
guestTeamName 'Гости' (Game game) = name(guestTeam(game));
//#game end

Так гораздо лучше выглядит, меньше информационного шума:


CLASS Game 'Игра' {
    date 'Дата': DATA DATE;
    hostTeam: DATA Team;
    guestTeam: DATA Team;
    hostTeamName 'Хозяева': name(this.hostTeam);
    guestTeamName 'Гости': name(this.guestTeam);
}
Даже в вашем примере вы обозначаете комментариями начало и конец структуры, это говорит о том, что выразительность языка недостаточная.

Эти комментарии — это разметка для скрипта, который формирует html'ки для confluence, который мы используем для документации. Это учебный пример из документации, поэтому он так размечен, выразительность языка тут не при чем.
Скажите, почему выбрана именно такая запись?

В lsfusion классы не являются центральной сущностью, вокруг которой строится остальная логика, в lsfusion главными и первичными яляются свойства и действия, а классы выступают в роли ограничений, фильтров. Да, с них удобно начинать объяснение, но это следствие того, что так большинству людей привычней.

Такой синтаксис также является следствием отсутсвия у нас инкапсуляции в том значении этого термина, где речь идет об объединении данных и методов работы с ними. То есть у нас свойства и действия не привязаны к какому-то одному главному классу. Если искать близкий аналог, то наши свойства — это что-то вроде мультиметодов, что дает возможность, например, subtype полиморфизма по нескольким параметрам. Реализуется это в lsfusion с помощью абстрактных (ABSTRACT) свойств и действий.

Также это дает нам возможность «расширять классы» новыми свойствами и действиями в разных модулях, обеспечивая модульность и позволяя нам компоновать необходимую функциональность с помощью выбора нужного множества модулей. Да, такого можно было добиться и открытыми классами c инкапсуляцией, как, например, в ruby, но наш подход — это следствие того, что свойства первичны, а классы вторичны. То есть свойство, зависящее, например, от товара и склада при нашем подходе не «принадлежит» ни товару, ни складу.

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

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

Функциональная СУБД


Поле в таблице с N ключами будет представлено как функция от N параметров.

Собственно, термин "свойство" в этой статье не упоминается ни разу, как и в следующей статье на ту же тему.


Я и говорю — любопытно.

Да, у меня там было два варианта, либо использовать нашу терминологию, либо использовать более известную обычному человеку «функция».

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

Из этого можно сделать не менее любопытный вывод: lsFusion не является функциональной СУБД. Ну так, по формальным признакам.

Эти комментарии — это разметка для скрипта, который формирует html'ки для confluence

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


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

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


Да, с них удобно начинать объяснение, но это следствие того, что так большинству людей привычней.

Так языки программирования для людей же делаются.


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

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


То есть свойство, зависящее, например, от товара и склада при нашем подходе не «принадлежит» ни товару, ни складу.

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

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

Язык разметки там для того чтобы в документацию часть файла вставлять, там их можно было part1, part2, ..., partN называть.

Ну так и плохо, что не привязано, потому что в предметной области оно привязано

Там в фразе на которую вы отвечали, основная часть — слово главному. То есть если у вас скажем currentBalance(Stock stock, Article article) — тут какой класс главный Stock или Article. Куда его класть в Stock или Article?

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

Но то, что для многих простых случаев инкапсуляция выразительнее — факт. И мы ее добавим (там на самом деле это не сложно, хотя описание алгоритма поиска свойств конечно еще больше усложнится), но и старый синтаксис естественно тоже останется (это своего рода static'ы в Java, C#), выше описал для чего. Просто в данном случае то что вы предлагаете это лучшее — враг хорошего.
Язык разметки там для того чтобы в документацию часть файла вставлять, там их можно было part1, part2, ..., partN называть.

Так, и с какой же целью вы вставляете в конкретный раздел документации именно эту часть, а не рандомные строки? Может потому что строки в этой части как-то связаны?


Там в фразе на которую вы отвечали, основная часть — слово главному.

Да, и в предметной области ровно то же самое.


То есть если у вас скажем currentBalance(Stock stock, Article article) — тут какой класс главный Stock или Article. Куда его класть в Stock или Article?

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


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

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

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

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

Не совсем понял эту мысль. Сейчас как раз у нас один синтаксис для описания свойств. Добавив инкапсуляцию будет два. Оставив чисто инкапсуляционный синтаксис, можно получить что некоторые модули будут пестрить EXTEND Team. При этом static синтаксис все равно придется оставить, иначе непонятно что например делать со свойствами от примитивов. Скажем f = DATE (INTEGER, INTEGER); Их куда? Делать EXTEND INTEGER?
При этом static синтаксис все равно придется оставить, иначе непонятно что например делать со свойствами от примитивов. Скажем f = DATE (INTEGER, INTEGER);

А что такое "свойство от примитива"? Вот в вашем конкретном примере в f какой прикладной смысл вкладывается?

Например, свойство isDayOff = DATA BOOLEAN (DATE). Обозначает, является ли данный день выходным или нет.

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

Так он и есть такой же:
isDayOff = DATA BOOLEAN (DATE);
isActive = DATA BOOLEAN (User);
В чем разница?

А я и не говорю, что разница есть. Я отвечаю на вопрос "что делать со свойствами примитивов" — то же самое, что со "свойствами" других классов.

Так человек предложил сделать инкапсуляцию. ОК:

EXTEND CLASS User {
isActive = DATA BOOLEAN;
}

Что с isActive от DATE делать?
Так человек предложил сделать инкапсуляцию

Вообще-то, человек вам явно написал "я говорю не про инкапсуляцию".


EXTEND CLASS User {
isActive = DATA BOOLEAN;
}

… и тот же человек вам написал: "я ничего не говорил про extend".


Что с isActive от DATE делать?

То же самое: если вы настаиваете, что для записи добавленного свойства для пользователя нужно использовать EXTEND, то для записи добавленного свойства даты нужно использовать его же.


EXTEND DATE {
isDayOff = DATA BOOLEAN;
}
EXTEND слово нужно для определения является ли это объявление нового класса или просто использование существующего.

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

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


Но тут вот какая штука, многие агитируют за инкапсуляцию, потому как привыкли к ней.

Пока что "за инкапсуляцию" здесь агитируете вы. А ваши собеседники повторяют, что они говорят не об инкапсуляции.


А ирония в том, что в современных языках инкапсуляции для примитивов в основном нет

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

Пока что «за инкапсуляцию» здесь агитируете вы. А ваши собеседники повторяют, что они говорят не об инкапсуляции.

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

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

Лично я чисто про ООП'ую говорю (сокрытие не обязательно, это опять таки перпендикулярная штука).

Там даже написано, какая конкретно инкапсуляция есть в C#. Не знаю уж, куда конкретнее.

isDayOff не может быть свойством DATE, так как требует кучу дополнительной информации — пользователя, причину, даже страну, в зависимости от целей. Взял пользователь выходной среди недели, ну вот мастер из ЖКХ только в этот день может прийти, как вы будете true возвращать? Правильный вариант это например класс ScheduleManager с методом isDayOff(Date, User).

Хорошо, а isLeapYear(Date) может быть?

И я хотел бы заметить, что мы обсуждаем lsfusion, отвечаем на вопросы, почему у нас синтаксис именно такой, а не иной. Когда мы используем слово «свойство», мы имеем ввиду термин из lsfusion. Если мы будем говорить на разных языках, то друг друга так и не услышим.

Ок, isLeapYear подходящий пример, и теперь понятно, при чем тут EXTEND. Допустим у нас несколько таких свойств.


isLeapYear = DATA BOOLEAN (DATE);
some LONG CODE;
isEvenYear = DATA BOOLEAN (DATE);
some LONG CODE;
another LONG CODE;
has31Days = DATA BOOLEAN (DATE);
some LONG CODE;
...

EXTEND Date {
    isLeapYear: DATA BOOLEAN;
    isEvenYear: DATA BOOLEAN;
    has31Days: DATA BOOLEAN;
}

some LONG CODE;
another LONG CODE;
...

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

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

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

Если не означает, не надо писать в один класс, если означает, надо. Как есть, так и делать. Все просто же.

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

Но опять же мы все-таки хотели иметь возможность не создавать классы для свойств, зависящих от нескольких равноправных сущностей. Можно, конечно, для этой цели использовать какой-нибудь вот такой синтаксис:
(Item i, Store s) {
property1;
...
propertyN;
}


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

"Глобальное пространство имен". Один объект, создается при старте, удаляется при завершении.


можно получить что некоторые модули будут пестрить EXTEND Team

Я ничего не говорил про extend, только про форму записи того, что у вас и так записано.


иначе непонятно что например делать со свойствами от примитивов. Скажем f = DATE (INTEGER, INTEGER); Их куда? Делать EXTEND INTEGER?

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


class SomeClass {
    f: DATE;
}

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

«Глобальное пространство имен». Один объект, создается при старте, удаляется при завершении.

Ну вы же понимаете что это дырявая абстракция и попытка подогнать все под ответ. В ERP этой абстракции будет принадлежать 70% свойств (так как в сложных системах свойств от одного параметра как правило большинство).
Не совсем понятно, что такое «свойство от примитивов» и как оно используется, но EXTEND тут ни при чем. Помещаем в отдельный класс с названием из бизнес-логики, который ни от чего не наследуется.

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

То есть как в примере сверху когда есть свойство является день выходным или нет:

class DayOffs {
isDayoff = BOOLEAN (DATE);
}

Как определить это на самом деле это isDayoff от одного параметра или от двух, то есть:
isDayOff = BOOLEAN (DATE)
или
isDayOff = BOOLEAN (Dayoffs, DATE)

Тоже самое с currentBalance. Не совсем понял какой синтаксис вы предлагается для него. Сейчас это:

income = GROUP SUM quantity(IncomeDocumentDetail i) BY sku(i), stock(document(i));
outcome = GROUP SUM quantity(OutcomeDocumentDetail i) BY sku(i), stock(document(i));
currentBalance(Sku sku, Stock stock) = income(sku,stock) — outcome(sku, stock);

В вашем синтаксисе это будет выглядеть для Sku:
CLASS Sku {
income = GROUP SUM quantity(IncomeDocumentDetail i) IF sku(i) = this BY
stock(document(i));
outcome = GROUP SUM quantity(OutcomeDocumentDetail i) IF sku(i) = this, BY stock(document(i));
currentBalance(Stock st) = income(st) — outcome(st);
}
Хотя тоже самое можно записать и для Stock. Соответственно вопрос куда именно класть эти свойства в Stock или Sku? И не будет ли такая неоднозначность создавать дополнительную сложность? В ООП инкапсуляция нужна для реализации field'ов и полиморфизма. А в lsFusion этой потребности нет.
В ERP этой абстракции будет принадлежать 70% свойств (так как в сложных системах свойств от одного параметра как правило большинство).

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


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

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


Соответственно вопрос куда именно класть эти свойства в Stock или Sku?

Вы не поверите, но кортежи ровно для этого и придумали.


(Sku, Stock) {
  income = ...
  outcode = ...
  currentBalance = income - outcome
}

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

Вы не поверите, но кортежи ровно для этого и придумали.

Вы эти точки тогда расшифруйте. Как вы в них будете к Sku и Stock обращаться this1 и this2?

Не говоря, о том что ладно когда у свойств первый параметр совпадает, но когда все совпадают это гораздо более редкая ситуация. Соответственно непонятно чем это лучше когда параметры задаются прямо при объявлении свойства.
Как вы в них будете к Sku и Stock обращаться this1 и this2?

sku и stock. Автоименование в кортежах уже даже в C# умеют.


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

А если не совпадают, то и группировать, возможно, не надо. Или надо, но иначе.


Соответственно непонятно чем это лучше когда параметры задаются прямо при объявлении свойства.

Тем, что связанные в проекте сущности оказываются связанными в языке. Это удобно.


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

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

Вот честно не понимаю, что вы имеете ввиду под фразой «все свойства одинаковые».

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

Очень простую вещь: вы в ходе этого обсуждения требуете, чтобы концепция, которую вам показали на isDayOff = DATA BOOLEAN (DATE), была применима к currentBalance(Stock st) = income(st) — outcome(st). Я из этого делаю вывод, что для вас и то, и другое — это свойство, и они в lsFusion относятся к одной и той же категории, и от них ожидается одно и то же поведение. Ну то есть ровно то, что подразумевается, когда две вещи называют одним словом.


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

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


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

Заводить по модулю на каждую бизнес-сущность? Можно, конечно, но избыточно же.

Заводить по модулю на каждую бизнес-сущность? Можно, конечно, но избыточно же.

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

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

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


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

Нет, не избыточно, если оно решает разные задачи.

Нет, не избыточно, если оно решает разные задачи.

Как разные? Одну же — задачу функциональной группировки.

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

А здесь уже бритва не помню кого должна работать. Что разные сущности не должны отвечать за одно и то же.

Ну так они и не отвечают за одно и то же. Они отвечают за разное.

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

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

Нет же. Там же написано: разных объектов. В смысле, классы группируют одни объекты, модули группируют другие объекты.

Ну вы же понимаете что это дырявая абстракция и попытка подогнать все под ответ.

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


В ERP этой абстракции будет принадлежать 70% свойств

Если вы так напишите, то да. А логически нет. externalSQL(), externalLSF(), importOrder(), shipment() логически делятся на 2 группы, одна относится к инфраструктуре, другая к бизнес-логике.


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

Свойства всегда принадлежат какому-то this. Параметры свойствам не нужны, this используется в коде методов.


Как определить это на самом деле это isDayoff от одного параметра или от двух, то есть:

Я другой код писал, у меня там это функция с 2 аргументами.


В вашем синтаксисе это будет выглядеть для Sku: Хотя тоже самое можно записать и для Stock. Соответственно вопрос куда именно класть эти свойства в Stock или Sku?

Я же уже сказал, если отнести к конкретному классу нельзя, это будет третий класс.


class SkuManager {
    currentBalance(Stock stock, Sku sku) {
        return this.income(stock, sku) - this.outcome(stock, sku);
    }
}

Вообще, если balance это количество товара на складе, то можно в склад поместить, но точно не в Sku. Потому что склад контролирует товар, а не наоборот. А вернее заведующий складом, вот и третья сущность появилась.


В ООП инкапсуляция нужна для реализации field'ов и полиморфизма.

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

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


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

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

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


Если у свойств одинаковый / семантически близкий функционал их лучше выделить в отдельный модуль. Благо lsFusion отлично подходит для работы с такими микромодулями. Ну или просто в одном модуле рядом положить. В некоторых случаях сгруппировать в одном классе может быть еще лучше, но это уже лучшее враг хорошего.
Ну или просто в одном модуле рядом положить.

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

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

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

Оно не принадлежит ни товару, ни складу, оно принадлежит третьему классу.

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

"Пара" это логически и есть третья сущность, только без явно выделенного класса.
Кстати, где хранятся значения, в промежуточной таблице для many-to-many?


В результате этого мы можем получить при желании множественную диспетчеризацию

Для поддержки множественной диспетчеризации в языке необязательно делать методы, висящие в глобальном пространстве имен. Нет никакой разницы выбирать реализацию мультиметода из globalNamespace.multiMethod() или someVariable.multiMethod().

"Пара" это логически и есть третья сущность, только без явно выделенного класса.

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

«Пара» это логически и есть третья сущность

Любая сущность (а точнее объект) подразумевает операции создания / удаления. У пары / кортежа таких операций нет.

Хотя конечно вопрос что под сущностью понимать. Так как любое понятие можно абстрагировать до полной бессмысленности.
У пары / кортежа таких операций нет.

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


Любая сущность (а точнее объект) подразумевает операции создания / удаления.

А у вас свойства могут быть только у сущностей ("а точнее объектов"), или нет?

У пары / кортежа таких операций нет.

Ну как это нет. Вот у меня есть Product product, я достал его по id из таблицы. Какое у него значение этого общего свойства? Никакое, пары в данный момент еще не существует. Потом я достал Stock stock, обратился к свойству, получил значение. Значит пара в этот момент существует. Значит она была создана между этими двумя моментами.


Но это буквоедство уже. Суть в том, что если свойство не принадлежит одному объекту, значит принадлежит другому, и лучше если это будет явно задано в коде, чем если это надо будет определять путем его анализа. Вот как в примере с функциями externalSQL(), externalLSF(), importOrder(), shipment(). Тот, кто читает код, будет их группировать в уме "ага, это системные функции, это бизнес-логика". Значит язык опять же недостаточно выразительный, не позволяет задавать все нужные взаимосвязи.

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

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

Оно не принадлежит ни товару, ни складу, оно принадлежит третьему классу.

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

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

Как ни странно, это совершенно не нужно для того, чтобы реализовать написанное выше предложение. Кортежи, они же типы-произведения — и все.


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

Ну, вы же по какому-то "событию" создаете запись в БД, которая содержит количество этого товара на этом складе? А она и есть этот "объект". И с удалением то же самое.

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

Ну, вы же по какому-то «событию» создаете запись в БД, которая содержит количество этого товара на этом складе? А она и есть этот «объект». И с удалением то же самое.

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

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


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


Ну и я, наверное, даже не столько про физическую сторону вопроса говорил, сколько про логическую.

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


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

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

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

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


Это позволяет не создавать объекты (товар, склад) (объекты же будут у этого класса?), потому что с этими объектами есть сложности, например, их когда-то нужно создавать и удалять.

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

И конкретно по этому примеру, как у вас хранится факт, что товар находится на складе?

Или вот возьмем более интересный пример, из соседней статьи.


CLASS Person;
likes = DATA BOOLEAN (Person, Person);
friends = DATA BOOLEAN (Person, Person);

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

Ну и да, к синтаксису задания свойств одного класса это не имеет никакого отношения.

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

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

Нет, давайте конкретно. Вот вы говорите про общее свойство currentBalance у Sku и Stock. Допустим оно не вычисляется, а просто вводится пользователем. В базе будут 3 таблицы — sku, stock, sku_stock? Или как?

Да, примерно так.

И этот currentBalance будет храниться в sku_stock? Ну вот и третий класс, в который это свойство надо поместить.

Я сказал «примерно так». В другой ситуации, когда, например, Sku и Stock — это некие производные классы, физическая модель может быть не такой. И эту физическую модель мы можем менять в продакшене.

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

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

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

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

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

Без изменения кода, но с полным сохранением поведения? Что-то верится с трудом, извините уж.


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

Понимаете ли, в чем дело… то, почему у вас так сделано, не отменяет того, как это сделано.

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

Эм. Вот было свойство, обычное такое хранимое свойство. В него были присвоения в нескольких местах кода. А теперь вы делаете его вычисляемым, и что происходит с этими присвоениями?..

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

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

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


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

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

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


Почему это не повлияет на классы при таком определении сущностей?

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


почему у нас сделано так, а не иначе.

Ну получается вы из-за нескольких случаев, когда надо сделать зависимость свойства от двух классов, сделали неудобный синтаксис, которым надо пользоваться во всех остальных. Копипаста (название класса в скобках) это основной признак того, что что-то не так. У вас были причины так сделать, но дело в том, что эти причины приводят к менее поддерживаемому коду, и не стоит продолжать их придерживаться. Что несколько человек и пытаются вам объяснить.


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

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

Просто хочу сказать, что вариант, о котором я говорю, не повлияет на преимущества, которые вы назвали (мультиметоды, расширения классов и т.д.)
Если речь о варианте с синтаксической конструкцией, то не повлияет. Если речь о cоздании «третьих классов» и переходе на single dispatch, то, конечно, повлияет. Но это, похоже, долгий разговор.

Вот эта третья таблица sku_stock и есть та самая сущность, про которую NitroJunkie утверждает, что ее нет.

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

Хотя опять таки вопрос, что вы понимаете под сущностью в программировании. Жду ссылку на описание этого понятия.
Я говорил про классы, а не про какие-то мифические сущности.

NitroJunkie: "Проблема в том что: «Не следует привлекать новые сущности без крайней на то необходимости». А тут не то что крайней, тут вообще необходимости нету.", вот ссылка.


Одно из двух: или вы говорите про сущности, или вы признаете, что принцип Оккама к вам не применим.


Никакого класса Товар на Складе нет.

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

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

А в приведенном мной примере?


CLASS Person;
likes = DATA BOOLEAN (Person, Person);
friends = DATA BOOLEAN (Person, Person);
В таблице с ключами (Person, Person). А может храниться в таблице (Object, Object) или (Person, Object). В конкретном примере в этом нет смысла, но для классов, которые являются частью какой-нибудь иерахии классов, смысл есть.

Давайте для простоты считать, что иерархии классов нет, а то она будет добавлять еще одно ненужное усложнение сейчас. Поэтому — (Person, Person).


  1. Пойдем по шагам. Вот есть только одна связь:


    likes = DATA BOOLEAN (Person, Person);

    К какой структуре таблицы она приведет? Когда в эту таблицу добавляются, и, что важнее, удаляются данные?


  2. Добавим вторую связь:


    friends = DATA BOOLEAN (Person, Person);

    Как изменилась структура БД?


  3. Добавим данные к связям: для likes нам надо хранить дату постановки лайка, для friends — кто может видеть эти отношения. И то, и другое поле обязательные, т.е. если A likes B, то дата постановки — не null, а если A is friends with B, то видимость — не null. Как это записать в lsFusion, и к какой структуре БД это приведет?



Ну и это напомнило мне еще одну вещь, конечно.


isDayOff = DATA BOOLEAN (DATE)

(это из обсуждения здесь)


К какой структуре БД это приведет?

>> свойство, зависящее, например, от товара и склада при нашем подходе не «принадлежит» ни товару, ни складу

А в чём проблема ввести дополнительную сущность? Ну и «принадлежать» только ей.
Бритва Оккама
Принцип «бритвы Оккама» состоит в следующем: если некое явление может быть объяснено двумя способами: например, первым — через привлечение сущностей (терминов, факторов, фактов и проч.) А, В и С, либо вторым — через сущности А, В, С и D, — и при этом оба способа дают одинаковый результат, то следует предпочесть первое объяснение. Сущность D в этом примере лишняя, и её привлечение избыточно.
Бритвой Оккама можно отсечь самое нужное, а потом мило улыбаясь, заявить — я ведь всё «по науке» обосновал!

По другому — Оккам за вас ничего не доказывает.
Подождите, вы сказали:
А в чём проблема ввести дополнительную сущность? Ну и «принадлежать» только ей.

Проблема в том что: «Не следует привлекать новые сущности без крайней на то необходимости». А тут не то что крайней, тут вообще необходимости нету.

Неа. Это вы не видите необходимости, но это не значит, что ее нет. Потому что эта сущность (в общем смысле слова, не в ER-терминологии, в ER-терминологии это будет связь) есть.

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

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


Софистика в чистом виде.

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

Неа, я этого не предлагал. Например, мне кажется, что в контексте вашей системы очень легко выделить «сущность»: это все, чему соответствует явная (а не материализованная) таблица в БД.

У нас можно написать TABLE objects (Object). И объекты всех классов (как и свойства с одним параметром) лягут в одну таблицу. Ну и есть еще числа, даты, которые тоже по сути сущности. Поэтому говорить что сущность соответствует таблице не совсем правильно. Хотя какая то логика тут есть.
К сожалению, софистикой занимаетесь вы, отказываясь признавать что-то сущностью, но при этом не дав сначала формального определения, что сущностью считается.

Сущность — это объект. То есть ровно тоже самое что подразумевается под объектом в том же C#. И вы же понимаете, что никаких объектов «Товар на складе» в C# нет.
У нас можно написать TABLE objects (Object).

Это другое.


Поэтому говорить что сущность соответствует таблице не совсем правильно.

А я и не говорю, что сущность соответствует таблице. Я говорю, что сущность — это все, чему соответствует таблица.


Сущность — это объект. То есть ровно тоже самое что подразумевается под объектом в том же C#.

В этом смысле ваши классы — не сущности. Потому что у ваших классов нет ни состояния, ни поведения.


И вы же понимаете, что никаких объектов «Товар на складе» в C# нет.

Ровно наоборот же: в типовой реализации ORM эта сущность будет:


class ItemAvailability
{
  Item Item;
  Warehouse Warehouse;
  decimal Qty;
  Unit UOM; 
}
А я и не говорю, что сущность соответствует таблице. Я говорю, что сущность — это все, чему соответствует таблица.

А можно тогда ссылку какую нибудь, где написано что такое сущность в программировании. А то в википедии класс и объект есть, а никакой сущности там нет.
Ровно наоборот же: в типовой реализации ORM эта сущность будет:

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

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


И вы же сказали, что сущность — это объект (причем не просто объект, а объект в C#).


А в системном программировании за такие классы вам любой архитектор руки оторвет.

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


Наличие таких классов, скорее характеризует ORM не с очень хорошей стороны, чем что-то доказывает.

Наличие таких классов доказывает, что если принять за данность, что в C# есть классы "товар" или "склад", то там может быть и класс "товар на складе", а следовательно, ваше утверждение "никаких объектов «Товар на складе» в C# нет" неверно.


Собственно, раз уж вы сказали "наличие таких классов, скорее характеризует ORM не с очень хорошей стороны". Вы имеете в виду любой ORM, или конкретный ORM, который представляет many-to-many связи таким образом?

>> А можно тогда ссылку какую нибудь, где написано что такое сущность

Читайте IDEF1(X), и да пребудет с вами сила.

>> в системном программировании за такие классы вам любой архитектор руки оторвет

А в чём системный архитектор здесь видит проблему? И тем более — «страшную проблему», за которую руки надо отрывать.
Читайте IDEF1(X), и да пребудет с вами сила.

Википедия говорит нам: "real or abstract things (people, objects, places, events, ideas, combination of things, etc.)". Оно?

В стандарте IDEF1(X) на эту тему гораздо больше весьма грамотных слов (на мой взгляд, разумеется). Без самостоятельного чтения вряд ли получится что-то вразумительное в наших с вами кратких репликах. Просто рекомендую почитать. Мне в своё время очень понравилось. Но версию выбирайте оригинальную, семьдесят-какого-то года, вроде, ибо потом пошло упрощенчество и уровень получился «как в википедии».
Мы уже это обсуждали выше. Во-первых, появляются объекты этих суррогатных классов, их временем жизни надо как-то управлять. Это не самостоятельные сущности, они зависимые. Затем, вот у нас есть иерархия классов с базовым классом Товар и иерархия классов с базовым классом Склад, нам теперь все пары классов из этих двух иерархий создавать? А если тройки? А четверки?

Другая проблема, которая сразу приходит на ум — это невозможность multiple dispatch без дополнительных усилий. То есть предложение делать сущности для пар, троек и т.д. объектов — это попытка вписать все в модель с инкапсуляцией и single-dispatch, то есть классическую ООП модель, которая существует во многих распространенных языках программирования (да, это привычно, я понимаю). В этой модели, если нам нужен полиморфизм по нескольким параметрам, то придется либо создавать на каждую пару по классу: SpaceshipSpaceship, SpaceshipAsteroid, AsteroidAsteroid (и делать вид, что это хорошее решение), либо переизобретать паттерн Visitor. А у нас нет инкапсуляции, зато мы получили multiple dispatch без особых усилий. Ну вот такой подход у нас.
Во-первых, появляются объекты этих суррогатных классов

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


В этой модели, если нам нужен полиморфизм по нескольким параметрам, то придется либо создавать на каждую пару по классу: SpaceshipSpaceship, SpaceshipAsteroid, AsteroidAsteroid

Во-первых, дженерики. Во-вторых, кортежи (которые те же дженерики, только еще более обобщенные).


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

Ну так вроде же в том же обсуждении уже выяснили, что нет никаких объектов суррогатных классов, не нужны они низачем. Можете привести пример, когда вам зачем-то нужен такой объект?
Ок, надо точнее выразить свою мысль. Если мы вернемся к самому первому предложению по синтаксису. И будем говорить о какой-то другой сущности, которая не является классом в lsfusion: какое-то новое понятие агрегата (кортежа) нескольких классов, то ок, все возможно, мы вроде бы уже остановились на этом. Это будет какой-то новый синтаксис, новое понятие поверх наших классов. Это нормальное предложение, но нужно взвешивать его плюсы и минусы.
Но если мы все еще обсуждаем вариант, в котором реально создается новый класс, класс в терминологии lsfusion. То в этом случае нет смысла в классе без объектов, если класс не абстрактный.

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

Можем ради интереса обсудить классический пример про астероиды. Я покажу на примере действий, со свойствами будет идентично. Вот как это будет выглядеть на lsfusion:
Объявляем абстрактный класс с абстрактным действием:
CLASS ABSTRACT Collidable;
collide ABSTRACT (Collidable, Collidable);

Используем где-нибудь это действие:
randomProcess(Collidable a, Collidable b) {
    ...
    collide(a, b);
    ...
}

Затем в каких-нибудь других модулях (скорее всего различных) объявляем классы:
CLASS Spaceship : Collidable;
CLASS Asteroid : Collidable;

И добавляем реализации для различных вариантов:
collide(Asteroid a, Asteroid b) + { ... }
collide(Asteroid a, Spaceship b) + { ... }
collide(Spaceship a, Asteroid b) + { ... }
collide(Spaceship a, Spaceship b) + { ... }

Теперь при использовании действия collide где-то в базовом модуле, будет вызываться нужная реализация, в зависимости от реальных рантайм классов объектов.
Я может быть просто не понимаю, как это будет выглядеть при добавлении «третьих» классов. Можете показать?
И будем говорить о какой-то другой сущности, которая не является классом в lsfusion: какое-то новое понятие агрегата (кортежа) нескольких классов, то ок, все возможно, мы вроде бы уже остановились на этом.

Ну, мне как раз не очевидно, что вы считаете возможным, а что — нет.


Это будет какой-то новый синтаксис, новое понятие поверх наших классов.

Ровно в том же объеме, в котором изначальное предложение michael_vostrikov "поверх" ваших классов — что, будем честными, на первый взгляд выглядит настолько просто, что можно препроцессором сделать.


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

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


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

В этой модели, если нам нужен полиморфизм по нескольким параметрам, то придется либо создавать на каждую пару по классу: SpaceshipSpaceship, SpaceshipAsteroid, AsteroidAsteroid

Зачем? Мы же обсуждали, нужен один третий класс, и всё. В нем будет этот же мультиметод с двумя параметрами.

Я собственно писал про это в первой статье, что инкапсуляцию можно добавить в язык, но это будет чисто синтаксическим сахаром. Самой платформе для реализации этот this не нужен, так как он не нужен SQL (которому фиолетово таблица от одного или от пяти ключей). И для того же полиформизма он тоже не нужен, полиморфизм в lsFusion в принципе по другому реализуется, не через виртуальные таблицы, где ключом ровно один параметр.

Кстати в вашем примере и this. собственно тоже не нужен. Да есть проблема с тем что hostTeam может быть параметром, но можно просто считать что параметры приоритетнее, вроде как локальные переменные в современных языках приоритетнее field'ов.
Самой платформе для реализации этот this не нужен, так как он не нужен SQL

Самой платформе зато нужен Game game, это то же самое, что this. Не аналогия, а именно абсолютно то же самое, только обозначается другими буквами.


Кстати в вашем примере и this. собственно тоже не нужен

Естественно, я просто заменил всё один-к-одному.

>> этот this не нужен, так как он не нужен SQL (которому фиолетово таблица от одного или от пяти ключей)

Ну вот, опять во всём всплывают уши SQL. То есть у вас неявная конвертация в SQL тянет за собой кучу последствий. Или по другому — скорее всего вы не имели никакой внятной картины будущей системы и ваяли «от души», то есть просто поглядывая, как ваше текущее желание ляжет на SQL. Ну и получили не стройное здание, а некую обвязку вокруг SQL, которую теперь всячески притягиваете за уши к чему-то стройному. Получилось не модель — реализация, а реализация — модель. С ног на голову. Поэтому везде вылазят уши SQL.
SQL никогда не был первичен. Более того первые реализации вообще не под SQL были. Тут как раз работала бритва оккама — в которой не надо выбирать это товар лежит на складе или склад содержит товар.
Возможно первичен не синтаксис (SQL), но реляционный подход. Собственно задача отображения кода в таблицы постоянно висит над всеми разработчиками ERP-подобных систем и вы не могли этим не заинтересоваться. Сначала были другие инструменты, с худшей гибкостью в реализации SQL (или вообще при отсутствии SQL, как при работе с какими-нибудь dbf-файлами), а потом вы перенесли наработки на более приличные СУБД.

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

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

Системно излагать предмет можно только опираясь на некую стройную логическую модель (как например реляционная модель сущность-атрибут-отношение), поэтому вам стоит серьёзно подумать над высокоуровневой моделью, задающей направления реализации вашего языка. Но если такой высокоуровневой модели нет — ну вы уже сами понимаете, что получился бессистемный наброс на тему «а мне кажется, что можно сделать ещё вкуснее».
Зарегистрируйтесь на Хабре, чтобы оставить комментарий