La programación orientada a objetos (OOP) es un paradigma de programación utilizado en los lenguajes de programación, en los entornos de desarrollo y en las industrias. En este artículo, discutiremos las preguntas más frecuentes sobre LabVIEW OOP. Tenga en cuenta que este documento asume que se tiene una comprensión básica de la terminología y los procesos de OOP.
C++ es un lenguaje funcional basado en texto. LabVIEW es un lenguaje gráfico de flujo de datos. Los distintos paradigmas requieren diferencias en cómo presentan las características de OOP:
Para obtener más explicaciones sobre estas diferencias, consulte Programación Orientada a Objetos de LabVIEW: Las Decisiones Detrás del Diseño
¿Cuál es el beneficio para un usuario nuevo en LabVIEW?
¿Cuál es el beneficio para un programador G experimentado que no practica OOP?
Para un ejemplo de pruebas y medidas que contrasta un enfoque basado en tareas y un enfoque orientado a objetos, consulte el ejemplo Board Testing que se incluye con LabVIEW 8.2 y versiones posteriores.
labview\examples\lvoop\BoardTesting\Board Testing.lvproj
LabVIEW 8.2 y posterior viene con varios ejemplos de programación orientada a objetos de LabVIEW. Consulte también la sección de Recursos Adicionales de este documento.
El comienzo más simple es convertir las definiciones de tipo existentes a clases de LabVIEW. Puede hacerlo haciendo clic derecho en una typedef en la ventana del Project Explorer y seleccionar Convert Contents to Class en el menú de acceso directo. Consulte la Ayuda de LabVIEW para obtener más información sobre cómo crear clases de LabVIEW.
Nota: LabVIEW no conserva el valor predeterminado de controles y constantes durante el proceso de conversión. Para acceder a los detalles de las typedefs, agregue VIs a aquellas clases que necesitan tener acceso a la definición de tipo. Esta agrupación de VIs basada en los datos sobre los que actúan es fundamental para la programación orientada a objetos. Consulte las dos presentaciones de NI Week 2006 que se enumeran a continuación en la sección Información Adicional para obtener más información sobre el diseño orientado a objetos.
Consulte el ejemplo Reference Object que se incluye con LabVIEW 8.2 y versiones posteriores.
labview\examples\lvoop\ReferenceObject\ReferenceObject.lvproj
Esencialmente, hace que los datos privados de una clase sean una referencia. El ejemplo muestra cómo usar una referencia de cola de un solo elemento para este propósito. También puede usar el GOOP Toolkit (consulte la sección del LabVIEW Object-Oriented Programming & GOOP Toolkit a continuación).
Con LabVIEW 2009, la orientación de objetos ahora es compatible con los dispositivos en tiempo real de LabVIEW. La programación orientada a objetos no es compatible en tiempo real con LabVIEW 8.6 y anteriores.
Cuando cierra un VI, LabVIEW conoce todos los subVI que no se utilizarán como resultado al cerrar ese VI, por lo que LabVIEW puede solicitar guardarlos todos a la vez. Sin embargo, las clases no pueden dejar la memoria hasta que todas las instancias de datos hayan dejado memoria, y LabVIEW no puede saber si cerrar un determinado VI cerrará realmente la última instancia de datos. Un VI puede no tener ninguna referencia a la clase en su código, pero aún puede tener una instancia de la clase almacenada en una variante en algún lugar. Si todos los VIs estuvieran inactivos, LabVIEW podría determinar cuántas instancias de la clase se irán con este conjunto de VIs y ver si eso explica todas las instancias de la clase que quedan en la memoria. Entonces LabVIEW sabría que la clase está dejando memoria con los VIs y podría preguntar sobre la clase en el mismo cuadro de diálogo Save Changes que los otros VIs/bibliotecas. Pero si algún VI aún se está ejecutando, el número de instancias puede fluctuar constantemente. Y mientras se ejecutan los VI, los datos se pueden ocultar en ubicaciones imposibles de buscar, como una cola o un notificador, y estos espacios adicionales solo se eliminan cuando el VI se encuentra inactivo. Un VI en ejecución también puede crear nuevas instancias en ubicaciones que LabVIEW ya verificó. Por lo tanto, es imposible contar instancias mientras se ejecutan los VIs. Dado que LabVIEW no cancela los VIs en ejecución hasta después de preguntar si se guardarán o no los cambios, LabVIEW aún no puede saber si la clase dejará memoria. Incluso si todos los VIs estuvieran inactivos y LabVIEW pudiera hacer la búsqueda de datos, esa búsqueda sería extremadamente lenta, por lo que LabVIEW no lo intenta en absoluto. Por lo tanto, cuando cierra un VI, las clases con frecuencia terminan obteniendo su propio cuadro de diálogo Save Changes.
El único momento en que LabVIEW puede incorporar clases con todo lo demás y ofrecer un solo cuadro de diálogo Save Changes es cuando está cerrando el proyecto. En ese caso, debido a que cada VI en el proyecto se cerrará, LabVIEW sabe que eso significa que todas las instancias de datos de la clase se eliminarán sin más explicación.
Puede encontrar una descarga gratuita de GOOP Development Suite en el sitio web de NI.
Sí
La mayoría de los usuarios encontrarán que las clases de LabVIEW funcionan mejor para sus aplicaciones. Las clases de LabVIEW se comportan como los clústeres con los que los usuarios están familiarizados.
Puede usar referencias para manejar la comunicación entre secciones de código que se ejecutan en paralelo. Para los clientes que realmente están modelando recursos del sistema, el modelo de referencia se vuelve muy útil y pueden desear crear clases de GOOP. Las referencias también son valiosas al crear estructuras de datos de gráficas y árboles. Incluso en estos casos, los campos de datos en el núcleo de la clase GOOP pueden ser clases de LabVIEW. Sin embargo, cuando use referencias o cualquier otro medio de comunicación entre secciones de código paralelo, debe saber sobre bloqueo, condiciones de carrera y otras complejidades que surjan.
Puede usar el modelo de referencia para garantizar que nunca duplique esa clase en la memoria. Para una clase que requiere mucha memoria, esto puede ser una ventaja.
No es necesario que reescriba las clases GOOP existentes como clases de LabVIEW. Una razón es que nunca debe destruir el código de trabajo sin una razón convincente, y las clases de GOOP continuarán funcionando en LabVIEW 8.2 y posteriores. Después de todo, el GOOP Toolkit está escrito en LabVIEW. Además, cambiar el código que funciona por referencia en código que funciona por valor es una tarea importante.
Una razón para la transición es el rendimiento. Se genera una gran sobrecarga para un objeto cuando cada llamada de función tiene que buscar la referencia, bloquear la instancia y extraer los datos. El GOOP Toolkit hace un trabajo increíble al minimizar esta sobrecarga, pero no obstante está ahí. Además, operar usando un refnum evita muchas operaciones que de otro modo podrían proceder en paralelo. Si tiene una clase que no necesita el comportamiento por referencia y sí necesita un mejor rendimiento, entonces podría considerar la transición de la clase GOOP a la clase de LabVIEW.
Esta es una pregunta que debe responderse dependiendo del caso. LabVIEW no tiene una forma automatizada de realizar la conversión.
Debido a la consistencia con el flujo de datos y la implementación nativa del compilador del despacho dinámico, las clases de LabVIEW superarán a las clases de GOOP en situaciones equivalentes. Dicho esto, hay muy pocas situaciones equivalentes. Las clases de LabVIEW están diseñadas para reemplazar clústeres y mejorar el flujo de datos. Las clases de GOOP son una forma de agregar referencias a LabVIEW. Sirven para dos propósitos diferentes en el lenguaje. Al crear nuevas clases, debe tomar la decisión entre una clase de GOOP o una clase de LabVIEW en función de la funcionalidad que necesita la clase, no en función de las predicciones de rendimiento.
Evaluar en una variedad de PCs muestra que el rendimiento entre estos dos es casi idéntico. Consulte la siguiente pregunta para obtener más información sobre el rendimiento.
Un subVI de despacho dinámico tiene una pequeña sobrecarga cuando LabVIEW busca qué subVI invocar. La sobrecarga es constante. No aumenta a medida que agrega más clases o cuando agrega más VIs dinámicos a una clase. Puede haber un impacto en el rendimiento si la llamada del subVI tiene que hacer copias adicionales de los parámetros para que coincidan con la funcionalidad del subVI actual que LabVIEW invoca. Puede evitar esto conectando las terminales del panel frontal de entrada a las terminales del panel frontal de salida incluso en VIs dinámicos que nunca espera llamar (por ejemplo, VIs primarios que existen solo para definir el panel de conectores para que los secundarios los anulen). Consulte Programación Orientada a Objetos de LabVIEW: Las Decisiones Detrás del Diseño para obtener detalles sobre cómo el despacho dinámico puede alcanzar un rendimiento general constante.
Una clase de LabVIEW es un tipo de biblioteca de proyectos. Es una biblioteca de proyectos dedicada a la tarea de definir un tipo de datos. Al igual que una biblioteca de proyecto, la clase de LabVIEW define el alcance y el espacio de nombres para sus VIs miembros, y un VI puede ser propiedad de una sola clase de LabVIEW.
La clase de LabVIEW tiene un control de datos privados. Este es un VI de control que define los valores de datos de la clase. Este control especial no forma parte de otros tipos de bibliotecas, y en realidad se guarda dentro del archivo de clase. Las clases de LabVIEW tienen todas las propiedades que tienen las bibliotecas y algunas propiedades adicionales. Puede ver las propiedades adicionales en el cuadro de diálogo Class Properties en las páginas Inheritance, Probes y Wire Appearance.
La única capacidad que tienen las bibliotecas de proyecto que las clases de LabVIEW no tienen es la capacidad de contener sub-bibliotecas.
Si un VI usa una clase de LabVIEW, al cargar el VI se carga la clase, tal como un VI carga todos sus subVIs. Una clase de LabVIEW a su vez carga todos sus VIs miembros y su clase primaria. Las clases principales no activan automáticamente la carga de sus clases secundarias. Las primarias no tienen ningún vínculo con las secundarias. Un VI miembro de uno primario puede usar una clase secundaria y, por lo tanto, LabVIEW carga la clase secundaria.
"Por valor" significa que el cable transporta datos reales del tipo de cable. "Por referencia" significa que el cable lleva una referencia a los datos del tipo, y LabVIEW almacena los datos reales en algún repositorio central. La mayoría de los tipos de datos en LabVIEW, incluyendo números, arreglos, clústeres, secuencias, Booleanos y rutas son por valor. Por lo general, los únicos tipos que son por referencia son aquellos que usan comunicaciones o reflejan recursos del sistema, como refnums de archivos, refnums de cola y refnums de VI Server. Las clases de LabVIEW son por valor. En la sintaxis por valor, cada objeto tiene sus propios valores de datos, que puede modificar independientemente de otros objetos. En la sintaxis por referencia, hay una sola instancia de datos a la que se refieren varios objetos. Si un objeto modifica los datos, debe tener cuidado de no entrar en conflicto con otros objetos que están leyendo y escribiendo esos datos. Los principales pros y contras son:
Consulte Programación Orientada a Objetos de LabVIEW: Las Decisiones Detrás del Diseño.
NI no tiene una herramienta UML nativa. Endevo crea una herramienta para generar clases a partir de diagramas UML y generar diagramas UML a partir de código. La herramienta actualmente funciona para las clases de GOOP (consulte la sección LabVIEW Object-Oriented & GOOP Toolkit arriba), pero una próxima versión también admitirá las clases de LabVIEW.
Make Current Value Default es una característica valiosa de LabVIEW. Puede usarlo con frecuencia para construir VIs de prueba. Esta característica no es compatible con las clases de LabVIEW en LabVIEW 8.2 y posteriores debido a la complejidad de proporcionar una buena interfaz de usuario para que el usuario sepa cuándo los datos son distintos a los valores predeterminados, a pesar de que el usuario realmente no puede ver los datos porque los datos son privados. Esta característica es de alta prioridad para ser incluida en una futura versión de LabVIEW.
Los VIs dinámicos reentrantes no son características compatibles en LabVIEW 8.2. Debido a que los nodos de subVI dinámico en tiempo de edición no saben qué LabVIEW subVI invocará realmente en tiempo de ejecución, cada nodo tendría que crear clones de todos los subVIs posibles. Esto resulta ser costoso en cuestión de memoria.
(LabVIEW 8.5) Usted puede usar VIs dinámicos reentrantes en LabVIEW 8.5.
Puede configurar un VI de despacho dinámico para que sea recursivo o para usarse como parte de su propia definición. Los VIs recursivos pueden llamarse a sí mismos en su propio diagrama de bloques, incluyendo el diagrama de bloques de subVIs. La recursión es útil si desea operar muchas veces en la salida del mismo proceso. Puede configurar un VI miembro de despacho dinámico para permitir la recursión, configurándolo para que sea reentrante y comparta clones entre instancias.
Complete los siguientes pasos para configurar un VI para recursión.
Nota: No tener en cuenta la recursión infinita causa un uso innecesario de la memoria y puede bloquear LabVIEW. Para evitar una recursión infinita, considere llamar al VI recursivo en una estructura de Caso.