# Aprendiendo C# y Revit API (III)

Advertencia

Esto no es un curso de programación, ni pretende serlo, simplemente son comentarios e ideas de un aspirante a conocer C# y la API de Revit; si detectas algún error puedes contactar conmigo o dejar un comentario en esta entrada.

Creación de una Clase

Ya conocemos que la Programación Orientada a Objetos (POO) se caracteriza por el uso de ejemplares concretos de una determinada plantilla que previamente hemos definido; si hablamos con terminología más ortodoxa diríamos que "un programa escrito según el paradigma POO contendrá únicamente objetos", es decir, instancias de las clases definidas previamente por el desarrollador (o disponibles en el framework .NET).

Supongamos que vamos a diseñar un programa que va a trabajar con elementos constructivos. El primer paso que daremos será definir esas clases que nos permitirán generar posteriormente los objetos con los que trabajará nuestro programa.

Comenzaremos por definir una clase que agrupe a todos los elementos constructivos existentes en un edificio; la denominaremos "ElementoConstructivo":

    class ElementoConstructivo
    {
        // Atributos de la clase ElementoConstructivo

        // Propiedades de la clase ElementoConstructivo

        // Métodos de la clase ElementoConstructivo

        // Constructores de la clase ElementoConstructivo
    }

Ahora debemos comenzar a definir los miembros que componen dicha clase, distinguiendo principalmente entre:

  • Atributos (campos)
  • Propiedades
  • Métodos
  • Constructores

Atributos (campos)

Los atributos, o campos, de una clase son variables asociadas a dicha clase que pueden ser de multitud de tipos y para los que debemos controlar siempre su accesibilidad, es decir, que región del programa tiene acceso a dicho miembro de la clase.

En nuestro caso, vamos a definir dos variables privadas: "id", de tipo "int", y "nombre", de tipo "string":

        // Atributos de la clase ElementoConstructivo
        private int id;
        private string nombre;

Propiedades

Generalmente, no suele ser buena idea permitir que los valores de los atributos de una clase se lean o modifiquen directamente desde el exterior de la clase, principalmente porque perderíamos la capacidad de verificar cómo se devuelven o establecen dichos valores. Por este motivo se definen las propiedades, identificadas generalmente con el nombre del atributo en mayúsculas, que controlan cómo se recupera (get) o se establece (set) el valor de un atributo.

En nuestro caso, podemos verificar que el atributo "id" sea siempre mayor que 0 y que el atributo "nombre" no quede vacío (valor 'null' o espacios en blanco):

       // Propiedades de la clase ElementoConstructivo
        public int Id
        {
            get { return id; }
            set
            {
                if (value <= 0) id = 0;
                else id = value;
            }
        }
        public string Nombre
        {
            get { return nombre; }
            set
            {
                if (string.IsNullOrWhiteSpace(value)) nombre = "Sin especificar";
                else nombre = value;
            }
        }

Métodos

Además de controlar la información contenida en los atributos de la clase (a través de las propiedades), en la POO existe el concepto de método, que podríamos definir como una acción que se ejecuta en una clase u objeto (dependiendo del tipo de método implementado) como respuesta a un mensaje/llamada recibido.

En nuestro ejemplo, al ser una clase muy sencilla vamos a poder implementar pocos métodos. Sin embargo, vamos a suponer que necesitamos que nuestro objeto nos envíe un "string" (cadena de caracteres) con su nombre e identificador separados por el caracter "/"; para ello, implementaremos el método "Dni", haciendo un guiño al Documento Nacional de Identidad de España:

       // Métodos de la clase ElementoConstructivo
        public string Dni()
        {
            string mensaje = this.Nombre + " / " + this.Id.ToString();
            return mensaje;
        }

Constructores

Por último, es habitual definir uno o más constructores que serán las funciones que se invoquen cuando decidimos instanciar una clase, es decir, generar un objeto a partir de la clase que hemos definido.

Los constructores son fáciles de identificar porque tienen el mismo nombre que la clase; incluso podemos definir varios constructores que respondan a diferentes parámetros, lo que se conoce como "sobrecargas".

