Форум Сообщества Аналитиков

Общий раздел => Примеры => Тема начата: Vadim от 16 Мая 2017, 15:37:40

Название: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 16 Мая 2017, 15:37:40
Есть класс "Склад" с атрибутом "ФИО Кладовщика", значение атрибута может меняться (не frozen).
Есть класс "Накладная", который связан со "Складом" ассоциацией * к 1 (накладная относится к ровно одному складу, склад связан с любым количеством "Накладных").
Пусть (хоть это и неважно) "Склад" у "Накладной" не может меняться (frozen).
У класса "Накладная" тоже есть атрибут "ФИО Кладовщика", который должен получить значение равное значению атрибута "ФИО Кладовщика" из "Склада" в момент создания "Накладной", и дальше менять значение этого атрибута нельзя.
Как обозначить эту ситуацию на диаграмме классов?
Сделать атрибут "Накладная" "ФИО Кладовщика" frozen мало - надо как-то объяснить как он вычисляется.
Сделать атрибут "Накладная" "ФИО Кладовщика" derived с ограничением "derive: ФИО_Кладовщика = Склад.ФИО_Кладовщика" нельзя - при изменении "Склад" "ФИО Кладовщика" его значение будет изменено.
Сделать атрибут "Накладная" "ФИО Кладовщика" frozen и derived тоже нельзя - это будет означать, что при наличии хотя бы одной "Накладной" у связанного "Склада" не может измениться  значение "ФИО Кладовщика".
Похоже использование derived вообще недопустимо - мы имеем дело не с избыточным элементом, удаление которого не меняет ничего.
Конечно, всегда есть такое средство, как комментарий - пиши, что хочешь! Но ситуация ничего экстраординального из себя не представляет, хотелось обойтись стандартными средствами!
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Galogen от 16 Мая 2017, 18:03:04
В момент создание объекта, значение атрибута или задается по умолчанию, или вычисляется задается конструктором.

Атрибуты типа derived вычисляются уже после создания объектов, например появление у родительского объекта новых дочерних объектов: Заказ (число заказанных товаров)- Товар
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 17 Мая 2017, 09:35:12
Так как же должно выглядеть описание атрибута по форме видимость ИМЯ кратность : тип = начальное_значение {свойства} (взято из Иванова-Новикова)?
Пока ясно, что среди свойства не должно быть derived и должно быть frozen. Но только frozen мало, надо еще что-то, может быть какие-то constraint?
В момент создание объекта, значение атрибута или задается по умолчанию, или вычисляется задается конструктором.
Как это надо понимать:
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Galogen от 17 Мая 2017, 10:08:35
Так как же должно выглядеть описание атрибута по форме видимость ИМЯ кратность : тип = начальное_значение {свойства} (взято из Иванова-Новикова)?
Пока ясно, что среди свойства не должно быть derived и должно быть frozen. Но только frozen мало, надо еще что-то, может быть какие-то constraint?Как это надо понимать:
  • В момент создание объекта значение атрибута или (a) задается по умолчанию, или (b) вычисляется - задается конструктором.
  • В момент создание объекта значение атрибута или (a) задается по умолчанию, или (b) вычисляется, или (c) задается конструктором.

Вадим.  UML это не язык программирования, а язык проектирования. На этом языке мы предлагаем описание требований или стратегию развития системы.
Сигнатура описания атрибута предполагает некоторый набор свойств. Одно из таких свойств - начальное значение (или значение по умолчанию), которое присваивается атрибуту при создании объекта. Надеюсь это понятно? Создание объекта - это рантайм режим, реализация и выходит за рамки дизайн-тайм, режима проектирования. Какой способ реакции на запись атрибут = начальное значение определяется языком реализации.Типично можно присвоить статическое значение, но в некоторых случаях можно в качестве начального значения использовать какую-то функцию. Возможность этого определяется языком реализации.

Например я создаю таблицу и ставлю на поле Дата создания дефолтное значение  = now(). Что это означает? Только то, что я показал уже реализацию, поскольку не всякая СУБД это воспримет как руководство к действию, а только та, для которой такая функция определена на уровне ядра и имеется внутренняя инструкция как применять.

Т.е. на уровне UML мы используем те средства, что мы имеем, описание через ограничение, заметку или еще как-то.
Итак, если у нас начальное значение = статическое (невычисляемое, а явно задаваемое ) значение - то мы его можем записать явно в сигнатуре определения атрибута
Если начальное значение динамическое, вычисляемое из довольно сложных условий (присвоение даты, присвоение значения в зависимости от значение других объектов и т.п.), то такую задачу можно поручить только конструктору объекта (т.е. вычисляется = задается)
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 17 Мая 2017, 14:26:09
UML это не язык программирования, а язык проектирования.
и ещё специфицирования
На этом языке мы предлагаем описание требований или стратегию развития системы.
"ФИО кладовщика в накладной должно совпадать с ФИО кладовщика склада на момент создания накладной" - разве это не требование?
Сигнатура описания атрибута предполагает некоторый набор свойств. Одно из таких свойств - начальное значение (или значение по умолчанию), которое присваивается атрибуту при создании объекта. Надеюсь это понятно?
Присвоение происходит в момент, когда объекта не было и он появляется, или в момент, когда объект был "новый" и стал "не новый"? Может эти моменты совпадают?
Создание объекта - это рантайм режим, реализация и выходит за рамки дизайн-тайм, режима проектирования.
Создание объекта - это рантайм режим, но речь идет не о конкретном объекте, а об общих правилах создания объектов.
Какой способ реакции на запись атрибут = начальное значение определяется языком реализации.Типично можно присвоить статическое значение, но в некоторых случаях можно в качестве начального значения использовать какую-то функцию. Возможность этого определяется языком реализации.

Например я создаю таблицу и ставлю на поле Дата создания дефолтное значение  = now(). Что это означает? Только то, что я показал уже реализацию, поскольку не всякая СУБД это воспримет как руководство к действию, а только та, для которой такая функция определена на уровне ядра и имеется внутренняя инструкция как применять.

Т.е. на уровне UML мы используем те средства, что мы имеем, описание через ограничение, заметку или еще как-то.
Итак, если у нас начальное значение = статическое (невычисляемое, а явно задаваемое ) значение - то мы его можем записать явно в сигнатуре определения атрибута
Если начальное значение динамическое, вычисляемое из довольно сложных условий (присвоение даты, присвоение значения в зависимости от значение других объектов и т.п.), то такую задачу можно поручить только конструктору объекта (т.е. вычисляется = задается)
Конструктор возвращает уже "не новый" объект - все ограничения должны выполняться (у "нового" ограничения могут и не выполняться - некоторые свойства (атрибуты и полюса) имеют "Null" значение)?
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Galogen от 17 Мая 2017, 18:02:57
и ещё специфицирования
Да, конечно.
Цитировать
"ФИО кладовщика в накладной должно совпадать с ФИО кладовщика склада на момент создания накладной" - разве это не требование?
Требование и что?
Цитировать
Присвоение происходит в момент, когда объекта не было и он появляется, или в момент, когда объект был "новый" и стал "не новый"?

