simbologia sencillos objetos ejemplos diagrama clases c++ c uml enterprise-architect

c++ - sencillos - diagrama de objetos uml



RepresentaciĆ³n UML para punteros de funciĆ³n C/C++ (7)

¿Cuál sería la mejor representación de un puntero de función C / C ++ (fp) en un diagrama estructural UML?

Estoy pensando en usar un elemento de interfaz, incluso si está "degenerado" con la restricción de tener como máximo una sola operación declarada.

Encontré una propuesta en este documento: Guía del usuario de sincronización de C y UML, Sección 5.7.4 . Pero esto suena bastante engorroso y no muy útil en la práctica. Aunque sea desde un nivel muy bajo de visión semántica. Aquí hay un diagrama que muestra su concepto brevemente:

IMHO en C y C ++ los punteros de función se utilizan como una vista reducida de una interfaz que solo proporciona una función única y su firma. En C fp, también se utilizaría para implementar interfaces más complejas que declaren una estructura que contiene un conjunto de punteros de función.

Creo que incluso puedo lograr que mi herramienta UML particular (Enterprise Architect) reenvíe el código correcto y se sincronice con los cambios de código sin ningún daño.

Mis preguntas son:

  1. ¿La declaración de fp''s como parte de los elementos de la interfaz en UML proporcionaría una vista semántica correcta?
  2. ¿Qué tipo de estereotipo se debe utilizar para la declaración de fp único? Al menos tengo que proporcionar un código fuente en el código para que esta sea mi elección. (Descubrí que este estereotipo es propiedad de Enterprise Architect) y necesito definir un estereotipo apropiado para adaptar la generación de código. En realidad, he elegido el nombre del estereotipo "delegado", ¿esto tiene implicaciones o colisiones semánticas?
  3. En cuanto a C ++, ¿estaría anidando una interfaz estereotipada "delegada" en un elemento de clase suficiente para expresar un puntero de función de miembro de clase correctamente?

Aquí hay un diagrama de ejemplo de mis pensamientos para la representación en lenguaje C:

Este es el código C que debe generarse a partir del modelo anterior:

struct Interface1; typedef int (*CallbackFunc)(struct Interface1*); typedef struct Interface1 { typedef void (*func1Ptr)(struct Interface1*, int, char*); typedef int (*func2Ptr)(struct Interface1*, char*); typedef int (*func3Ptr)(struct Interface1*, CallbackFunc); func1Ptr func1; func2Ptr func2; func3Ptr func3; void* instance; }; /* The following extern declarations are only dummies to satisfy code * reverse engineering, and never should be called. */ extern void func1(struct Interface1* self, int p1, char* p2) = 0; extern int func2(struct Interface1* self, char*) = 0; extern int func3(struct Interface1* self, CallbackFunc p1) = 0;

EDITAR:
Todo el problema se reduce a lo que sería la mejor manera con la herramienta UML disponible y sus capacidades de ingeniería de código específicas. Así que he añadido la etiqueta de enterprise-architect .


Como su primer ejemplo, usaría un clasificador pero lo escondería en un perfil. Creo que lo han incluido para aclarar la explicación del concepto; pero en la práctica, toda la idea de los estereotipos es abstraer detalles en los perfiles para evitar el problema del "ruido". EA es bastante bueno para manejar perfiles.

Donde difiero de su primer ejemplo es que clasificaría el estereotipo de tipo primitivo y no el estereotipo de tipo de datos . El tipo de datos es un objeto de alcance de dominio, mientras que el tipo primitivo es un elemento atómico con semántica definida fuera del alcance de UML. Esto no quiere decir que no pueda agregar notas, especialmente en el perfil o darle un estereotipo muy claro como functionPointer.


Creo que prácticamente se podría envolver el puntero de función con una clase. Creo que UML no tiene que estar a la altura del código, ya que documentar el concepto es más importante.


El archivo de ayuda de EA tiene lo siguiente que decir sobre el tema de los punteros de función:

Al importar el código fuente de C ++, Enterprise Architect ignora las declaraciones de puntero de función. Para importarlos a su modelo, puede crear un typedef para definir un tipo de puntero de función y luego declarar los punteros de función usando ese tipo. Los punteros de función declarados de esta manera se importan como atributos del tipo de puntero de función.

Nota "podría". Esto es de la sección C ++, la sección C no menciona en absoluto los punteros de función. Por lo tanto, no están bien soportados, lo que a su vez se debe a la brecha entre el modelado y las comunidades de programación: los conceptos de lenguaje no trivial simplemente no se admiten en UML, por lo que cualquier solución será necesariamente específica de la herramienta.

Mi sugerencia es un poco complicada y un poco complicada, pero creo que debería funcionar bastante bien.

Debido a que en UML las operaciones no son de primera clase y no se pueden usar como tipos de datos, mi respuesta es crear entidades de primera clase para ellas, en otras palabras, definir tipos de punteros de función como clases.

Estas clases servirán para dos propósitos: el nombre de la clase reflejará la firma del tipo de la función para que se vea familiar para el programador en los diagramas, mientras que un conjunto de valores etiquetados representará los parámetros reales y los tipos de retorno para usar en la generación de códigos.

0) Es posible que desee configurar una tecnología MDG para los pasos 1-4.

1) Defina un tipo de valor etiquetado "retval" con el Detalle "Tipo = RefGUID; Valores = Clase;"

2) Defina un conjunto adicional de tipos de valores etiquetados con el mismo Detalle llamado "par1", "par2" y así sucesivamente.

3) Defina un perfil con un estereotipo de clase "funptr" que contenga un valor etiquetado "retval" (pero no etiquetas "par").

