Как смоделировать умные контракты в UML? - PullRequest
0 голосов
/ 24 августа 2018

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

У меня есть следующий контракт на обслуживание:

contract ServiceContract {


    constructor (address _storeC, address _quizC, address _signC) {

        StorageContract storeC = StoreContract(_storeC);
        QuizContract quizC = QuizContract(_quizC);
        SignatureContract signC = SignatureContract(_signC);
    }


    function storeData (bytes32 data) public {
        storeC.save(data);
    }

    function getAnswer( bytes32 question) public constant returns (bytes32) {
       return quizC.get(question);
    }

    function sign (bytes32 data) public returns (bytes32) {
        return signC.sign(data);
    }

}

Я смоделировал это с помощью этой диаграммы классов, это правильно?

enter image description here

Ответы [ 2 ]

0 голосов
/ 24 августа 2018

[ Отредактировано для дополнительного уточнения ]

Моделирование системы - это формальное описание системы с использованием языка моделирования, а в некоторых случаях следование некоторым общим рекомендациям. В этом случае вы предлагаете использовать UML (см. UML Specification ).

UML-диаграммы можно разделить на три категории:

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

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

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

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

В предложенной вами схеме у вас есть четыре класса: ServiceContract, StorageContract, QuizContract и SignatureContract. Вы нарисовали связь между классами, известную как зависимость . И эта зависимость имеет определенный тип: использование (представлено ключевым словом «use»). Что это значит в UML?

Зависимость в UML определяется как отношение, в котором « семантика клиентов не завершена без поставщиков » ( Раздел 7.7.3.1 спецификации UML). Кроме того, зависимость использования определяется как отношение, в котором « одному NamedElement требуется другой NamedElement (или набор NamedElements) для его полной реализации или операции » ( Раздел 7.7.3.2 ).

Следовательно, если мы применим эти определения к предложенной вами диаграмме, вы можете прочитать соотношение между ServiceContract и StorageContract как «ServiceContract использует StorageContract». Но больше ничего. На этой диаграмме вы не знаете, как ServiceContract использует StorageContract, если он использует более одного экземпляра StorageContract и т. Д.

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

Первым шагом является использование ассоциации вместо зависимости . В UML ассоциация определяется как " семантическая связь, которая может возникнуть между типизированными экземплярами ". И вы знаете семантические отношения между классами, которые вы моделируете на диаграмме классов. Поэтому имеет смысл использовать ассоциацию .

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

enter image description here

Теперь, когда у нас есть связь, нам нужно определить ее дальше. Есть ли у ассоциации имя? Может ли ассоциация читаться обоими способами? Знаем ли мы значения множественности для каждого конца ассоциации? У концов ассоциаций есть ограничения?

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

Давайте посмотрим на исходный код. Когда вы положите это:

contract ServiceContract {
    constructor (address _storeC, address _quizC, address _signC) {
        StorageContract storeC = StoreContract(_storeC);
        QuizContract quizC = QuizContract(_quizC);
        SignatureContract signC = SignatureContract(_signC);
    }
}

Вы можете выразить это как ", ServiceContract имеет (владеет) свойством с именем storeC типа StoreContract" и т. Д.Право собственности на ассоциацию представлено маленьким закрашенным кружком (называемым точка ), в точке, где линия встречает принадлежащий ей классификатор.Также вы можете добавить название свойства, которое владеет собственностью ( Раздел 11.5.4 ).На этом этапе диаграмма выглядит следующим образом:

enter image description here

(см. ответ Томаса Килиана )