Конструктор создает новый объект - это очевидно, вопрос реанимации объекта в рамках нашей дискуссии? если да, то
1 - возможно создание ранее не существующего объекта. В этом случае его атрибуты принимают значения по умолчанию, если это никак не задано, то Null. Реляционная теория призывает не создавать пустых атрибутов, но типичная ситуация иная, тем более в рамках реализации.
2 - возможна реанимация ранее существующего объекта, т.е. загрузка его в оперативную память, например для отображение данных для формы редактирования. В любом случае объект проходит разные циклы превращения и 2 случай как исходный может включать 1, работа конструктора в таком случае может быт параметризирована (си ++ допускает множество конструкторов)

Цитировать
Может эти моменты совпадают?
Хотелось бы понять что Вы под этим подразумеваете

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

Если провести аналогию с базами данных. Для атрибутов у вас ест правила валидации (default value, validation rules и стандартные процедуры обеспечения целостности, которые определяют значения индексов, первичный и внешних ключей), для любых нестандартных моментов можно использовать триггеры.

Например ясно что если вы поставите ограничение внешнего ключа, то в накладной никак не может оказаться кладовщик, отсутствующий в таблице Кладовщики, но если вам нужно определить, что в накладной должен быть кладовщик работающий в момент формирования накладной, то тут без сложный правил проверки написанных как триггер, не обойдешься.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 17 Мая 2017, 21:52:17
Требование и что?
Любое требование хочется зафиксировать с использованием формальных и, по возможности, визуальных средств (OCL лучше текста, графически лучше OCL).
Если провести аналогию с базами данных.
В БД будет так:
Таблица "Склады" с полями: Первичный ключ: Ид_Склад

Таблица "Накладные" с полями: Внешний ключ (на таблицу "Склады"): Ид_Склад
 
Новая запись в таблице "Накладные" в качестве значений полей ничего, кроме Null, иметь не может, ведь нет никаких default value. Это первый из моментов, объекта не было и он появился. Дальше кто-то (или что-то) должен позаботиться, чтобы ограничения целостности (оба NotNull, внешний ключ и, конечно, совпадение ФИО Кладовщика) выполнялись - запись может быть сохранена в БД, и сохраняется. Это второй из моментов, объект был "новым" и стал "не новым" - теперь запись ничем не отличается от других.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Galogen от 18 Мая 2017, 00:20:06
В БД будет так:
Таблица "Склады" с полями:
  • Ид_Склад, NotNull
  • ФИО_Кладовщика, NotNull
Первичный ключ: Ид_Склад

Таблица "Накладные" с полями:
  • Ид_Склад, NotNull
  • ФИО_Кладовщика, NotNull
Внешний ключ (на таблицу "Склады"): Ид_Склад
 
Новая запись в таблице "Накладные" в качестве значений полей ничего, кроме Null, иметь не может, ведь нет никаких default value. Это первый из моментов, объекта не было и он появился. Дальше кто-то (или что-то) должен позаботиться, чтобы ограничения целостности (оба NotNull, внешний ключ и, конечно, совпадение ФИО Кладовщика) выполнялись - запись может быть сохранена в БД, и сохраняется. Это второй из моментов, объект был "новым" и стал "не новым" - теперь запись ничем не отличается от других.
Если честно не понял, что Вы этим хотели сказать.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 18 Мая 2017, 01:51:53
Попробую, как обычно, внести путаницу.
По стандарту frozen больше нет, есть {readOnly}.
По стандарту объект любого класса создаётся "голеньким", независимо от того, указаны начальные значения атрибутов или нет. Объект создаёт специальная создающая деятельность (её можно рисовать на диаграмме деятельности). Сразу после того как создающая деятельность отработала, запускается инициализирующая деятельность, которая вычисляет начальные значения и присваивает их ({readOnly} и не-{readOnly} атрибутам с начальными значениями). Стандарт пишет, мол, часто инициализирующую деятельность моделируют как конструктор -- операцию с подходящей сигнатурой и стереотипом <<create>>. Конструктору можно указать постусловие. На диаграмме это выглядит как приякоренное к конструктору примечание с пометкой post:. В постусловии можно использовать постфикс @pre, чтобы лишний раз указать, что значение берётся таким, каким оно было до вызова конструктора. Но даже если это не сделать, стандарт определяет момент вычисления выражения, описывающего начальное значение. Т. о. короткое описание того, что в начальном посте:
в Накладной фиоКладовщика:string=Склад.фиоКладовщика {readOnly}
См. 6.3.3 в нижней части стр. 15.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 18 Мая 2017, 12:04:37
Попробую, как обычно, внести путаницу.
Получилось классное объяснение даже того, что и не было сказано, а нужно было сказать!
По стандарту frozen больше нет, есть {readOnly}.
Лично мне больше нравится frozen из-за того, что я его использую не только в атрибутах и полюсах ассоциаций, но и в обобщениях, когда хочу подчеркнуть тот факт, что если объект начал принадлежать подклассу, то не может его сменить (типа человек: мужчина или женщина).
И еще - сочетание derived и frozen означает, что хотя исходные данные для определения derived могут менять значение, это не должно приводить к изменению значения самого derived. Типа стороны прямоугольника могут и меняться, но так, чтобы его площадь оставалась неизменной.
фиоКладовщика:string=Склад.фиоКладовщика {readOnly}
Мне и хотелось получить нечто подобное по краткости. Но по моим представлением так описывается несколько другая ситуация: да в дальнейшем фиоКладовщика изменяться не сможет, но при заведении накладной в фиоКладовщика можно внести что угодно, просто в качестве начального значения для редактирования будет предложено значение равное Склад.фиоКладовщика, а не пустышка.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 19 Мая 2017, 18:24:10
Но по моим представлением так описывается несколько другая ситуация: да в дальнейшем фиоКладовщика изменяться не сможет, но при заведении накладной в фиоКладовщика можно внести что угодно, просто в качестве начального значения для редактирования будет предложено значение равное Склад.фиоКладовщика, а не пустышка.
Если просто описать постусловие конструктора и этим ограничиться, то сказанное будет справедливо (у атрибута будет значение по умолчанию, которое после инициализации можно менять). Если к постусловию (или к указанию начального значения) добавляется {readOnly}, это делает значение по умолчанию неизменным в течение всего времени существования объекта (после инициализации).

P. S. Концы ассоциаций могут быть помечены {readOnly}. Но предпочтение тэга/мема дело привычки.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 19 Мая 2017, 22:09:24
Если просто описать постусловие конструктора и этим ограничиться, то сказанное будет справедливо (у атрибута будет значение по умолчанию, которое после инициализации можно менять). Если к постусловию (или к указанию начального значения) добавляется {readOnly}, это делает значение по умолчанию неизменным в течение всего времени существования объекта (после инициализации).
Я считал, что значение по умолчанию конструктор получает на входе (вместо "пустышки"), а что будет на выходе - определяет сам конструктор. А будет ли в дальнейшем (после конструктора) изменяться значение уже и определяет readonly. В том то и беда: что пойдет на вход конструктору и что можно будет делать после конструктора указать можно, а самое тривиальное поведение конструктора - "ничего не делать, то что получил на вход, то и дай на выход" или "дай на выход вот это" можно указать только в теле конструктора.

