domingo, 28 de febrero de 2016

Intro TypeScript - Open Close Principle

Hoy haré una pequeña prueba de concepto para ver como funciona un poco por encima TypeScript. Me dispongo a implementar el clásico ejemplo de calculador de áreas aplicando Open Close Principle de SOLID. Me parece un buen ejemplo para ver como usar mecanismos OOP en TypeScript.

TypeScript es un lenguaje open source creado sobre el 2012 y mantenido por Microsoft. Es un lenguaje basado en javascript que permite trabajar con clases y usar mecanismos OOP que no disponemos en javascript. El código TypeScript no se compila sino que se transpila, es decir, el compilador de TypeScript se encarga de traducir el código a javascript. Existen otras opciones como EcmaScript 6 o CoffeScript, similares que no entro a comparar porque tendría trabajo solo decir que si usas Visual Studio como IDE para desarrollar javascript seguramente la mejor opción es TypeScript por esto:



En la página oficial de TypeScript podemos encontrar ejemplos y el handbook que va bien para echar un vistazo a que se puede hacer.

En primer lugar comentar que para la prueba de concepto he usado Visual Studio 2015 en un aplicación cordova, en realidad no voy a pasarla a ningún dispositivo móvil simplemente he optado por este tipo de proyecto para la prueba de concepto porque la plantilla ya te lo da todo OOB para empezar a jugar con TypeScript. Destacar que se integra perfectamente con el IDE Visual Studio.

El ejemplo que voy a implementar lo he basado en este post de CodeProject donde está explicado como aplicar el principio en C#.

En primer lugar crearé una interface, IShape con un método Area():
module AreaCalculator {
    "use strict";

    export interface IShape {
        Area();
    }
}
Como veis he creado un module, ya que nos aislará del contexto global y de paso nos permitirá separar las clases, interfaces y demás que componen el servicio en diferentes archivos lo cual facilita el mantenimiento y trabajo equipo. Ahora que tenemos la interface, crearemos 2 formas que la implementen... un circulo y un cuadrado:
module AreaCalculator {
    "use strict";    

    export class Circle implements IShape {
        protected radius: number;

        constructor(radius: number) {
            this.radius = radius;
        }

        Area() {
            return this.radius * Math.PI;
        }
    }
}
module AreaCalculator {
    "use strict";

    export class Square implements IShape {
        protected Height: number;

        constructor(Height: number) {
            this.Height = Height;
        }

        Area() {
            return this.Height * this.Height;
        }
    }
}
Ahora que tenemos las formas ya podemos implementar el calculador de área.
module AreaCalculator{
    "use strict";

    export class Calculator implements IShape {
        protected shapes: Array;

        constructor() {
            this.shapes = new Array();
        }

        AddShape(shape: IShape) {
            this.shapes.push(shape);
        }

        Area() {
            var area: number = 0;
            this.shapes.forEach(function (shape) {
                area += shape.Area();
            });

            return area;
        }
    }
}
Por último edito el fichero root/scripts/index.ts, que es el punto de entrada de la aplicación. Tenemos que añadir este fragmento de código a la función window.onload:
//Area Calculator
var calc = new AreaCalculator.Calculator();
calc.AddShape(new AreaCalculator.Circle(10));
calc.AddShape(new AreaCalculator.Square(20));
alert(calc.Area());
Esto me muestra un mensaje con el resultado de la suma del área de las dos formas que hemos añadido. Si nos creásemos una tercera forma como podría ser un triangulo no sería necesario modificar AreaCalculator, simplemente tendríamos que hacer que implemente IShape y ya podríamos sumar su area a la del resto de formas.

Hasta aquí el artículo de hoy, si no conocías TypeScript ahora ya tienes alguna noción. Recuerda que puedes seguir areaTIC en las redes sociales y cualquier comentario siempre es bienvenido. Hasta la próxima!

miércoles, 24 de febrero de 2016

Unit Testing in Javascript Visual Studio 2015

Hoy hablaremos de unit testing y veremos algunas herramientas que nos pueden ayudar en proyectos javascript. El articulo es un poco extenso se podría decir que os comparto mis apuntes sobre este tema y de paso explico como me lo he montado para implantar testing en proyectos javascript usando el IDE Visual Studio 2015. Antes de hablar de herramientas y ver ejemplos sobre como integrarlas en nuestros proyectos javascript me veo obligado a hablar de unit testing, consideraciones previas, beneficios, etc. Si ya conoces la teoría y quieres info sobre como integrar diferentes herramientas de unit testing para proyectos javascript en Visual Studio 2015. ves directo al caso práctico.

