2015-04-02 8 views
5

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

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

Вот мой вопрос (я использую Visual Paradigm в качестве инструмента моделирования). Предположим, что у нас есть модуль микроконтроллера, а именно Timer. У нас есть набор операций, которые мы можем выполнить, например initTimer(), startTimer(), stopTimer() и так далее. Фактически эти функции определяют своего рода API. У нас могут быть разные классы Timer, скажем TimerA, TimerB, TimerC, которые наследуют (или реализуют?) Все указанные операции. Возможно, картина сделает сценарий более ясным. [C] означает классификатор.

     +----------------------------------+ 
         |    <<SW>>    | 
         |   <<Singleton>>   | 
     +--------------|    TimerA    | 
     |    +----------------------------------+ 
     |    | -instance : TimerA* = null [C] | 
     |    | -instanceFlag : bool = false [C] | 
     |    | -moduleAddress const = 0x0010 | 
     |    +----------------------------------+ 
     |    | -TimerA()      | 
     V    | +getInstance() : TimerA* [C]  | 
+---------------+  +----------------------------------+ 
| <<SW>>  |  
|  Timer  | 
+---------------+ 
| +initTimer() |  
| +startTimer() |<-----------------------+ 
| +stopTimer() |      | 
+---------------+  +----------------------------------+ 
         |    <<SW>>    | 
         |   <<Singleton>>   | 
         |    TimerB    | 
         +----------------------------------+ 
         | -instance : TimerB* = null [C] | 
         | -instanceFlag : bool = false [C] | 
         | -moduleAddress const = 0x0020 | 
         +----------------------------------+ 
         | -TimerB()      | 
         | +getInstance() : TimerB* [C]  | 
         +----------------------------------+ 

Visual Paradigm позволяет пользователю вводить код в каждую функцию. Я спрашиваю вас, какие отношения должны быть стрелками.

1) Обобщение: Timer класс с набором операций. Каждая операция имеет свою реализацию кода. Два производных класса TimerA и TimerB с обобщающей ссылкой, наследующей операции класса Timer.

2) Реализация: Timer является интерфейсом (не класс, как показано) и два класса, реализующих TimerA и TimerB. Критическая точка следующая. Хотя Timer является интерфейсом, и его операции не должны содержать детали реализации, VP позволяет написать код реализации для трех операций. При генерации кода, интерфейс C++, класс Timer создан: initTimer(), startTimer() и stopTimer() являются виртуальные члены из Timer с нет кода (как это должно быть). Создается класс C++ TimerA, который наследует класс Timer; кроме того, три операции Timer копируются среди членов TimerA с реализацией кода, которую я написал для операций класса интерфейса. Это происходит и для TimerB.

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

ответ

3

На ваш взгляд, какое из двух описаний лучше?

На мой взгляд, вариант 3, изображенный на рисунке ниже, лучше. Timer бы многоразовый (концептуально final) универсальный класс, это экземпляр только настроен по одноэлементным оберткам и связана usage dependency relationship

enter image description here

VP позволяет писать код реализации трех операций. Во время генерации кода ... Правильно ли писать реализацию кода для операций интерфейса ...?

Я не знаю, как правильно настроить генератор кода Visual Paradigm для получения того, что вы хотите, но хотя C++ интерфейс just a class like any other и нет никакого специального keyword для этой концепции, UML interface предназначается, чтобы быть только описание contract без связанной реализации. Некоторые языки, такие как C# или Java, имеют специальные interfacekeyword для этой цели, без правил кода, жестко закодированных в компиляторе.

Таким образом, хотя Visual Paradigm, возможно, может генерировать код, который вы хотите в конце концов, с точки зрения UML, моделируя interface с кодом неправильно


Сделайте свой выбор. Если вам нужен только код, который делает что-то, тогда идите и взломайте его в любом случае, что работает (как предлагает @ gilead-silvanas). Если вы хотите практиковать UML для использования в ваших будущих проектах на разных языках, тогда нет.

Также есть время, когда исходный сгенерированный код будет отходить от начальных проектных чертежей и от генератора кода, и вы отредактируете его вручную, даже если вы будете использовать такой инструмент, как Quantum Leaps Modeler for embedded systems.

Я бы пересмотрел (регулярно), если сражался с инструментом проектирования над весами. Преимущества для генерации кода

+1

Пожалуйста, исправьте меня, если я ошибаюсь. Благодаря вашему моделированию обеспечивается единственное существование классов 'TimerA' и' TimerB', потому что соответствующий флаг задается любой из двух оболочек singleton. То, что на самом деле создается, является объектом класса 'Timer' для всех доступных оболочек Singleton (это делается с помощью' TimerA :: getInstance() 'и' TimerB :: getInstance() 'static members). Итак, в конце концов, конструкторы 'TimerA()' и 'TimerB()' не используются? Могу передать аргументы классу Timer из TimerA и TimerB. Я ссылаюсь, в частности, на 'moduleAddress'. Благодарю. –

+0

@ UmbertoD. да, вот что я имел в виду: 'TimerA()' и 'TimerB()' могут иметь классные «статические» конструкторы, которые инициализируют переменные 'instance'.Но ** не беру его буквально **, поскольку он будет содержать для 'C#', где тик таймера будет обрабатываться функцией, прикрепленной к четному обработчику таймера (https://msdn.microsoft.com/en-us/ библиотека/system.timers.timer.elapsed (v = vs.110) .aspx). Я не был в мире «C++» активно в течение нескольких лет (и я рад). В 'C++' вы можете реализовать его, создав подклассы. Поэтому мой ответ может быть довольно обманчивым, когда дело доходит до генерации кода – xmojmr

2

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

+0

Спасибо за ответ. Мое первоначальное мнение заключалось в том, что 'Timer' фактически представляет интерфейс, потому что он содержит набор методов (API), которые должен реализовать каждый конкретный модуль (' TimerA', 'TimerB' и т. Д.). Я сомневался в наиболее концептуально приемлемом решении с точки зрения UML. Другая тревожная точка заключалась в том, чтобы записать код C++ (в VP), следовательно, реализацию для операций, которые являются частью интерфейса, а не класса. –

+2

На мой взгляд, с точки зрения UML, было бы неправильно писать реализации в интерфейсе, если мы будем строго следовать объектно-ориентированным правилам. –