Но предпочтение тэга/мема дело привычки.
Я не против readOnly, если читающий знает, что это означает: неизменность значения после инициализации. Но частенько буквальный перевод "только читать" интерпретируют как "нельзя писать", то есть "нельзя редактировать", но другим путем (например вычислять derived атрибут) изменять значение можно!
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 21 Мая 2017, 04:24:39
Думаю, тут снова проявляется безалаберность авторов [текста] стандарта.
В книге Dragan Milicev "Model-Driven Development with Executable UML" (pdf-ка есть на bookfi) хорошо разъясняется взгляд на readonly-атрибуты, frozen-атрибуты, выводимые атрибуты. ReadOnly = замороженные сразу после инициализации + без возможности разморозки. NonReadOnly выводимые (по стандарту UML) = обычные атрибуты с единственной особенностью: их значения можно посчитать по другим значениям, но, вообще говоря, неизвестно когда и как посчитать. Отсюда ReadOnly выводимые (по стандарту UML) = замороженные сразу после инициализации + без возможности разморозки атрибуты с единственной особенностью: их значения можно посчитать по другим значениям, но, вообще говоря, неизвестно когда и как посчитать.
Итого: можно ставить слэш перед Накладная::фиоКладовщика {readOnly}, и пытаться отражать "когда" и "где" оно выводится постусловием конструктора. Это не требует делать {readOnly} атрибут Склад::фиоКладовщика.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 22 Мая 2017, 09:52:44
В книге Dragan Milicev "Model-Driven Development with Executable UML" (pdf-ка есть на bookfi) хорошо разъясняется взгляд на readonly-атрибуты, frozen-атрибуты, выводимые атрибуты. ReadOnly = замороженные сразу после инициализации + без возможности разморозки. NonReadOnly выводимые (по стандарту UML) = обычные атрибуты с единственной особенностью: их значения можно посчитать по другим значениям, но, вообще говоря, неизвестно когда и как посчитать. Отсюда ReadOnly выводимые (по стандарту UML) = замороженные сразу после инициализации + без возможности разморозки атрибуты с единственной особенностью: их значения можно посчитать по другим значениям, но, вообще говоря, неизвестно когда и как посчитать.
Начал перечитывать Dragan Milicev "Model-Driven Development with Executable UML". Его frozen-атрибуты - это нечто не из UML (хотя явно где-то нужно). А вот про совместное readonly и derived не увидел. Что касается "их значения можно посчитать по другим значениям, но, вообще говоря, неизвестно когда и как посчитать" - он тут говорит скорее о реализации.
Итого: можно ставить слэш перед Накладная::фиоКладовщика {readOnly}, и пытаться отражать "когда" и "где" оно выводится постусловием конструктора.
Если {readOnly} (определяет что будет после инициализации, а точнее, что после инициализации ничего не будет меняться) и есть постусловие конструктора (определяет чем закончится инициализация), то чем отличаются наличие и отсутствие слэша?
Это не требует делать {readOnly} атрибут Склад::фиоКладовщика.
Как правильно это понять: ?
В исходных данных:
Есть класс "Склад" с атрибутом "ФИО Кладовщика", значение атрибута может меняться (не frozen).