4) Modifique la Declaración de atributos y el Parámetro de los scripts de generación de código para recuperar "retval" (siempre) y "par1" - "parN" (donde esté definido) y genere la sintaxis correcta para ellos. Esta será la parte difícil y no he hecho esto realmente. Creo que se puede hacer sin demasiado esfuerzo, pero tendrás que intentarlo. También debe asegurarse de que no se genere ningún código para las definiciones de clase "funptr", ya que representan tipos anónimos, no typedefs.

5) En su proyecto objetivo, defina un conjunto de clases para representar los tipos C primitivos.

Con esto, puede definir un tipo de puntero de función como una clase «funptr» con un nombre como "long (*) (char)" para una función que toma un carácter y devuelve un valor largo.

En la etiqueta "retval", seleccione la clase "larga" que definió en el paso 4.

Agregue la etiqueta "par1" manualmente y seleccione la clase "char" como se indica arriba.

Ahora puede usar esta clase como el tipo de un atributo o parámetro, o en cualquier otro lugar donde EA permita una referencia de clase (como en la etiqueta "par1" de una clase "funptr" diferente; esto le permite crear fácilmente tipos de punteros para Funciones donde uno de los parámetros es en sí mismo un tipo de puntero de función).

El bit más complicado aquí es el número "par1" - "parN" etiquetas. Si bien es posible en EA definir varias etiquetas con el mismo nombre (es posible que tenga que cambiar las opciones de la ventana de valores etiquetados para verlas), no creo que pueda recuperar los diferentes valores en el script de generación de código (e incluso si podría no pensar que el orden se mantendría necesariamente, y el orden de los parámetros es importante en C). Así que deberías decidir el número máximo de parámetros de antemano. No es un gran problema en la práctica; La configuración de decir 20 parámetros debería ser suficiente.

Este método no es de ninguna ayuda para la ingeniería inversa, ya que EA 9 no le permite personalizar el proceso de ingeniería inversa. Sin embargo, el próximo EA 10 (actualmente en RC 1) lo permitirá, aunque no lo he examinado yo mismo, así que no sé qué forma tomará esto.


He podido conseguir algo parecido a trabajar con Enterprise Architect. Es un poco una solución pirata, pero satisface mis necesidades. Lo que hice:

  1. Crear un nuevo estereotipo de clase llamado FuncPtr. Seguí la guía aquí: http://www.sparxsystems.com/enterprise_architect_user_guide/10/extending_uml_models/addingelementsandmetaclass.html Cuando hice esto, hice una nueva vista para el perfil. Así que puedo mantenerlo contenido fuera de mi proyecto principal.

  2. Modificado las plantillas de código de clase. Básicamente, seleccione el lenguaje C, comience con la plantilla de clase y presione ''Agregar nuevo reemplazo de estereotipo'' y agregue FuncPtr como un nuevo reemplazo.

  3. Agregue el siguiente código a esa nueva plantilla:

%PI="/n"% %ClassNotes% typedef %classTag:"returnType"% (*%className%)( %list="Attribute" @separator=",/n" @indent=" "% );

  1. Modificado la plantilla de código de declaración de atributo. Igual que antes, añadiendo un nuevo estereotipo.

  2. Agregue el siguiente código a la nueva plantilla:

% PI = ""%% attConst == "T"? "const": ""%

% attType%

% attContainment == "Por referencia"? "*": ""%

% attName%

Eso es todo lo que tenía que hacer para instalar los punteros de función en Enterprise Architect. Cuando quiero definir un puntero de función simplemente:

  1. Crear una clase regular
  2. Agregue la etiqueta ''returnType'' con el tipo de devolución que quiero
  3. Añadir atributos para los parámetros.

De esta manera, creará un nuevo tipo que se puede incluir como atributos o parámetros en otras clases (estructuras) y operadores. No lo convertí en un operador en sí mismo porque, por lo tanto, no habría sido referenciado dentro de la herramienta como un tipo que puede seleccionar.

Así que es un poco intrépido, usar clases especiales estereotipadas como typedefs para punteros de función.


La definición de los punteros de función está fuera del alcance de la especificación UML. Además, es una característica específica del idioma que no es compatible con muchos programas de modelado UML. Así que creo que la respuesta general a su primera pregunta sugiere evitar esta característica. Los trucos que proporcionó solo son relevantes para Enterprise Architect y no son compatibles con otras herramientas de modelado UML. Aquí es cómo se admiten los punteros de función en algún otro software UML:

MagicDraw UML utiliza los estereotipos de << C++FunctionPtr >> para los miembros de la clase FP y << C++FunctionSignature >> para el prototipo de función.

Ejemplo de código (tomado del sitio oficial - vea "Viewlet de modelado de typedef y función para la generación de código C ++"):

class Pointer { void (f*) ( int i ); }

Modelo UML correspondiente:

Objecteering define los atributos de PF con la correspondiente nota TypeExpr de C ++.

Rational Software Architect de IBM no admite punteros de función. El usuario puede agregarlos al código generado en las secciones definidas por el usuario que se dejan sin tocar durante las transformaciones de código-> UML y UML->.


Me parece correcto. No estoy seguro de que deba sumergirse en los detalles de bajo nivel de la descripción del tipo y la relación de su puntero de función única. Por lo general, encuentro que una descripción es suficiente para detallar sin necesidad de descomponer los elementos internos de la misma.


Mi sensación es que usted desea asignar interfaces UML al lenguaje C de struct-with-function-pointers.

Interface1 es el elemento importante en su modelo. La declaración de tipos de objetos de puntero de función en todo el lugar hará que sus diagramas sean ilegibles.

Enterprise Architect le permite especificar sus propios generadores de código. Busque el marco de plantilla de código . Debería poder modificar el generador de código preexistente para C con la ayuda de uno o dos estereotipos nuevos.