Поскольку мы не можем вывести видимость свойств из источника, мы можем просто сделать его неопределенным (в противном случае мы можем использовать знак + перед именем свойства для открытого свойства, знак - для частного свойства, # для защищенного свойства и ~ для пакета).

Также мы можем показать свойства в классификаторе для ServiceContract вместо конца принадлежащего ему классификатора вассоциация.Это будет выглядеть так:

enter image description here

Оба стиля разрешены спецификацией UML ( Раздел 9.5.3 ), и этотакже не обеспечивает соблюдение каких-либо соглашений.Однако в нем упоминается соглашение для общих сценариев моделирования", что свойство, тип которого является типом класса, является концом ассоциации, в то время как свойство, тип которого является типом DataType, не является ".

Эта диаграмма является правильной в том смысле, что она соответствует спецификации UML и описывает систему, в которой у вас есть:

  • Классификатор с именем ServiceContract, которому принадлежиттри свойства:
    • Свойство с именем storeC, тип которого является классификатором с именем StorageContract.
    • Свойство с именем quizC, тип которого является классификатором с именем QuizContract.
    • Свойство с именем signC, типом которого является классификатор с именем SignatureContract.

И помните, что вам по вкусу как модельеру, если этого достаточнодля вашей цели или нет.

Из источника я могу сказать, что предыдущая диаграмма все еще неполна и неточна.Почему?

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

Сначала мы добавим операции (функции) на диаграмму:

enter image description here

[ ПРИМЕЧАНИЕ. Вы также можете добавить _constructor_ к операциям. ]

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

Теперь для точности мне кажется, что ServiceContract группирует StorageContract, QuizContract и SignatureContract, чтобы обеспечить общий классификатор длядоступ к определенным операциям (функциям).Если это так, то речь идет о агрегации .В UML агрегация определяется как ассоциация, в которой « один экземпляр используется для группировки набора экземпляров » ( Раздел 9.5.3 ).

Агрегация можетмогут быть двух типов: shared (или просто общеизвестный как агрегация из предыдущих версий спецификации) и составной (или просто общеизвестный как состав из предыдущих версий спецификации).

Спецификация UML предоставляет более или менее конкретную семантику для того, что означает для агрегата тип составной : " составной объект несет ответственность за существование и хранение составных объектов".

Предположим, что в вашем случае существование и хранение StorageContract, QuizContract и SignatureContract - это ответственность ServiceContract. Тогда в этом случае у вас есть совокупность составной , которая представлена ​​черным ромбом:

enter image description here

И это читается как "ServiceContract состоит из собственного свойства типа классификатора StorageContract с именем storeC" и т. Д.

Имейте в виду, что, используя составной тип агрегации, вы говорите, что ServiceContract объект отвечает за существование и хранилище . Это означает, что всякий раз, когда экземпляр ServiceContract удаляется / уничтожается, соответствующие StorageContract, QuizContract и SignatureContract также должны быть уничтожены.

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

Итак, если StorageContract, QuizContract и SignatureContract существуют независимо от ServiceContract, и если вы согласитесь, что ServiceContract агрегирует эти объекты в соответствии с определением, данным в спецификации UML, вы должны использовать агрегацию shared .

A shared агрегация представлена ​​пустым ромбом в конце ассоциации классификатора, который объединяет другие классификаторы. И вот как это выглядит:

enter image description here

И эту диаграмму можно прочитать как:

  • Существует четыре классификатора: ServiceContract, StorageContract, QuizContract и SignatureContract.
  • ServiceContract объединяет три объекта недвижимости:
    • storeC, типа StorageContract.
    • quizC, типа QuizContract.
    • signC, типа SignatureContract.
  • ServiceContract имеет один конструктор, который требует трех аргументов:
    • _storeC типа address.
    • _quizC типа address.
    • _signC типа address.
  • ServiceContract имеет три публичные функции:
    • storeData, для которого требуется один аргумент типа bytes32 с именем data и ничего не возвращается.
    • getAnswer, который требует один аргумент типа bytes32 с именем question и возвращает тип данных bytes32.
    • sign, для которого требуется один аргумент типа bytes32, называемый data, и возвращается bytes32 тип данных.

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

0 голосов
/ 24 августа 2018

У вас просто есть ассоциации с этими тремя классами:

enter image description here

(я только что нарисовал одно отношение)

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

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