Для меня на данный момент проблема выглядит так:
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 22 Мая 2017, 16:57:31
Его frozen-атрибуты - это нечто не из UML (хотя явно где-то нужно).
Да. Но у него, на мой вкус, внятная позиция по тому, что это такое и как увязываются между собой {readOnly} и {frozen}. Если можно морозить, то можно и разморозить и т. п. Есть другой вариант (http://book.uml3.ru/sec_3_2) внятной позиции.

А вот про совместное readonly и derived не увидел.
Совместное получается склеиванием раздельного, т. к. в стандарте оба свойства из метамодели независимы. Мы берём то, что сказано про readonly, и то, что сказано про derived и объединяем. Вот аналогия: теплое и сладкое -- это тёплое + сладкое. По намёкам из текущей версии стандарта выходит, что от соединения теплого и сладкого возникает дополнительный эффект "дрожжей" и градус в модели вдруг повышается.

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

Если {readOnly} (определяет что будет после инициализации, а точнее, что после инициализации ничего не будет меняться) и есть постусловие конструктора (определяет чем закончится инициализация), то чем отличаются наличие и отсутствие слэша?
Если слэша нет, то о привязке к другому значению мы узнаём только из постусловия. Если слэш есть, то наше внимание дважды акцентируется на непростом атрибуте.

Как правильно это понять ... не требует атрибут Склад::фиоКладовщика делать {readOnly}?
Второе. Извините за невнятность.

В исходных данных:
Для меня на данный момент проблема выглядит так:
  • используя readonly и конструктор можно нужную ситуацию описать
  • конструктор использовать не хочется
  • вместо конструктора можно отразить только его постусловие
  • "=defaultValue" не отражает постусловие
  • может "init: Накладная::фиоКладовщика = Склад::фиоКладовщика" отражает постусловие?
"=defaultValue" отражает постусловие конструктора в той части, в которой важно. И "init: Накладная::фиоКладовщика = Склад::фиоКладовщика" тоже. Просто в этих двух выражениях нет явной привязке ко времени, когда берётся присваиваемое значение. Эта привязка неявная, данная стандартом в пояснении к defaultValue. Постусловие, как мне кажется, нагляднее говорит о временнОй привязке. Выше писало про @pre, его можно [с некоторой тонкостью] использовать, что явно скажет о том, когда используется значение.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 22 Мая 2017, 22:33:59
Да. Но у него, на мой вкус, внятная позиция по тому, что это такое и как увязываются между собой {readOnly} и {frozen}. Если можно морозить, то можно и разморозить и т. п.
readonly и derived - это свойства "раз и навсегда", frozen (unfrozen) - только на время. Кроме того, если атрибут readonly, то делать его frozen (unfrozen) не имеет смысла - от этого ничего не изменится. И еще, если атрибут derived, то какой смысл давать ему defaultValue, разве что считать это дополнительным ограничением на те атрибуты, по которым вычисляется этот атрибут. Например описание атрибутов "длина, ширина, /площадь=6 {derive: длина*ширина}" означает: "Сразу после инициализации длина и ширина могут быть любыми числами, но их произведение должно равняться 6. Потом на длину и ширину не накладывается никаких ограничений, но площадь всегда будет равна их произведению.".
Есть другой вариант (http://book.uml3.ru/sec_3_2) внятной позиции.
Эти авторы когда-то впечатлили меня фразой: "существуют три уровня понимания обучающимся нового предмета, которые характеризуются следующими признаками: 1. Возникает приятное чувство понимания; 2. Может повторить своими словами; 3. Видит ошибки. Данная книга написана на третьем уровне и адресована обучающимся, ориентированным на третий уровень" - взято отсюда (http://window.edu.ru/resource/371/60371/files/itmo310.pdf). Про derived ничего не говорят, только про derive.
Совместное получается склеиванием раздельного, т. к. в стандарте оба свойства из метамодели независимы. Мы берём то, что сказано про readonly, и то, что сказано про derived и объединяем. Вот аналогия: теплое и сладкое -- это тёплое + сладкое. По намёкам из текущей версии стандарта выходит, что от соединения теплого и сладкого возникает дополнительный эффект "дрожжей" и градус в модели вдруг повышается.
Склеиваем и получаем: как получилось расчетное значение сразу после инициализации, так дальше и не меняется, хотя все время пересчитывается.
Если слэша нет, то о привязке к другому значению мы узнаём только из постусловия. Если слэш есть, то наше внимание дважды акцентируется на непростом атрибуте.
"=defaultValue" отражает постусловие конструктора в той части, в которой важно. И "init: Накладная::фиоКладовщика = Склад::фиоКладовщика" тоже. Просто в этих двух выражениях нет явной привязке ко времени, когда берётся присваиваемое значение. Эта привязка неявная, данная стандартом в пояснении к defaultValue. Постусловие, как мне кажется, нагляднее говорит о временнОй привязке. Выше писало про @pre, его можно [с некоторой тонкостью] использовать, что явно скажет о том, когда используется значение.
Рассмотрим класс "меняющийся прямоугольник" с атрибутами: длина, ширина, площадь, первоначальная площадь. Правильным описанием двух последних атрибутов будет: /площадь {derive: длина*ширина}, первоначальная площадь=площадь {readonly} (если считать, что "=defaultValue" отражает постусловие конструктора). Делать первоначальную площадь derive нельзя - тогда надо указывать правило вычисления. Или считать, что для атрибута с derived наличие "=defaultValue" (может в сочетании с readonly) служит правилом вычисления.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 23 Мая 2017, 16:25:52
readonly и derived - это свойства "раз и навсегда", frozen (unfrozen) - только на время.
Согласно. Выше, говоря о связке readOnly с frozen, имело в виду, что readOnly=frozenForever.

Кроме того, если атрибут readonly, то делать его frozen (unfrozen) не имеет смысла - от этого ничего не изменится. И еще, если атрибут derived, то какой смысл давать ему defaultValue, разве что считать это дополнительным ограничением на те атрибуты, по которым вычисляется этот атрибут.
Речь шла не о совместном применении readOnly и frozen, а об общности их смыслов.
Меня озарило, что авторы стандарта дали кучу примеров использования обсуждаемых нами тегов и слэшей. Они даны на диаграммах (и OCLях) описывающих метамодель UML. На 9.5.2 есть такое: Property::/isComposite:Boolean=false (также в 9.9.17.5). Авторы демонстрируют свой приём моделирования. Для каждого выводимого атрибута (полюса ассоциации) ими заводится одноимённая операция, возвращающая выведенное значение. Если OCL позволяет, то операции даётся тело (удивительно, что не derive!). См. Property::isComposite() в 9.9.17.7. Если убрать начальное значение в этом примере, смысл сохранится. Есть подозрение, что явное выписывание начального значения тут -- подсказка читателю диаграммы, чтобы ему не пришлось искать тело и в уме делать вывод. В схожей ситуации 12.3.2 (12.4.1.4, 12.4.1.6), Extension::/isRequired:Boolean вместо =false указано {readOnly}. Налицо "эффект дрожжей". Есть ещё одно подозрение, что завихрения относительно readOnly + derived рождались у авторов стандарта и обкатывались на метамодели UML. Т. е. это их реализаторская точка зрения, в которой они путают "не может меняться извне" с "не может меняться после инициализации". По каким-то причинам авторам эта путаница удобна. О том, как быть остальным, они не заботились. Щепотка "дрожжей" нашлась в описании Message::/messageKind {readOnly}. Для выводимого атрибута задана операция, тело которой состоит из возврата значения взятого у самого атрибута.
 
Например описание атрибутов "длина, ширина, /площадь=6 {derive: длина*ширина}" означает: "Сразу после инициализации длина и ширина могут быть любыми числами, но их произведение должно равняться 6. Потом на длину и ширину не накладывается никаких ограничений, но площадь всегда будет равна их произведению.".
Я бы такое описание прочло так: Длина и ширина не имеют значений по умолчанию. Площадь по умолчанию равна 6. В какие-то моменты времени значение площади вычисляется как произведение длины на ширину. Чтобы описать, в какие именно моменты, следует дать диаграмму состояний и/или дать реализации операций класса Прямоугольник.

Эти авторы когда-то впечатлили меня фразой: "существуют три уровня понимания обучающимся нового предмета, которые характеризуются следующими признаками: 1. Возникает приятное чувство понимания; 2. Может повторить своими словами; 3. Видит ошибки. Данная книга написана на третьем уровне и адресована обучающимся, ориентированным на третий уровень" - взято отсюда (http://window.edu.ru/resource/371/60371/files/itmo310.pdf). Про derived ничего не говорят, только про derive.
Авторы захаживали/захаживают на эту планету, так что я остановлюсь на первом предложенном ими уровне.

Склеиваем и получаем: как получилось расчетное значение сразу после инициализации, так дальше и не меняется, хотя все время пересчитывается.
Я полагаю, что слэш не устанавливает явной директивы, что нужно всё время пересчитывать. Стандарт на этот счёт лишь замечает, что изменение значения nonReadOnly выводимого свойства должно подчиняться derive-ограничению.

Рассмотрим класс "меняющийся прямоугольник" с атрибутами: длина, ширина, площадь, первоначальная площадь. Правильным описанием двух последних атрибутов будет: /площадь {derive: длина*ширина}, первоначальная площадь=площадь {readonly} (если считать, что "=defaultValue" отражает постусловие конструктора). Делать первоначальную площадь derive нельзя - тогда надо указывать правило вычисления. Или считать, что для атрибута с derived наличие "=defaultValue" (может в сочетании с readonly) служит правилом вычисления.
С точки зрения написанного мной выше этот пример может быть разобран так:
Значение первоначальной площади зависит от других значений, значит этот атрибут можно пометить как выводимый.
Указание начального значения у первоначальной площади, которая является {readOnly}, играет ту же роль, что и правило вычисления. При инициализации объекта будет вычислено то, что справа от равенства, результат будет положен в  первоначальную площадь, далее он меняться не будет.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 23 Мая 2017, 21:43:17
Меня озарило, что авторы стандарта дали кучу примеров использования обсуждаемых нами тегов и слэшей. Они даны на диаграммах (и OCLях) описывающих метамодель UML. На 9.5.2 есть такое: Property::/isComposite:Boolean=false (также в 9.9.17.5). Авторы демонстрируют свой приём моделирования. Для каждого выводимого атрибута (полюса ассоциации) ими заводится одноимённая операция, возвращающая выведенное значение. Если OCL позволяет, то операции даётся тело (удивительно, что не derive!). См. Property::isComposite() в 9.9.17.7. Если убрать начальное значение в этом примере, смысл сохранится. Есть подозрение, что явное выписывание начального значения тут -- подсказка читателю диаграммы, чтобы ему не пришлось искать тело и в уме делать вывод. В схожей ситуации 12.3.2 (12.4.1.4, 12.4.1.6), Extension::/isRequired:Boolean вместо =false указано {readOnly}. Налицо "эффект дрожжей". Есть ещё одно подозрение, что завихрения относительно readOnly + derived рождались у авторов стандарта и обкатывались на метамодели UML. Т. е. это их реализаторская точка зрения, в которой они путают "не может меняться извне" с "не может меняться после инициализации". По каким-то причинам авторам эта путаница удобна. О том, как быть остальным, они не заботились. Щепотка "дрожжей" нашлась в описании Message::/messageKind {readOnly}. Для выводимого атрибута задана операция, тело которой состоит из возврата значения взятого у самого атрибута.
Наиболее часто встречается ошибка из 12., она же самая грубая. Основная причина
Цитировать
путают "не может меняться извне" с "не может меняться после инициализации"
Ситуация из 9. чревата тогда, когда правило начального значения и правило производного значения приводят к разным результатам. Init это только на момент инициализации, а derive - и на момент инициализации, и на всю последующую жизнь! (readonly только на оставшуюся жизнь, но не на момент инициализации)
Я полагаю, что слэш не устанавливает явной директивы, что нужно всё время пересчитывать. Стандарт на этот счёт лишь замечает, что изменение значения nonReadOnly выводимого свойства должно подчиняться derive-ограничению.
Производный атрибут может использоваться в invariant-ограничениях, а там неактуальным не место!

У тех же Новикова и Иванова про derive:
Цитировать
Буквально означает "может быть вычислен по". Зависимость с данным стереотипом применяется не только к классам, но и к другим элементам модели: атрибутам, ассоциациям и т.д. Суть состоит в том, зависимый элемент может быть восстановлен по информации, содержащейся в независимом элементе. Таким образом, данная зависимость показывает, что зависимый элемент, вообще говоря, излишен и введен в модель из соображений удобства, наглядности и т.д.
Если убрать зависимый элемент и заменить все его использования на его derive-определение, ничего измениться не должно. А это возможно, если зависимый элемент постоянно будет актуальным.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 27 Мая 2017, 18:57:44
Ситуация из 9. чревата тогда, когда правило начального значения и правило производного значения приводят к разным результатам. Init это только на момент инициализации, а derive - и на момент инициализации, и на всю последующую жизнь! (readonly только на оставшуюся жизнь, но не на момент инициализации)
...
Производный атрибут может использоваться в invariant-ограничениях, а там неактуальным не место!
С Вами согласны авторы стандарта OCL 2.4 (см. 7.3.3, 7.3.7, 12.6, 12.9). Я спорить не буду, лишь замечу, что обороты вроде "всё время" употребимы для деклараций/спецификаций. С точки зрения реализации может быть достаточно [а может-- и нет], чтобы выводимый атрибут имел корректное значение всякий раз, когда оно затребовано. Такой ситуации отвечает описание ограничения как тела операции, а не как правила вывода. Быть может, то, что авторы UML 2.5 в метамодели UML описывают body, указывает на это обстоятельство. В этом можно увидеть различие между umlьным derive и oclьным (про oclьный явно сказано в тексте его стандарта, что он "всё время"). Забавно, что umlьные инварианты соблюдаются не всегда, если верить мелкому замечанию внутри 6.3.3. (мол, между вызовами операций объекта всё должно быть чики-пуки, а во время выполнения метода на инварианты смотрят сквозь пальцы).

У тех же Новикова и Иванова про derive:... Если убрать зависимый элемент и заменить все его использования на его derive-определение, ничего измениться не должно. А это возможно, если зависимый элемент постоянно будет актуальным.
Авторы "UML3" переводят пояснение, данное в стандарте к стереотипу <<derive>> из стандартного профиля, который можно применять к связям реализации и манифестации. Полагаю, что к этому случаю написанное и относится.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 28 Мая 2017, 19:50:17
С Вами согласны авторы стандарта OCL 2.4 (см. 7.3.3, 7.3.7, 12.6, 12.9).
Я с ними не согласен  :) (правда по другому поводу).
Из 7.3.7: "The derivation constraint must be satisfied at any time, hence the derivation includes the initialization. Both are allowed on the same property but they must not be contradictory. For each property there should be at most one initialization constraint and at most one derivation constraint.". Что привносит возможность одновременно задать и derive, и init? Проверить (гарантировать), что в момент инициализации выполняется дополнительное ограничение равенства одного и другого? А если понадобится проверить (гарантировать), что в момент инициализации выполняется какое-либо другое условие, вообще не связанное со значением описываемого property - придется всё равно использовать другой механизм (какой?, но это уже отдельный вопрос: как указать constraint, действующий не как invariant - всегда, а только в момент инициализации? Единственное, что пришло в голову - предусловие в конструктор. А если конструкторов несколько - в каждом прописывать одно и то же?)? Поэтому возможность одновременного указания derive и init считаю лишней - "For each property there should be at most one initialization OR derivation constraint." (если что-то не так с английским - простите).
Я спорить не буду, лишь замечу, что обороты вроде "всё время" употребимы для деклараций/спецификаций. С точки зрения реализации может быть достаточно [а может-- и нет], чтобы выводимый атрибут имел корректное значение всякий раз, когда оно затребовано. Такой ситуации отвечает описание ограничения как тела операции, а не как правила вывода. Быть может, то, что авторы UML 2.5 в метамодели UML описывают body, указывает на это обстоятельство. В этом можно увидеть различие между umlьным derive и oclьным (про oclьный явно сказано в тексте его стандарта, что он "всё время").
По-моему между "все время" и "когда затребовано" нет никакой разницы: даже про значение обыкновенного (не выводимого) атрибута известно только в тот момент, когда "затребовано" (ну и получено) это значение.
Забавно, что umlьные инварианты соблюдаются не всегда, если верить мелкому замечанию внутри 6.3.3. (мол, между вызовами операций объекта всё должно быть чики-пуки, а во время выполнения метода на инварианты смотрят сквозь пальцы).
Упоминается это мелкое замечание: " Note, however, that the postcondition is not required to hold during the
transient execution of the method behavior, but only at the stable point of the completion of execution of that
behavior. A class may also have invariant conditions that must be true before and after the execution of the
operation but may be violated during the course of the execution of the operation method." или что-то другое?
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 29 Мая 2017, 17:47:18
Что привносит возможность одновременно задать и derive, и init?
Да. Я по-прежнему думаю, что автор модели может потрафить читателю и явно выписать начальное значение выводимого атрибута (правда, затратив дополнительные усилия, чтобы они соответствовали друг другу). Например, площадь "хитрого" прямоугольника может быть единичной при неопределённом значении длины и/или ширины, а при заданных размерах равняться их произведению. Derive-правило в этом случает будет немного длинной oclькой, зато единицу можно указать не только в нём, но и явно на ДК.
 
Поэтому возможность одновременного указания derive и init считаю лишней - "For each property there should be at most one initialization OR derivation constraint." (если что-то не так с английским - простите).
Можно ей не пользоваться, но вдруг кем-то [авторами метамодели UML в одном единственном месте] востребовано.)

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

Упоминается это мелкое замечание: " Note, however, that ...?
Да, оно.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 30 Мая 2017, 22:51:40
Да. Я по-прежнему думаю, что автор модели может потрафить читателю и явно выписать начальное значение выводимого атрибута (правда, затратив дополнительные усилия, чтобы они соответствовали друг другу).
Если изменится правило вычисления выводимого атрибута или начальное значение того, из чего выводится выводимый атрибут, то возможно изменится и выписанное начальное значение - автору надо не забыть исправить.
Например, площадь "хитрого" прямоугольника может быть единичной при неопределённом значении длины и/или ширины, а при заданных размерах равняться их произведению. Derive-правило в этом случает будет немного длинной oclькой, зато единицу можно указать не только в нём, но и явно на ДК.
context Прямоугольник::площадь derive: if длина->isEmpty() or ширина->isEmpty() then 1 else длина*ширина endif
context Прямоугольник::площадь init: 1
Подразумевается, что при инициализации длина и ширина получают "пустое" значение?
Можно ей не пользоваться, но вдруг кем-то [авторами метамодели UML в одном единственном месте] востребовано.)
Это единственное - Property::isComposite?
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 31 Мая 2017, 00:48:32
Если изменится правило вычисления выводимого атрибута или начальное значение того, из чего выводится выводимый атрибут, то возможно изменится и выписанное начальное значение - автору надо не забыть исправить.
Ну, да.

длина->isEmpty() or ширина->isEmpty()
меняем на длина=null or ширина=null
или лучше на длина.oclIsUndefined() or ширина.oclIsUndefined()

Подразумевается, что при инициализации длина и ширина получают "пустое" значение.
Смешно, нигде явно не сказано, что писать в oclьке, чтобы проверить, есть ли значение в слоте (атрибуте). Сами авторы стандарта UML при описании метамодели сравнивают с null в таких случаях. Дурной пример заразителен, так что я думаю, надо идти след в след за ними. Строго говоря, не инициализированный слот не получает никакого значения. Чтобы по умолчанию был null надо явно его указывать, как дефолтное значение [намёк на это есть в стандарте OCL]. Так что речь нужно вести не о том, что лежит в слоте, если туда ничего не положили и не указали дефолтное значение, а о том, как выглядит ocl-проверка.
 
Это единственное - Property::isComposite?
Да. Искало без фанатизма, но, кажется, больше такого нет.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 31 Мая 2017, 16:29:11
длина->isEmpty() or ширина->isEmpty()
меняем на длина=null or ширина=null
или лучше на длина.oclIsUndefined() or ширина.oclIsUndefined()
В 11.7.1 Collection (OCL) есть:
Note: null->isEmpty() returns 'true' in virtue of the implicit casting from null to Bag{}
Смешно, нигде явно не сказано, что писать в oclьке, чтобы проверить, есть ли значение в слоте (атрибуте). Сами авторы стандарта UML при описании метамодели сравнивают с null в таких случаях. Дурной пример заразителен, так что я думаю, надо идти след в след за ними.
Авторы OCL чаще используют oclIsUndefined(), но в одном месте (11.5.4) - null.
Строго говоря, не инициализированный слот не получает никакого значения. Чтобы по умолчанию был null надо явно его указывать, как дефолтное значение [намёк на это есть в стандарте OCL]. Так что речь нужно вести не о том, что лежит в слоте, если туда ничего не положили и не указали дефолтное значение, а о том, как выглядит ocl-проверка.
Для меня это слишком: отдельно null, отдельно "никакое значение". Можно ссылку на намёк?
Да. Искало без фанатизма, но, кажется, больше такого нет.
Я тоже искал по-простому: у каких derived есть ещё и init. Так можно пропустить случай, если между атрибутами redefinition, один из них derived, а другой - с init.

А про это что-нибудь:
как указать constraint, действующий не как invariant - всегда, а только в момент инициализации? Единственное, что пришло в голову - предусловие в конструктор. А если конструкторов несколько - в каждом прописывать одно и то же?
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 31 Мая 2017, 19:34:10
В 11.7.1 Collection (OCL) есть:
Note: null->isEmpty() returns 'true' in virtue of the implicit casting from null to Bag{}
Я, наверно, ошибаюсь, считая, что тип длины определяется статически по её описанию, а не динамически по её значению.

Авторы OCL чаще используют oclIsUndefined(), но в одном месте (11.5.4) - null.
oclIsUndefined() лучше тем, что сработает при неправильно вычисленной длине (например, полученной делением на 0).

Для меня это слишком: отдельно null, отдельно "никакое значение". Можно ссылку на намёк?
A.2.1.1 Пример с email'ами.

А про это что-нибудь: ...
Угу. Полагаю, что общую часть можно описать один раз через def, а затем использовать в предусловиях разных конструкторов.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Galogen от 31 Мая 2017, 21:17:59
Вам надо время от времени итожить свою дискуссию, чтобы сохранить ее понимание для окружающих :)
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 01 Июня 2017, 13:23:52
Строго говоря, не инициализированный слот не получает никакого значения.
Имелось в виду, что не получает никакого значения при инициализации экземпляра.) По стандарту при мощности 1..1 значение быть должно. Можно предположить, что перед инициализацией, т. е. при создании "голого" экземпляра в атрибуты кладутся какие-то значения, как того требуют мощности. Но что это за значения, можно лишь гадать (и сравнивать с null, как это делают авторы метамодели:)).
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 03 Июня 2017, 20:33:44
Эти авторы когда-то впечатлили меня фразой: "существуют три уровня понимания обучающимся нового предмета, которые характеризуются следующими признаками: 1. Возникает приятное чувство понимания; 2. Может повторить своими словами; 3. Видит ошибки.
Навеяло. У Коберна 4 уровня понимания: http://alistair.cockburn.us/Shu+Ha+Ri+Kokoro
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 04 Июня 2017, 10:52:06
Навеяло. У Коберна 4 уровня понимания: http://alistair.cockburn.us/Shu+Ha+Ri+Kokoro
Неважно сколько уровней, важно, что только последний имеет реальную ценность.
Я, наверно, ошибаюсь, считая, что тип длины определяется статически по её описанию, а не динамически по её значению.
Множественность длины [0..1], поэтому тип длины такой, что включает и null-значение.
A.2.1.1 Пример с email'ами.
Все равно не уловил. :'(
Угу. Полагаю, что общую часть можно описать один раз через def, а затем использовать в предусловиях разных конструкторов.
Это способ лучшего описания конструкторов, а хотелось обойтись без конструкторов.
Вам надо время от времени итожить свою дискуссию, чтобы сохранить ее понимание для окружающих :)
Пока не готов.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 04 Июня 2017, 13:24:49
Множественность длины [0..1], поэтому тип длины такой, что включает и null-значение.
При такой мощности мне придраться не к чему.

