Class 图的代码生成:两个 类 之间的组合不会改变生成的 Java 代码中的任何内容

Code Generation from Class Diagram: Composition between two classes does not change anything in generated Java code

我通过 Visual Paradigm 在 Visual Paradigm software, such that there there a COMPOSITION between these two classes. However, the generated code (in Java) is the same with OR without the association between these two classes. In other words, the generated code, if there is a composition between class A and B, is the same as when I deleted the composition between class A and class B. That is, the composition between classes is NOT considered in generated code 中创建了两个简单的 classes A 和 B。 解决方法是什么?

编辑: 根据@Christophe 的要求,我添加了一个测试示例项目的照片(class 图),以及两个 Java class 由 Visual Paradigm 生成,在两种情况下(两个 classes 之间有和没有组合关系)生成的代码完全相同。

Visual Paradigm 生成的代码:

public class Class {

private int attribute;

public void operation() {
    // TODO - implement Class.operation
    throw new UnsupportedOperationException();
}

}

public class Class2 {

private int attribute;

public void operation() {
    // TODO - implement Class2.operation
    throw new UnsupportedOperationException();
}

}

P.S. 我用 IBM Rational Rhapsody 试了一下,效果更好。也就是说,它在代码中更详细地生成模型的特征。请参阅下面由 IBM Rational Rhapsody 生成的代码,并比较与 Visual Paradigm 生成的代码的差异:

IBM Rational Rhapsody 生成的代码:

package Default;


//----------------------------------------------------------------------------
// Default/class_0.java                                                                  
//----------------------------------------------------------------------------

//## package Default 


//## class class_0 
public class class_0 {
    
    protected int attribute_0;      //## attribute attribute_0 
    
    protected class_1 itsClass_1;       //## link itsClass_1 
    
    
    // Constructors
    
    //## auto_generated 
    public  class_0() {
        initRelations();
    }
    
    //## operation Operation_1() 
    public void Operation_1() {
        //#[ operation Operation_1() 
        //#]
    }
    
    //## auto_generated 
    public int getAttribute_0() {
        return attribute_0;
    }
    
    //## auto_generated 
    public void setAttribute_0(int p_attribute_0) {
        attribute_0 = p_attribute_0;
    }
    
    //## auto_generated 
    public class_1 getItsClass_1() {
        return itsClass_1;
    }
    
    //## auto_generated 
    public void __setItsClass_1(class_1 p_class_1) {
        itsClass_1 = p_class_1;
    }
    
    //## auto_generated 
    public void _setItsClass_1(class_1 p_class_1) {
        if(itsClass_1 != null)
            {
                itsClass_1.__setItsClass_0(null);
            }
        __setItsClass_1(p_class_1);
    }
    
    //## auto_generated 
    public class_1 newItsClass_1() {
        itsClass_1 = new class_1();
        itsClass_1._setItsClass_0(this);
        return itsClass_1;
    }
    
    //## auto_generated 
    public void deleteItsClass_1() {
        itsClass_1.__setItsClass_0(null);
        itsClass_1=null;
    }
    
    //## auto_generated 
    protected void initRelations() {
        itsClass_1 = newItsClass_1();
    }
    
}
/*********************************************************************
    File Path   : DefaultComponent/DefaultConfig/Default/class_0.java
*********************************************************************/

第二个class代码:

package Default;


//----------------------------------------------------------------------------
// Default/class_1.java                                                                  
//----------------------------------------------------------------------------

//## package Default 


//## class class_1 
public class class_1 {
    
    protected int attribute_0;      //## attribute attribute_0 
    
    protected class_0 itsClass_0;       //## link itsClass_0 
    
    
    // Constructors
    
    //## auto_generated 
    public  class_1() {
    }
    
    //## operation Operation_1() 
    public void Operation_1() {
        //#[ operation Operation_1() 
        //#]
    }
    
    //## auto_generated 
    public int getAttribute_0() {
        return attribute_0;
    }
    
    //## auto_generated 
    public void setAttribute_0(int p_attribute_0) {
        attribute_0 = p_attribute_0;
    }
    