Un poco de teoría


El proposito que se persigue con unit testing es tener herramientas que testeen nuestra aplicación en busca de errores o comportamientos no deseados. Un test unitario consiste en testear las funcionalidades de una clase, objeto o componente. Generalmente todos en algun momento hemos trabajado en sitios y proyectos donde no hay testeo unitario. Es fácil (aunque cada vez menos) encontrarte escenarios donde se considere que el testing unitario es un coste que no aporta demasiado, que complica y hace encarecer el proyecto. La madurez y la experiencia de haber estado en proyectos que se han descontrolado me hacen dar la razón a todos aquellos defensores del unit testing y técnicas como TDD (Test driven development) o como BDD (Bevahiour Driven Development). En este post no entraré en detalle a explicar todas las técnicas de testing ni como aplicarlas en parte porque ya hay post y libros dedicados a estos escritos por la gente que realmente sabe de la materia...

Es fácil pensar en testing como un tiempo que inviertes al final del proyecto para automatizar tests de las funcionalidades importantes. Por norma general esto es un grave error. Es complicado implantar una solución de testing en un proyecto que no ha sido diseñado pensando en que todas las funciones de los objetos, clases y componentes han de ser testeables. Has de tener en cuenta que no podrás testear de manera eficiente y fácil un diseño acoplado donde unos objetos dependen de otros directamente, donde hay clases que no tienen un proposito claro, funciones que cubren más de una funcionalidad, etc.

Por tanto ya veis que pensar en una solución testeable te obliga a realizar un ejercicio previo a la implementación y tener claro el propósito de cada componente desde el inicio. Esto podría incrementar el coste inicial para desarrollar un proyecto, es evidente, pero en proyectos de largo recorrido evitarás que se descontrole y tengas un proyecto donde soluciones una cosa y se “rompan” otras siete. A nivel de costes no sólo acabarás recuperando la inversión inicial sino que está demostrado que acabarás ahorrando mucho en la fase de mantenimiento y evolución. Seguramente hayas oido hablar sobre TDD/BDD… estas técnicas consisten en implementar los test previo al desarrollo de los componentes (simplificando muchísimo). Por tanto tendremos tests que fallan y a medida que se desarrollan los componentes empezarán a superarse los test.

Qué beneficios te podrían aportar las técnicas:
  • Te asegura que sólo escribes código para cubrir las funcionalidades demandadas.
  • Te asegura que el código funciona correctamente y hace lo que esperamos que haga en todo momento.
  • Facilita el trabajo en equipo y el mantenimiento del código.

Ya para acabar con la teoría es importante hablar sobre como enfocar un test. Un test unitario sólo debe testear la lógica de un componente, por tanto, si el componente trabaja con datos de un servicio remoto se suele simular accesos al servicio usando mocks de modo que la comunicación con terceros e infrastuctura suele quedar fuera del ámbito de testeo unitario. Otro concepto que no hemos tocado es el coverage o cobertura de los test. Imagina que tienes una función con un if / else, los valores que le pasas al test hacen que siempre pase por el If y nunca por el else… En este caso habrás creado un unit test que aporta un 50 % de cobertura sobre esa funcionalidad.

¿Debo entonces optar por tdd o bdd, siempre debería buscar el 100 % de coverage?

Entiendo que no existe una verdad absoluta, podria interesarte una estrategia u otra en función del proyecto, equipo que participa, recursos, timmings, etc. Depende con quien hables te dirá que si tdd o bdd o que busca como objetivo un 70% de coverage, etc. Lo que nadie te dirá es que no cree en automatizaciones de test. Os dejo algunos hangouts interesantes donde referentes debaten sobre estos temas.

HangOuts

Testing javascript en Visual Studio 2015


Vamos ya con la parte práctica. Como comentábamos vamos a integrar una solución de testing unitario en un proyecto javascript (da igual si usas angular o react o jquery o javascript ‘nativo’) en tu IDE Visual Studio 2015..