Все равно не уловил.
Там указывается, что null можно использовать не только как пустое значение, но и как неопределённое значение. Если в Client::email положили null (например, конструктором/init'ом), то это может явно указывать, что емэйл неизвестен. Из  того, что авторы стандарта OCL пишут "may, for example, be assigned to an attribute", можно сделать вывод, что null не возникает сам по себе как неопределённое значение атрибута. Авторы метамодели UML полагают, что возникает, но не оговаривают это в своём стандарте.

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

Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 07 Июня 2017, 10:46:20
Вам надо время от времени итожить свою дискуссию, чтобы сохранить ее понимание для окружающих :)
Попробую. ИМХО:
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 28 Июля 2017, 02:19:37
Как возможные промежуточные итоги:
Описание метамодели UML и метамодели OCL можно рассматривать как источник для установления прагматики некоторых конструкций UML.
В стандарте UML есть ошибки.
Утверждение, что инвариант истинен всегда следует принимать без фанатизма. Если в модели есть динамика, то в ней обычно допустимы короткие отрезки времени, в течение которых целостности нет.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Galogen от 28 Июля 2017, 13:03:35
Спасибо.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 18 Октября 2017, 20:14:19
Когда начинал тему, проблема была довольно абстрактной, на уровне "хорошо бы". А сегодня на работе реальный вопрос: создаем заявку, а в ней 2 атрибута: дата создания и дата встречи. "Дата создания" должна получить в качестве значения текущую дату и больше не меняться. "Дата встречи" должна получить в качестве значения то что укажет пользователь при создании заявки и больше не меняться. А пользователь в качестве предлагаемого значения "даты встречи" получает текущую дату. Что для этой ситуации максимально можно сделать в рамках UML+OCL?
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 20 Октября 2017, 20:19:15
Вдруг уже не актуально, тогда простите.
На диаграмме классов описываем