Para nuestro ejemplo, vamos a crear un único constructor que reciba dos argumentos, 'i' y 'n', que serán los valores que se asignarán a los atributos internos del objeto, utilizando para ello las propiedades definidas anteriormente:

        // Constructores de la clase ElementoConstructivo
        public ElementoConstructivo(int i, string n)
        {
            Id = i;
            Nombre = n;
        }

Creación de un objeto

Una vez que tenemos definida nuestra clase "ElementoConstructivo" podemos crear un pequeño programa en el que crearemos un par de objetos diferentes y, posteriormente, invocaremos algún método para que nos devuelvan cierta información de los mismos.

En C#, el compilador buscará entre los archivos fuente (extensión "cs") un único método denominado "Main" que será estático (static), no devolverá ningún valor (void) y cuyo argumento será de tipo string (string[] arg).

Este será el punto de entrada y salida del programa.

    class Program
    {
        static void Main(string[] args)
        {
        }
    }

Dentro del método "Main", definiremos e inicializaremos cuatro variables que utilizaremos como argumentos para la creación de los dos objetos de la clase "ElementoConstructivo":

            // Variables de los objetos
            int idObjeto1 = 12345;
            string nombreObjeto1 = "Muro";
            int idObjeto2 = 67890;
            string nombreObjeto2 = "Forjado";

A continuación, crearemos dos instancias de la clase "ElementoConstructivo" que denominaremos "elemento1" y "elemento2". Utilizaremos el constructor definido al que pasaremos como argumentos las variables definidas previamente:

            // Creación de objetos
            ElementoConstructivo elemento01 = new ElementoConstructivo(idObjeto1, nombreObjeto1);
            ElementoConstructivo elemento02 = new ElementoConstructivo(idObjeto2, nombreObjeto2);

Finalmente, mostraremos por pantalla dos cadenas de texto que hagan uso del método "Dni()" que definimos para la clase "ElementoConstructivo":

            // Utilizar el método Dni() en ambos objetos
            System.Console.WriteLine("El elemento 1 es '{0}'", elemento01.Dni());
            System.Console.WriteLine("El elemento 2 es '{0}'", elemento02.Dni());

La salida de la consola será:

El elemento 1 es 'Muro / 12345'
El elemento 2 es 'Forjado / 67890'

Conclusiones

Hemos visto que una clase es una 'plantilla' que definimos para poder crear objetos.

Esos objetos los creamos utilizando constructores que permiten definir los atributos que poseerá dicha instancia de la clase (objeto).

Además, podremos crear propiedades y métodos que permitirán a los diferentes objetos responder a los mensajes que le lleguen, devolviendo valores o realizando operaciones internas con los atributos de la clase.

Aprendiendo C# y Revit API (II)

Advertencia

Esto no es un curso de programación, ni pretende serlo, simplemente son comentarios e ideas de un aspirante a conocer C# y la API de Revit; si detectas algún error puedes contactar conmigo o dejar un comentario en esta entrada.

Lenguajes de programación

La creación de un programa informático guarda algunas similitudes con la construcción de un edificio: se trata de generar un proyecto (conjunto de instrucciones) que el proyectista (desarrollador) entrega a la empresa constructora (ordenador) para que ejecuten una determinada construcción (programa).

Por tanto, para que la información fluya de forma correcta y todos entiendan el trabajo que deben realizar, el envío de instrucciones entre el proyectista (desarrollador) y la empresa constructora (ordenador) debe realizarse en un idioma estandarizado y codificado.

En el caso concreto de la programación, debemos de tener presente que nuestro el ordenador es una máquina "tonta" que únicamente entiende dos estados (dos niveles de voltaje) en sus componentes internos: 0 y 1; es lo que conocemos como "lenguaje máquina".

