Как стать автором
Обновить
4
0
Алексей Данченко @DAleby

Программист

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

1. «Законченное двоичное дерево».
Возможно, этот термин где-нибудь и применяется, но обычно это либо называют «полным двоичным деревом», либо вообще никак не называют, описывая правила построения

2. «Пирамидальная сортировка — это вполне годный алгоритм. Его типичная реализация не стабильна, но может быть таковой сделана».
Не стабильна, близка к распаду. Вроде бы обычно в русском языке термин «stable sort» называют «устойчивой сортировкой».

3. Описание алгоритма.
«Наконец, преобразуйте полученное дерево в max-heap с новым корнем.».
В оригинале ведь все куда более конкретно: «Finally, heapify the root of tree.» и затем идет описание того, что же такое «heapify». В переводе термин «heapify» потерян, из-за этого логика становится куда более размытой.
Также третий пункт описания алгоритма «Повторяйте вышеуказанные шаги, пока размер кучи больше 1.» в оригинале написан неудачно (не очень понятно. нужно повторять шаги 1 и 2 или только 2), и тут также оставлен без изменений (причем русскоязычный вариант субъективно еще менее понятный).
В результате по описанию этого простого алгоритма, на мой взгляд, вообще мало что понятно без чтения кода или дополнительного поиска информации (что возвращает нас к теме качества статей на geeksforgeeks).
CONSTRAINT password(User u) == password(BlackListItem item) MESSAGE 'пользователь не может иметь пароль, входящий в блеклист'
Я все-таки еще раз влезу. Уже целая куча сообщений в этой ветке из-за непонимания друг друга. Дело в том, что когда NitroJunkie написал «множество всех значений функции» имел он ввиду все-таки (если я не прав, то скажи) все то же множество всех наборов аргументов, для которых функция определена (ее значение от этих аргументов не равно NULL). Область определения функции, если угодно.
Интересует вопрос — а как вы работаете с миграциями? Накидали кода, развернули сервак, бабах — перименовали в коде кучу свойств, как оно потом всё это обрабатывает?

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

Более подробно можно прочитать здесь

Информация

В рейтинге
Не участвует
Откуда
Минск, Минская обл., Беларусь
Работает в
Дата рождения
Зарегистрирован
Активность