    //## auto_generated 
    public class_0 getItsClass_0() {
        return itsClass_0;
    }
    
    //## auto_generated 
    public void __setItsClass_0(class_0 p_class_0) {
        itsClass_0 = p_class_0;
    }
    
    //## auto_generated 
    public void _setItsClass_0(class_0 p_class_0) {
        if(itsClass_0 != null)
            {
                itsClass_0.__setItsClass_1(null);
            }
        __setItsClass_0(p_class_0);
    }
    
    //## auto_generated 
    public void setItsClass_0(class_0 p_class_0) {
        if(p_class_0 != null)
            {
                p_class_0._setItsClass_1(this);
            }
        _setItsClass_0(p_class_0);
    }
    
    //## auto_generated 
    public void _clearItsClass_0() {
        itsClass_0 = null;
    }
    
}
/*********************************************************************
    File Path   : DefaultComponent/DefaultConfig/Default/class_1.java
*********************************************************************/

如您所见,IBM 生成的代码包括关联(组合)和其他特征。

这是由 IBM Rational Rhapsody 生成的上述代码的 class 图:

图表是否提供了所需的内容?

在你的 VP 图中,你添加了一个组合关系,留下了很多未指定的东西:

  • 它不表示关联是否可导航
  • 不显示多重性
  • 未指定角色(即关联端名称)

这些中的每一个都可能成为正确生成代码的障碍:

  • 没有可导航性,该工具不知道您是否打算参考另一侧(或者如果没有可导航性,即没有可以轻松找到另一侧的参考)。
  • 如果没有多重性,该工具不知道它是否必须生成一个简单的 java 字段引用一个 object,或者 collection of objects
  • 没有角色,该工具不知道您要如何命名应该实现 associated/composed object.
  • 的 java 字段

不同的工具做出不同的假设。 VP 显示以下 tool-specific 行为:

  • 如果您打开您的组合规范,您会看到如果导航性未指定(这是特定于 VP 而不是 UML 标准),则假定在两个方向上都是正确的。
  • 如果图中未指定,则用于代码生成的默认多重性为 1。
  • 但是 缺少角色导致 java association/composition 无法生成: VP 不知道如何命名它。

如果图表足够,VP 生成构图

这里是我将用于演示目的的图表:

组成的规格如下:

如果有角色名(这里是A和B),很好生成结构关系对应的代码:

public class MyClassA {
    private long id;
    Collection<MyClassB> B;  // <========== only if role is in diagram
    public void doSomething() {
        // TODO - implement MyClassA.doSomething
        throw new UnsupportedOperationException();
    }
}

public class MyClassB {
    private string name;
    MyClassA A;   // <=========================
    public string getName() {
        return this.name;
    }
    public void setName(string name) {
        this.name = name;
    }
}

顺便说一句,正如我之前的回答中所解释的那样,如果您有一个关联而不是一个组合,则生成的代码是相同的,因为语义差异(排他性地包含在组合中并删除组合元素复合生命周期结束)很难自动化。

什么时候不生成作文?

如果从规范中删除角色名称,生成的代码会删除实现关联的 java 字段;生成的 类 看起来就像根本没有 composition/association:

public class MyClassA {
    private long id;
    public void doSomething() {
        // TODO - implement MyClassA.doSomething
        throw new UnsupportedOperationException();
    }
}
public class MyClassB {
    private string name;
    public string getName() {
        return this.name;
    }
    public void setName(string name) {
        this.name = name;
    }
}

这是您亲身体验过的结果。您可以故意使用此行为,例如在一侧而不是另一侧实现关联(例如,如果 B 不需要知道它拥有 A)。

缺少 VP 功能? 唯一真正缺少的是代码生成时关于可导航性和缺席角色之间不一致的警告消息。这样的消息会为您节省很多时间。

备注:

  • 在您的 IBM 图表中,角色名称就在那里。如果缺少角色名称,看看代码是否会如此全面将会很有趣。
  • 我用 BOUML 测试了行为。如果没有角色名,代码会生成一个匿名成员变量(再说一遍,楼主死了不会给你发明属性名):生成的代码中有组成,但是没有名字会导致编译错误。