Este lenguaje máquina es específico de cada procesador (modelo de ordenador), además de complejo de leer y entender por humanos, por lo que los programadores han ideado otros "lenguajes de alto nivel", que se aproximan más a la sintaxis habitual del lenguaje humano, que nos ayudan a escribir programas de forma más sencilla y no nos exigen conocer al detalle la estructura interna de cada procesador. Paralelamente, se han desarrollado traductores entre lenguajes de alto nivel y lenguajes máquina, conocidos como "compiladores", que se encargan de convertir las instrucciones escritas por los programadores en instrucciones entendibles por los procesadores de los equipos.

El lenguaje C# y .NET Framework

Centrándonos en el lenguaje C#, que se utiliza principalmente para trabajar con la API de Revit, debemos saber que se trata de uno de los lenguajes de programación de alto nivel soportados por .NET Framework, el conjunto de herramientas/soluciones desarrollado por Microsoft para facilitar a la creación de aplicaciones.

.NET Framework se encarga de convertir nuestro programa escrito en C# (o en cualquier otro lenguaje soportado por la plataforma .NET) a un lenguaje intermedio, denominado Common Intermediate Language (CIL), que luego es ejecutado en cada ordenador gracias al uso de una máquina virtual denominada Common Language Runtime (CLR).

Es decir, nuestro programa no se compila expresamente para una máquina/arquitectura concreta, sino que es traducido a un lenguaje intermedio que es interpretado por un compilador Just-In-Time que traduce en tiempo real nuestro código al lenguaje máquina soportado por el procesador en el que corre nuestro programa.

Por todo esto, utilizar un lenguaje como C# bajo .NET Framework nos ofrece la ventaja de desarrollar nuestro programa sin preocuparnos por el equipo/plataforma que lo ejecutará después: sólo necesitaremos que exista la máquina virtual .NET en la plataforma en la que correremos nuestro programa.

Tipo de lenguaje y POO

Si nos centramos en las características propias del lenguaje C# podemos decir que se trata de un lenguaje de programación orientado a objetos, un paradigma de programación que se basa en organizar los programas como conjuntos de objetos que poseen determinados atributos y funcionalidades.

Un ejemplo sencillo: si estuviésemos trabajando en un programa de modelado BIM, podríamos diseñar un objeto "muro" que tuviese una serie de atributos (altura, longitud, espesor, material, etc.) y que tendría funcionalidades asociadas como "Vincula tu altura a un nivel" o "Cambia tu directriz".

En resumen, un programa diseñado bajo el paradigma de la Programación Orientada a Objetos (POO) se basará en la definición de objetos, con sus atributos y funcionalidades diferentes, que se irán relacionando entre sí mediante de mensajes.

Clases

Por tanto, el trabajo del desarrollador de software será abstraer la estructura básica de esos objetos (caracterísitcas y acciones) que compondrán nuestro programa, y crear una serie de plantillas genéricas, denominadas "clases", que permitan al programa construir posteriormente objetos específicos.

Es decir, nuestro trabajo será definir la clase "Muro", que poseerá una serie de atributos (características) y métodos (acciones que pueden realizar), y durante la ejecución del programa iremos creando "objetos" que serán "instancias o ejemplares" (concreciones en definitiva) de esa clase "Muro".

Estructura de un programa en C

Según indica la Guía oficial de C# escrita por Microsoft, un programa escrito en C# tendrá la siguiente estructura básica:

Los principales conceptos organizativos en C# son programas, espacios de nombres, tipos, miembros y ensamblados. Los programas de C# constan de uno o más archivos de origen. Los programas declaran tipos, que contienen miembros y pueden organizarse en espacios de nombres. Las clases e interfaces son ejemplos de tipos. Los campos, los métodos, las propiedades y los eventos son ejemplos de miembros. Cuando se compilan programas de C#, se empaquetan físicamente en ensamblados. Normalmente, los ensamblados tienen la extensión de archivo .exe o .dll, dependiendo de si implementan aplicaciones o bibliotecas, respectivamente.

Para ampliar información

Os dejo algunos enlaces interesantes que desarrollan las ideas principales de esta entrada del diario:

Aprendiendo C# y Revit API (I)

El comienzo de un nuevo año suele ser una fecha adecuada para plantearse nuevos objetivos y retos en nuestra faceta personal y profesional.

