【问题标题】:UML generalization and realizationUML泛化与实现
【发布时间】:2015-06-07 10:45:41
【问题描述】:

我对 UML 很陌生,所以我对泛化和实现有一些疑问。我正在对电子微控制器的行为进行建模,我需要根据 UML 描述生成 C++ 代码。

据我所知,一个 实现一个接口,也就是说它可以提供一个接口的实现。 两个类之间可能存在泛化关系。在这种情况下,派生类继承基类的所有成员并获得对公共和受保护成员的访问权。

这是我的问题(我使用 Visual Paradigm 作为建模工具)。 假设我们有一个微控制器模块,即Timer。我们有一组可以执行的操作,比如initTimer()startTimer()stopTimer() 等等。实际上这些函数定义了一种API。我们可能有不同类的Timer,比如TimerATimerBTimerC,它们继承(或实现?)所有引用的操作。图片可能会使场景更清晰。 [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 具有一组操作的类。每个操作都有其代码实现。两个派生类TimerATimerB 具有继承类Timer 的操作的泛化链接。

2) 实现Timer是一个接口(不是图中所示的类)和两个实现类TimerATimerB。关键点如下。虽然 Timer 是一个接口,它的操作不应该包含实现细节,但 VP 允许为这三个操作编写实现代码。在代码生成期间,会创建一个接口 C++ 类 TimerinitTimer()startTimer()stopTimer()Timer虚拟成员无代码(应该是这样)。生成了一个 C++ 类TimerA,它继承了类Timer 的成员;另外Timer的三个操作在TimerA的成员之间复制了我为接口类的操作编写的代码实现。 TimerB 也会发生这种情况。

您认为这两种描述中哪一种更好?即使我知道在代码生成后会转移到实现类中,为接口的操作编写代码实现是否正确?

【问题讨论】:

    标签: class uml code-generation visual-paradigm generalization


    【解决方案1】:

    您认为这两种描述哪个更好?

    我认为下图所示的选项 3 更好。 Timer 将是可重用(概念上为 final)的通用类,它只是由单例包装器配置并由 usage dependency relationship 链接的实例

    VP 允许为这三个操作编写实现代码。代码生成过程中...为接口的操作编写代码实现是否正确...?

    我不知道如何正确配置 Visual Paradigm 的代码生成器以生成您想要的内容,但是尽管 C++ 接口是 just a class like any other 并且对于这个概念没有特殊的 keywordUML interface 的意思是仅描述contract,没有耦合实现。一些语言,如 C#Java 有特殊的 interface keyword 用于此目的,在编译器中硬编码无代码规则。

    因此,虽然 Visual Paradigm 最后可能会生成你想要的代码,但从 UML 的角度来看,用代码建模 interface 是错误的


    做出你的选择。如果您只想要执行 The 某事的代码,那么无论如何都要去破解它(正如@gilead-silvanas 建议的那样)。如果您想练习 UML 以在您未来使用不同语言的项目中使用,那么不要。

    还有一段时间,初始生成的代码会偏离初始设计图纸和代码生成器,您需要手动编辑它,即使您使用 Quantum Leaps Modeler for embedded systems 之类的工具也是如此。

    我会(定期)重新考虑与设计工具的斗争是否超过了代码生成的好处

    【讨论】:

    • 如果我错了,请纠正我。通过您的建模,可以确保类 TimerATimerB 的单一存在,因为相应的标志由两个单例包装器中的任何一个设置。实际实例化的是类Timer 的对象,用于尽可能多的可用单例包装器(这是通过TimerA::getInstance()TimerB::getInstance() 静态成员完成的)。那么,到底构造函数TimerA()TimerB() 没有被使用?我可以将参数从TimerATimerB 传递给Timer 类。我指的是,特别是moduleAddress。谢谢。
    • @UmbertoD。是的,这就是我的意思,TimerA()TimerB() 可能有类“静态”构造函数来初始化instance 变量。但是不要按字面意思理解,因为它适用于C#,其中计时器的滴答声将由附加到timer's even handler 的函数处理。几年来我一直没有活跃在C++ 世界中(我很高兴)。在C++ 中,您可能必须通过创建子类来实现它。所以我的回答在代码生成方面可能会产生很大的误导
    【解决方案2】:

    这可能只是 VP 让事情变得更快的简写。正如您所说,在代码生成时,它无论如何都会从接口中清除这些代码并将其放入实现类中。我认为这没有任何问题,因为重要的是生成的代码,在你的情况下是正确的。

    【讨论】:

    • 感谢您的回答。我最初的看法是Timer 实际上代表一个接口,因为它包含一组方法(API),每个特定模块(TimerATimerB 等)都必须实现。从 UML 的角度来看,我对概念上最可接受的解决方案持怀疑态度。另一个令人担忧的地方是写下 C++ 代码(在 VP 中),从而实现作为接口一部分的操作,而不是类。
    • 在我看来,从 UML 的角度来看,如果我们要严格遵循面向对象的规则,那么在接口中编写实现是不正确的。
    猜你喜欢
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多