Necesitaremos las siguientes herramientas:
  • Framework para desarrollar lost test unitarios: JasmineJS / Mocha / (…)
  • Herramienta que permita governar los test unitarios y se encargue de ejecutarlos-> Chutzpah / Karma / Protactor
  • Herramienta para determinar la cobertura de tus tests. -> Chutzpah / Instanbul / Karma-coverage
  • Gestor de tareas que permita automatizar la ejecución de test en procesos como una build. -> Grunt / Gulp.

Para ver estos ejemplos partiremos de un proyecto javascript de tipo Apache Cordova en Visual Studio 2015.. Si no tienes la template de cordova instalada puedes seguir los pasos en un proyecto web.

Ya veis que hay frameworks y opciones como para escoger. Como framework para crear los test usaré JasmineJS.

Como test runner me decanto por Chutpah dado que se integra bien con el IDE, permite ejecutar los test desde Test Explorer de Visual Studio, te facilita integración con herramientas de ALM Microsoft y es muy sencillo de configurar no hace falta gestor de tareas (grunt o gulp). Como alternativa valoro positivamente Karma. ProtactorJS no hace mala pinta pero se basa en Selenium y requiere instalar el jdk de java y como hay que decantarse por uno esto de momento haría que lo descarte en ámbito VS.

Os paso un par de videos de Channel9 que explican paso a paso como configurar Chutzpah y como configurar karma en Visual Studio 2015..

Respecto al video de Karma en mi caso, prefiero usar Grunt que también está soportado por Visual Studio. Ambos son automatizadores de tareas de ámbito cliente.

Otro tema que veo mejorable sobre como está planteado en el vídeo es que Karma lo hace correr en Chrome y por tanto siempre necesitas tener una ventana con el navegador abierto… esto se podría evitar con PhantomJS que veremos también.

Preparación del entorno, descarga paquetes y configuración


Karma:

Os recomiendo descargar este packete de nuget que ya añade a packages.json las dependencias que necesitaremos, crea los ficheros de configuración de Karma y grunt por nosotros y la carpeta donde ubicar los test del proyecto (podrías cambiar la ruta si lo deseas).

Chutzpah:

Has de seguir los pasos del video que consisten en instalar 2 extensiones, la configuración podría decirse que es más sencilla que el caso anterior debido a que no necesitas Grunt o Gulp.

Crear un compontente testeable


No seré original y usaré el clásico componente de una calculadora con 4 casos de uso muy marcados que son sumar, restar, multiplicar y dividir. Creo un nuevo archivo javascript y lo dejo en una carpeta [root]/services.
function Calculator() {

}

Calculator.prototype.Add = Add;
Calculator.prototype.Substract = Substract;
Calculator.prototype.Divide = Divide;
Calculator.prototype.Multiply = Multiply;

function Add(a, b) {
    return a + b;
}

function Substract(a, b) {
    return a - b;
}

function Divide(a, b) {
    return a / b;
}

function Multiply(a, b) {
    return a * b;
}

Crear test unitario


Ya podemos crear nuestro primer test para el componente calculadora. Creamos un nuevo archivo javascript en la carpeta DefaultTest que llamaremos CalculatorTest. Ahora entra en juego el primer framework de los que hemos descargado JasmineJS. Un test unitario para las 4 funcionalidades de la calculadora tendría esta pinta usando Jasmine:
describe("Calculator Test", function () { 
    var calculator;
    beforeEach(function () {
        calculator = new Calculator();
    });

    it("can add", function () {
        expect(calculator.Add(5, 5)).toEqual(10);
    });

    it("can substract", function () {
        expect(calculator.Substract(10, 5)).toEqual(5);
    });

    it("can divide", function () {
        expect(calculator.Divide(10, 2)).toEqual(5);
    });

    it("can multiply", function () {
        expect(calculator.Multiply(10, 5)).toEqual(50);
    });
});

Ejecutar los tests


Chuztpah se instala como una extensión de Visual Studio. Esta extensión añade un adaptador que busca archivos de test en la solución y los muestra en el test explorer de Visual Studio. Por tanto si instalas Chutzpa en tu Visual Studio podrías governar los tests también desde la herramienta de Visual Studio aunque uses Karma como test runner. Para activar el test Explorer has de ir a Test/Windows/Text Explorer de Visual Studio 2015.