Заявка
--------------------------------
датаСоздания : Дата = сегодня() {readOnly}
датаВстречи : Дата {readOnly}
--------------------------------
<<create>> новаяЗаявка(дВ : Дата) : Заявка

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

на ocl пишем:
context Заявка::датаСоздания : Дата
init: сегодня()
Это мы продублировали кусок uml-ного описания атрибута, чтоб определение работало в два раза сильнее.))

context Заявка::новаяЗаявка(дВ : Дата) : Заявка
post: result.датаВстречи = дВ
это мы рассказали о том, что датаВстречи заполняется конструктором, параметром которого является значение даты.

Если есть желание утроить, то можно ещё
context Заявка::новаяЗаявка(дВ : Дата) : Заявка
post: result.Создания = сегодня()

Понятно, что дублирование ограничений делает модель менее модифицируемой. Вместо того, чтобы править в одном месте, правим в 2-3 местах.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 01 Ноября 2017, 11:23:52
Вдруг уже не актуально, тогда простите.
Актуально, появились новые проблемы, но о них в конце.
На диаграмме классов описываем

Заявка
--------------------------------
датаСоздания : Дата = сегодня() {readOnly}
датаВстречи : Дата {readOnly}
--------------------------------
<<create>> новаяЗаявка(дВ : Дата) : Заявка