En mi caso particular, y llevando esta lista de propósitos al plano profesional, 2019 se presenta como un año de nuevos proyectos (en un futuro espero poder escribir sobre ellos) para los que siempre es necesario mantenerse actualizado e ir adquiriendo nuevos conocimientos y habilidades.

Concretamente, en lo que respecta al uso de herramientas BIM, me he propuesto dar un salto de calidad en mis conocimientos sobre programación: ir más allá de las posibilidades que Dynamo ofrece en el campo de la automatización de tareas (que no son pocas) y abrazar las bondades de la API de Revit.

¿Qué es una API y para qué sirve?

En pocas palabras, podríamos definir una API (Application Program Interface) como un conjunto de herramientas que un determinado software (Revit en este caso) ofrece a los desarrolladores para facilitarles la creación de pequeños, o grandes, programas/utilidades/rutinas que hagan uso de las capacidades principales del programa y, eventualmente, las mejoren y amplíen.

The following are general areas where the API is suitable:

- Creating add-ins and macros to automate repetitive tasks in the Autodesk Revit user interface

- Enforcing project design standards by checking for errors automatically

- Extracting project data for analysis and to generate reports

- Importing external data to create new elements or parameter values

- Integrating other applications, including analysis applications, into Autodesk Revit products

- Creating Autodesk Revit project documentation automatically

Online Autodesk Revit Help

¿Qué necesito para trabajar con la API de Revit?

La propia Autodesk recomienda 4 puntos fundamentales para comenzar a trabajar con la API de Revit:

1. A working understanding of Autodesk Revit.

2. An installation of an Autodesk Revit-based product, including the Software Development Kit.

3. MS Visual Studio 2015 Express Edition (C# or VB.NET). Microsoft Visual Studio 2015 Professional is recommended, though, as Express editions do not support DLL debugging. Alternatively, you can use the built-in SharpDevelop development environment in Revit.

4. Some experience in a .NET based development language. (Autodesk Revit API examples are provided in C# and Visual Basic.NET.)

Los tres primeros requisitos resultan bastante evidentes y accesibles para alguien con experiencia trabajando en Revit: debes conocer el funcionamiento del propio Revit, disponer de una instalación del mismo y utilizar un IDE (Entorno de Desarrollo Integrado) que permita desarrollar utilizando el framework .NET.

Sin embargo, el cuarto requisito es sin duda el mayor handicap a la hora de enfrentarse al desarrollo con la API de Revit: conocer algún lenguaje de programación compatible con el framework .NET; concretamente, Autodesk recomienda trabajar con el lenguaje C# (pronunciado ‘Si Sharp’).

¿Cómo aprendo a programar con C#?

La programación es una disciplina que requiere de ciertas habilidades y estructuras mentales muy concretas (abstracción, análisis, creatividad…) pero, sobre todo, es necesario querer aprender y dedicar tiempo.

En la red existen millones de recursos para comenzar a programar en C#:

En mi caso particular, he optado por adquirir una copia digital en Amazon del libro “Microsoft C#. Curso de Programación. 2ª edición” escrito por Francisco Javier Ceballos Sierra: me gusta la idea de comenzar por un manual estructurado, que me permita adquirir los conocimientos básicos del lenguaje y, a partir de ahí, lanzarme a buscar otras fuentes y referencias para profundizar en los temas que vaya necesitando para mis pequeños proyectos de desarrollo.

Diario

Para forzarme a mantener un ritmo constante de dedicación y aprendizaje, me he auto-impuesto la obligación de escribir un diario de aprendizaje, del que estás leyendo la primera entrada, en el que ir plasmando mis avances y experiencias (se dice que para aprender algo es recomendable escribir sobre ello…).

Además, tengo la intención de publicar mis pequeños proyectos de prueba, para lo cual me he creado una cuenta en GitHub (que tengo que aprender a usar e integrar con Visual Studio).

class AprendiendoCSharpYRevitAPI
{
    static void Main(string[] args)
    {
        System.Console.WriteLine("¡Arrancamos!");
    }
}