En el caso de Karma podemos lanzarlo también desde el Task Run Explorer (View/Other Windows/Task Run Explorer) y veremos el resultado en el output console de javascript. Para ello nos vamos a Task Explorer, veremos las tareas configuradas en grunt o gulp y si pulsamos botón derecho sobre una podemos ejecutarla. En la pestaña Output veremos el resultado de la ejecución de los test.



Determinar el coverage de mis test


Karma:

Si os fijáis entre los packages que hemos descargado tenemos karma-coverage. Este paquete también conocido como istanbul nos permite generar un informe con la cobertura de los test. Para ello tendremos que configurarlo en karma.conf.js, al volver a ejectura un test veremos que nos genera un fichero html en la ruta que si lo abrimos con el navegador veremos tiene esta pinta.



Chutzpah:

Al instalar el la extensión Context menu extensión de Chutzpah podemos situarnos en el solution explorer y sobre la carpeta donde hemos creado los test unitarios pulsar botón derecho y seleccionamos la opción "Run Chutzpah with coverege".



Esto lanza los test de la solución y al finalizar abre en un ventana del explorador un informe de coverage que tiene esta pinta.



Hasta aquí el post de hoy de areaTIC, me ha gustado ver que el gran Visual Studio soporta bien la integración con herramientas de testing javascript.

lunes, 8 de febrero de 2016

asp net core y docker

Hace un tiempo estuve probando a ver si ya podía desarrollarla desde el mac con VsCode y no podía depurar asp.net desde el IDE así que lo dejé en stand-by. Este fin de semana he vuelto a la carga desde un equipo Windows para intentar hacer que mi api .net sea multiplataforma y los resultados son buenos.

En el post de hoy veremos como desarrollar una web api multiplataforma y también como publicarla en un contenedor docker en Azure (Linux). En primer lugar remarcar que estamos viendo cosas que todavía están por llegar oficialmente y puede ser que en poco tiempo cambien algunos de los pasos que describo a continuación. Para realizar el post, sobre todo para la publicación en docker me he apoyado en una serie de articulos que iré haciendo referencia.

Qué necesitas para hacer estas pruebas:
  • Visual Studio 2015
  • Cuenta en Azure (puedes obtener una subscripción temporal aquí).

Crear Api con Asp net core y Visual Studio 2015


En primer lugar en el asistente de nuevo proyecto en Visual Studio seleccionamos proyecto web de tipo asp.net y en la plantilla seleccionamos el vacío asp.net 5 (core). Por defecto si abres un proyecto asp.net con Visual Studio en Windows viene configurado para usar como host IIS Express (a Febrero 2016). Yo aquí me propongo hacer una api core “libre” de IIS, por tanto tenemos que despedirnos de IIS y el framework nativo. Para ello lo primero es eliminar todo resquicio de dnx 4.6 y IIS en el proyecto vacío de asp.net.

Propiedades del proyecto web:





Ves a project.json, elimina la configuración dnx46 de la sección frameworks y añade estas dependencias al proyecto:



El fichero project.json debería parecerse a este:
{
  "webroot": "wwwroot",
  "version": "1.0.0-*",

  "dependencies": {
    "System.Runtime": "4.0.20-beta-22816",
    "Microsoft.AspNet.Hosting": "1.0.0-beta5",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-beta5",
    "Microsoft.Framework.DependencyInjection": "1.0.0-beta5",
    "Microsoft.AspNet.Http.Extensions": "1.0.0-beta5",
    "Microsoft.AspNet.Http": "1.0.0-beta5",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta5",
    "Microsoft.AspNet.Mvc": "6.0.0-beta5"
  },

  "commands": {
    "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000",
    "kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5001"
  },

  "frameworks": {
    "dnxcore50": { }
  },

  "publishExclude": [
    "node_modules",
    "bower_components",
    "**.xproj",
    "**.user",
    "**.vspscc"
  ],
  "exclude": [
    "wwwroot",
    "node_modules",
    "bower_components"
  ]
}

Tenemos el command web para ejecutar en local (windows) y kestrel para cuando publiquemos en Linux.

Por último, asegúrate que Startup.cs tiene esta pinta
public class Startup
{
   public Startup(IHostingEnvironment env)
   {

   }

   // This method gets called by a runtime.
   // Use this method to add services to the container
   public void ConfigureServices(IServiceCollection services)
   {
   }