к этой операции приякориваем примечание о том, что пользователю в формочке для создания заявок предложат по умолчанию, и о том, что из формочки будет вызван этот конструктор.
Получается операция нужна только для того, чтобы к ней "приякорить" примечание - если в примечании указать, что оно относится к созданию Заявки (любому, не обязательно связанному с конкретной операцией), то этого достаточно. Примечание в этом случае будет связано не с конкретной операцией, а с <<create>> для Заявки.
на ocl пишем:
context Заявка::датаСоздания : Дата
init: сегодня()
Это мы продублировали кусок uml-ного описания атрибута, чтоб определение работало в два раза сильнее.))
Дублирование - это плохо, а почему - Вы и сами знаете:
Понятно, что дублирование ограничений делает модель менее модифицируемой. Вместо того, чтобы править в одном месте, правим в 2-3 местах.

context Заявка::новаяЗаявка(дВ : Дата) : Заявка
post: result.датаВстречи = дВ
это мы рассказали о том, что датаВстречи заполняется конструктором, параметром которого является значение даты.
Да, при наличии операции надо объяснить её работу. И ещё где-то надо рассказать, про начальное значение, равное сегодня().
Если есть желание утроить, то можно ещё
context Заявка::новаяЗаявка(дВ : Дата) : Заявка
post: result.Создания = сегодня()
Строго говоря, это не "чистое" утроение - мы говорим, что операция новаяЗаявка подчиняется общим правилам в отношении датыСоздания, то есть утроение только для операции новаяЗаявка. Если будет еще одна операция с <<create>>, то для неё утроение будет, если и в ней написать "post: result.Создания = сегодня()".

Теперь о новой проблеме. Пусть есть Склад, который связан не с одним, а со МНОГИМИ Кладовщиками. Накладная связана с одним Складом и с одним Кладовщиком (причем ни Склад, ни Кладовщик со временем не меняются {readOnly}). В момент создания Накладной её Кладовщик должен быть одним из Кладовщиков, связанных с её Складом, но это только в момент создания. Получается нужен init не типа derive (правило для вычисления значения), а типа invariant (правила проверки того, что значение является подходящим). Как init он действует только при создании, а как invariant не вычисляет, а проверяет.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 02 Ноября 2017, 05:54:02
Получается операция нужна только для того, чтобы к ней "приякорить" примечание - если в примечании указать, что оно относится к созданию Заявки (любому, не обязательно связанному с конкретной операцией), то этого достаточно.
Согласно текущей версии модели других способов создания заявок пока нет. Т. е. операция нужна, чтобы описать, как [вообще] создаются Заявки. К слову, в этом месте стандарт не декларирует, а рекомендует, т. е. указывает некоторую сложившуюся практику.

Примечание в этом случае будет связано не с конкретной операцией, а с <<create>> для Заявки.
С конкретной операцией (как элементом модели) будет связан конкретный экземпляр стереотипа <<create>>. С ним, в свою очередь, -- ограничение. Задать ограничение внутри класса для всех его конструкторов проблематично. Если мы не имеем в виду init:, конечно. Можно дать define-ом общее ограничение, но в каждом постусловии конструктора придётся явно сослаться на него.

Дублирование - это плохо
Ну, это был повод дать повод поговорить о некоторой избыточности OCL-я, который не только дополняет UML, но и в чём-то дублирует.
Прибавлю,  что если модель где-то стабильна, то снизить её модифицируемость в этом месте можно.
 