   // Configure is called after ConfigureServices is called.
   public void Configure(IApplicationBuilder app, IHostingEnvironment env)
   {
      app.Run(async (context) =>
      {
          await context.Response.WriteAsync("Hello World!");
      });
    }
}    

Si todo ha ido bien ya tienes una aplicación web, multiplataforma, totalmente desacoplada de IIS y windows corriendo en dnx.



Ahora estaría bien que la aplicación haga algo más que decir hola mundo. Verás que no es complicado. Simplemente tenemos que añadir la siguiente dependencia al archivo project.json (si no la has añadido ya en el paso anterior):

"Microsoft.AspNet.Mvc": "6.0.0-beta5"

Modificamos startup.cs:
public void ConfigureServices(IServiceCollection services)
{
     services.AddMvc();
}

// Configure is called after ConfigureServices is called.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
      app.UseMvc();
}
Por último creamos una carpeta controllers y dentro añadimos un archivo de tipo Web Api Controller. No lo edito, tal y como viene por defecto si compilas y vas a la url http://localhost:5000/api/values deberías ver el json de values.

Resumiendo hasta aquí, como ves el paquete mvc ya integra web api (antes eran paquetes separados) y ya no hay WebApiConfig ni necesidad de configurar rutas por defecto.

Publicar api en un contenedor Docker (Servicio en Azure)


En este post está bien explicado qué es Docker y el concepto DevOps en Español. Yo he seguido más o menos estos pasos para publicar. Os paso también un post de Hanselman al respecto.

Como se indica en los posts que hago referencia es necesario tener instalado el RC1 Update de Visual Studio y el cliente windows de docker.



Si ya tienes el RC1 ves a Extensions and Updates en Visual Studio y busca Docker:



Llegado este punto podemos crear la máquina virtual Ubuntu en Azure desde Visual Studio y gestionar las imagenes/contenedores donde correrán nuestras aplicaciones a través de docker.



Si todo va ok, si vas al portal de Azure o sino desde el panel de Azure en Visual Studio deberías ver la máquina.



Si te fijas verás que se han añadido una serie de archivos powerShell a tu proyecto que Visual Studio usará al publicar en la máquina que hemos configurado. Desde el asiente de publicación puedes validar la conexión al contenedor que acabas de crear en el paso anterior.



Al pulsar publish si todo va bien se publicará tu aplicación, puedes seguir los pasos de publicación en el panel de actividad de azure en Visual Studio.



Ya para acabar con el post, tras varios intentos fallidos esta fue mi expresión al conseguir publicar sin errores jajjajaja.



Bueno, espero que esto que comparto le sea útil a alguien. También podrías montar un docker en local y publicar contra este entorno, a mi me gustaría sacar tiempo para montarlo y así entrar con un poco más de detalle... Ahora ya puedo empezar a pasar mi api asp.net 4.5 y ver que soporta core y que no, por ejemplo tengo claro que de momento tendré que prescindir de funcionalidades SignalR. Otro punto que me tocará adaptar es como persistir la información porque mi api usar EF 6 code first y SQL Server que yo sepa todavía no corre en todas las plataformas ni está previsto que así sea. Como siempre espero ir sacando tiempo para publicar las pruebas de concepto, recordar que podéis seguir areaTIC en las redes sociales y colaborar en forma de comentarios, matices, aportaciones, insultos (sin pasarse) en definitiva feel free para participar!.

viernes, 5 de febrero de 2016

iOS Journey, UI en XCode