Теперь о новой проблеме. Пусть есть Склад, который связан не с одним, а со МНОГИМИ Кладовщиками. Накладная связана с одним Складом и с одним Кладовщиком (причем ни Склад, ни Кладовщик со временем не меняются {readOnly}). В момент создания Накладной её Кладовщик должен быть одним из Кладовщиков, связанных с её Складом, но это только в момент создания. Получается нужен init не типа derive (правило для вычисления значения), а типа invariant (правила проверки того, что значение является подходящим). Как init он действует только при создании, а как invariant не вычисляет, а проверяет.
Я всё ещё верю, что readOnly выводимые значения вычисляются [только] в момент создания объекта. Т. е. derive не "распространяет" readOnly дальше -- на элементы вычисляемого выражения.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 02 Ноября 2017, 22:23:01
Согласно текущей версии модели других способов создания заявок пока нет. Т. е. операция нужна, чтобы описать, как [вообще] создаются Заявки. К слову, в этом месте стандарт не декларирует, а рекомендует, т. е. указывает некоторую сложившуюся практику.
С конкретной операцией (как элементом модели) будет связан конкретный экземпляр стереотипа <<create>>. С ним, в свою очередь, -- ограничение. Задать ограничение внутри класса для всех его конструкторов проблематично. Если мы не имеем в виду init:, конечно. Можно дать define-ом общее ограничение, но в каждом постусловии конструктора придётся явно сослаться на него.
Вот-вот, если про создание сказать нечего, кроме того, что есть правило расчета значения атрибута создаваемого объекта - можно и не создавать операцию со стереотипом <<create>>.
Ну, это был повод дать повод поговорить о некоторой избыточности OCL-я, который не только дополняет UML, но и в чём-то дублирует.
Прибавлю,  что если модель где-то стабильна, то снизить её модифицируемость в этом месте можно.
Мне избыточность (в виде возможности выразить одно и то же несколькими способами) тоже не очень нравится, хочется её приспособить для чего-нибудь нужного, например:
Значение по умолчанию (задается в виде "=defaultValue" или "init: defaultValue") означает каким будет значение property в момент КОНЦА, а не НАЧАЛА инициализации экземпляра объекта. Если есть 2 способа для обозначения одного и того же, может один из них использовать для чего-то другого (например для значения property в момент НАЧАЛА)?
Или для решения свежей проблемы:
Теперь о новой проблеме. Пусть есть Склад, который связан не с одним, а со МНОГИМИ Кладовщиками. Накладная связана с одним Складом и с одним Кладовщиком (причем ни Склад, ни Кладовщик со временем не меняются {readOnly}). В момент создания Накладной её Кладовщик должен быть одним из Кладовщиков, связанных с её Складом, но это только в момент создания. Получается нужен init не типа derive (правило для вычисления значения), а типа invariant (правила проверки того, что значение является подходящим). Как init он действует только при создании, а как invariant не вычисляет, а проверяет.
можно было бы считать, что init не задает выражение, которое рассчитывает значение, а является логическим выражением, которое должно быть истинным в момент создания: для описанного примера context накладная init: self.склад.кладовщик->includes(self.кладовщик).
Я всё ещё верю, что readOnly выводимые значения вычисляются [только] в момент создания объекта. Т. е. derive не "распространяет" readOnly дальше -- на элементы вычисляемого выражения.
Если так, то того же эффекта можно добиться сочетанием init или = (с выражением как в derive) и readOnly - и вычислим в момент создания объекта, и на элементы вычисляемого выражения никакого влияния.
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 11 Ноября 2017, 02:53:31
Вот-вот, если про создание сказать нечего, кроме того, что есть правило расчета значения атрибута создаваемого объекта - можно и не создавать операцию со стереотипом <<create>>.
Авторы стандарта UML дают в описании метамодели UML пример, когда для каждого выводимого атрибута (тут у меня натяжка, т. к. выводимый м. б. <> есть правило расчёта) заводят операцию, поясняющую выводимость.
Почитало про выводимость у Фахрутдинова. Мне понравилось. По его формулировке можно сделать вывод, что если для атрибута есть сеттер, то он выводимый. Ну, или мой переводчик с английского на нлошный глючит.)
 
Мне избыточность (в виде возможности выразить одно и то же несколькими способами) тоже не очень нравится, хочется её приспособить для чего-нибудь нужного
Авторы стандарта uml позаботились о том, чтобы поставить рогатку на этом пути. В 9.5.3 сказано, что uml'ьный init работает только в отсутствие "specific setting for the Property"(???) и в отсутствие ocl'ьного init. Авторы стандарта ocl написали так, как-будто про uml'ьный init слыхом не слыхивали, т. е. подпели.
Плюс к этому, разные части uml'ного стандарта писали разные люди, из-за чего можно испытать много радости, читая, например, в 16.1.1.1, что создание объекта и "creation operation" могут содержать в себе инициализацию, но в то же время есть действие CreateObjectAction, которое только создаёт объект, не выполняет инициализацию атрибутов (которая моделируется отдельными действиями).
Или для решения свежей проблемы:можно было бы считать, что init не задает выражение, которое рассчитывает значение, а является логическим выражением, которое должно быть истинным в момент создания: для описанного примера context накладная init: self.склад.кладовщик->includes(self.кладовщик).Если так, то того же эффекта можно добиться сочетанием init или = (с выражением как в derive) и readOnly - и вычислим в момент создания объекта, и на элементы вычисляемого выражения никакого влияния.
Такая трактовка (лог. выражение, которое должно быть истинным) нестандартна (расходится со стандартом ocl).
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: Vadim от 20 Ноября 2017, 10:56:01
Почитало про выводимость у Фахрутдинова. Мне понравилось. По его формулировке можно сделать вывод, что если для атрибута есть сеттер, то он выводимый. Ну, или мой переводчик с английского на нлошный глючит.)
Дайте, пожалуйста, ссылку.
Авторы стандарта uml позаботились о том, чтобы поставить рогатку на этом пути. В 9.5.3 сказано, что uml'ьный init работает только в отсутствие "specific setting for the Property"(???) и в отсутствие ocl'ьного init. Авторы стандарта ocl написали так, как-будто про uml'ьный init слыхом не слыхивали, т. е. подпели.
Такая трактовка (лог. выражение, которое должно быть истинным) нестандартна (расходится со стандартом ocl).
Я понимаю, что это противоречит текущему (им) стандарту! Пытаюсь найти пути реализации потребности минимально модифицируя стандарт (или его трактовку). Осознаю, что любой, даже самый минимальный, отход от стандарта - опасен (читатель диаграммы поймет строго по стандарту - и будет прав).
Название: Re: Как обозначить атрибут, значение которого вычисляется в момент создания объекта
Отправлено: [прилетело НЛО и...] от 20 Ноября 2017, 23:20:19
Дайте, пожалуйста, ссылку.
https://www.uml-diagrams.org/derived-property.html
Цитировать
Derived property is property which value (or values) is produced or computed from other information...
Избирательному цитированию научилось от местных старожилов, если что.
Так вот, если мы согласимся, что значение параметра сеттера в момент его последнего вызова -- это "other information", то можем смело метить атрибут этого сеттера выводимым.)))