Hoy seguiremos con la serie de iOS journey que empecé a principios de año. En el post anterior tratamos un poco la sintaxi de Swift. La conclusión a la que llegué es que el lenguaje no es tan diferente a lo que estoy acostumbrado (C#, javascript, java..). En el siguiente enlace encontrarás un libro gratuito sobre Swift.

Hoy mostraré como trabajar con la UI y moverse un poco por XCode. Crearemos una aplicación vacía, añadiremos una escena, y arrastraremos 4 campos a las vista para ir viendo un poco.

En primer lugar una pequeña guía para moverse por Xcode, estos son los botones que te ayudarán a moverte por las secciones de Xcode que necesitamos ver en este mini tutorial.

Secciones principales de Xcode

Assistant editor: Divide la sección principal de Xcode diseño/código, de modo que muestra el código asociado a la pantalla en la que estamos situados.
Debug console: Muestra/Oculta la consola de depuración en la parte inferior de Xcode.
Project Navigator: Permite ver el arbol con los contenidos del proyecto.
Utility Panel: Muestra/Oculta el panel de utilidades. Dentro del panel de utilidades encontramos varias s


Apartados en Utility Panel

Identity Inspector: (sección superior) Permite modificar propiedades relacionadas con el objeto seleccionado en el story board.
Attribute Inspector: (sección superior) Permite modificar propiedades relacionadas con el objeto seleccionado en el story board.
Size Inspector: (sección superior) Permite modificar propiedades relacionadas con el objeto seleccionado en el story board.
Add File: (sección inferior) Permite añadir archivos al proyecto.
Object Library: (sección inferior) Set de componentes de UI que podemos arrastrar a los story boards.
En el post anterior ya comenté que el desarrollo iOS actual tiende hacía aplicar un pattern MVC. En iOS, tenemos los Story Boards que no dejan de ser un conjunto de escenas que representan el flujo que puede seguir el usuario cuando lanza tu aplicación. Por norma general una aplicación tiene un Story Board, pero podrías tener más de uno si la aplicación lo requiere. Por ejemplo la template de proyecto de XCode de saque viene con dos StoryBoards uno que se activa al ejecutar la aplicación (Launch) y otro para el contenido de la aplicación.

Al situarnos sobre un story board XCode nos muestra un canvas con las escenas. Sobre este editor podremos añadir nuevas escenas, añadir componentes a las escenas, controlar la navegación entre escenas…


Una escena generalmente está compuesta por una vista principal. Para añadir una escena a un Canvas has de pulsar en el botón Utility Panel para desplegar el panel de utilidades, localizar en la parte inferior el botón Object Library y arrastrar un ViewController al canvas (hay más tipos de controladores que ya veremos más adelante).



El siguiente paso será crear una clase que ejercerá el rol de controlador de la vista principal de la nueva escena que hemos creado. Vamos a File -> Add y seleccionamos un archivo de tipo File o CocoaTouchClass y lo editamos para que tenga el siguiente aspecto:
//
//  areaTICViewController.swift
//  iOS.journey
//
//  Created by Carlos Cañizares on 31/1/16.
//  Copyright © 2016 Carlos Cañizares. All rights reserved.
//

import UIKit

class areaTICViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Para vincular la clase que acabamos de crear a la escena, hemos de situarnos en la escena y abrimos el identity panel. En el campo class informamos el nombre del controller que acabamos de crear.


El siguiente paso será situarnos en la vista y arrastrar desde el Object Library un label mismo… en el momento de arrastrar te pedirá introducir un texto por defecto.

¿Cómo podríamos interactuar con los componentes de la vista desde el controlador? La respuesta es creando un outlet. Siempre que necesitemos interactuar con un componente tendremos que previamente crear un outlet. Crearlo es sencillo, nos situamos en la vista y pulsamos en el botón Assistant Editor.

Esto hará que XCode muestre pantalla divida con la vista y con el código asociado (deberíamos ver el código controller que hemos creado). El siguiente paso es situarnos sobre el label, arrastrar con botón derecho al punto donde queremos definir el outlet en código (normalmente donde estén el resto de variables del controlador) y ya lo tendríamos.


Para modificar el valor del label una vez la vista haya cargado podríamos hacerlo del siguiente modo:

class areaTICViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    @IBOutlet weak var MainLabel: UILabel!

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
        
        MainLabel.text = "iOS Journey"
    }
}

Con esto ya podrías acceder a un objeto de la UI desde el controller. En este caso un label no tiene acciones como por ejemplo un botón… Si arrastramos un botón a la vista y luego repetimos el mismo proceso que hemos realizado para el Outlet veremos que tenemos más opciones en el contextual que aparece… podemos crear un Action que a diferencia del outlet se usa para subscribirnos a una acción del botón desde el controller.

Como prueba de concepto podríamos hacer que al pulsar el botón cambie el texto del label. Hasta aquí habríamos visto como empezar a trabajar con la UI, moverse por XCode y como asociar controladores a las vistas. Hasta aquí el articulo de hoy, recuerda que puedes seguir areaTIC en las principales redes sociales!