Performance o rendimiento, e implicaciones del uso de const o reandonly

Introducción

Hacía bastante tiempo que no escribía en el blog. La principal culpa de ello es un proyecto en el que estoy involucrado desde el primer día de Octubre y que me tiene felizmente ocupado.

No obstante, tenía muchas ganas de retomar mi blog aunque el tiempo libre que tengo sea un bien preciado, y era uno de mis objetivos en este nuevo año.

Durante todo este tiempo en el que he estado un poco apartado del blog, me han surgido muchas cosas algunas de las cuales me apetece contar, pero el tiempo es limitado y por lo tanto, no me permite contar todo, así que debo seleccionar alguna de ellas.

En este caso, voy a comentar lo que suele ser una pregunta general con respecto a const o readonly, y luego alguna implicación de su uso, ya que me encuentro a veces que se tienen dudas sobre ello.

Const o readonly

En primer lugar, la pregunta de si el uso de const o readonly tiene impacto en el rendimiento, o si es mejor utilizar una u otra.

La respuesta a esta pregunta es realmente simple, por eso la quiero abordar al principio del todo.

No. Así de simple.

No existe un impacto destacable en rendimiento entre const o readonly que justifique el uso de una u otra opción.

El uso declarativo de const se hace en tiempo de compilación, mientras que el readonly se hace en tiempo de ejecución.

A priori puede pensarse que const será más eficiente que readonly (y de hecho lo es), pero la realidad es que esa eficiencia no es por lo general algo destacable, y que en el caso de que así pudiera ser, estamos hablando de nanosegundos. Vamos… que no hay que hacerse pajas mentales y que si queremos mejorar el rendimiento de nuestras aplicaciones, es mejor centrarse en los bloques de código principales en lugar de intentar ganar un nanosegundo aquí.

Dicho y aclarado esto, vamos con la segunda de las preguntas que a mi juicio es mucho más importante que la primera pregunta.

¿Existe alguna implicación en usar const y readonly?.

Sí.

Y aquí me voy a detener más.

Antes comentaba que el uso de const se lleva a cabo en tiempo de compilación, y readonly en tiempo de ejecución.

Imaginemos entonces un ensamblado que posee dos variables, una constante (const) que por defecto es estátida, y una variable de sólo lectura (readonly) que podemos declarar como estática o no (esto no es relevante).

Algo así:

 

namespace FooAssembly

{

    public class FooClass

    {

        public const string WithConst = “OneConst”;

        public static readonly string WithReadOnly = “OneReadOnly”;

    }

}

 

Compilamos el ensamblado. Todo perfecto.

Ahora creamos una aplicación de consola a la que agregamos como referencia nuestro ensamblado.

Y por supuesto, consumimos nuestro ensamblado.

Algo parecido a lo siguiente:

 

namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine(“Demo const – readonly”);

 

            Console.WriteLine(FooClass.WithConst);

            Console.WriteLine(FooClass.WithReadOnly);

 

            Console.ReadLine();

        }

    }

}

 

¿Qué información recibiremos por pantalla?.

Parece obvio que la pantalla nos mostrará la siguiente información:

 

OneConst

OneReadOnly

 

Y así sucede,…

Pero vayamos a reflector y analicemos el código del ensamblado de nuestra aplicación de consola.

Si abrimos nuestro ensamblado con Reflector, podremos ver algo que nos dará una pista directa de por donde voy a ir.

Observamos que en el caso del uso de la constante declarada en el primer ensamblado, ésta aparece “incrustada” en el ensamblado que la consume, ya que esta incrustación se ha realizado en tiempo de compilación.

Mientras que en el caso del uso de la variable de sólo lectura, se irá al ensamblado que la contiene para pedirle en tiempo de ejecución el valor de esa variable.

Con este escenario, planteemos ahora la siguiente ecuación.

Si el ensamblado que contiene la constante y la variable de sólo lectura, cambia,… es decir, algo como lo que voy a poner a continuación… ¿qué piensas que ocurrirá?.

 

namespace FooAssembly

{

    public class FooClass

    {

        public const string WithConst = “TwoConst”;

        public static readonly string WithReadOnly = “TwoReadOnly”;

    }

}

 

En este caso, nuestra aplicación de consola mostrará algo parecido a lo siguiente:

 

OneConst

TwoReadOnly

 

El ensamblado de nuestra aplicación de consola sigue teniendo “incrustada” la constante que se definió en la primera versión del ensamblado que la contiene, mientras que en el caso de la variable de sólo lectura, como se va a buscar su valor en tiempo de ejecución, ésta sí se “actualiza” de acuerdo a la nueva versión del ensamblado.

¿Y como resolver el problema?.

Pues tenemos la opción de recompilar nuestra aplicación de consola que posee una referencia a nuestro ensamblado para que ésta “se entere” del nuevo valor de la constante y lo “incruste” correctamente.

En realidad no se va a enterar de nada, ya que lo único que hará será compilar el ensamblado e “incrustar” los valores de las constantes nuevamente, sin importarle los valores originales.

Lo que vemos aquí, es que indirectamente estamos acoplando nuestra aplicación de consola al ensamblado que contiene las constantes.

¿Y esto es bueno o es malo?.

Pues como siempre, depende de lo que queramos hacer.

Por una parte, puede parecer malo este acoplamiento, pero por otro lado, nos aseguramos (y pudiera interesarnos) que si alguien introduce una nueva versión del ensamblado que contiene estas constantes, el valor de las constantes en la aplicación permanecerá inalterable, por lo que forzaremos al cliente a obtener una nueva versión de (en este caso de ejemplo) la aplicación de consola.

Aún y así, la recomendación de diseño es que no se utilicen como constantes, valores o datos que presumiblemente podrían cambiar a lo largo del tiempo.

Un ejemplo práctico de lo que NO sería recomendado, podría ser el uso de una constante para indicar la versión del producto, o bien el porcentaje de descuento ante diferentes situaciones, o también una Uri a un recurso, etc… hay cientos de ejemplos, pero todos ellos dependerán de los requisitos de nuestra solución, de si pueden cambiar a lo largo del tiempo, etc.

Y ojo, esta misma problemática no sólo aplica a const, sino también a los argumentos con nombre y argumentos opcionales, que tan útiles son a veces y que tan peligrosos son sino los conocemos bien.

Y sobre la técnica empleada por Microsoft con respecto a esta forma de trabajar, su nombre es “constant folding“, y se emplea de esta forma por temas de rendimiento. Salvo que alguien me corrija, en Java funciona de la misma manera.

Por cierto… se me olvidaba.

Una variable declarada como const no puede ser modificada dentro de la clase en la que se declara.

Sin embargo, una variable declarada como readonly sí puede ser modificada dentro de la clase en la que se declara siempre y cuando no haya sido declarada como estática (como he hecho en el ejemplo). Esta modificación se debería hacer en el constructor. Esta posibilidad, nos puede ofrecer una flexibilidad que no ofrece una constante.

Es por esto, que en lugar de pensar en el rendimiento cuando nos preguntamos si usar una constante o una variable readonly, quizás deberíamos plantearnos otras preguntas y sus posibles implicaciones, como por ejemplo como el uso de una constante, podría “romper” nuestra aplicación, algo que ya me he preocupado yo de adelantarte en esta entrada.

Espero que te haya gustado y parecido entretenida e interesante la lectura de esta entrada. ¡Hasta la próxima!. :)

No uses DataAnnotations en interfaces

Disclaimer

Quizás el uso de DataAnnotations en una interfaz no sea precisamente una buena práctica, así que no me aticéis por ahí porque el objetivo de esta entrada no es discutir eso, sino saltarnos esa recomendación y demostrar algunas cosas. De hecho, el uso de DataAnnotations tiene como objetivo también, evitar su uso en interfaces, siendo precisamente en su implementación donde tengamos la libertad de adoptarlas o crear nuestras propias DataAnnotations personalizadas.

Introducción

El título dicho así, puede sonar un poco drástico, pero sí,… usar DataAnnotations en nuestras interfaces no es una buena idea, y en esta entrada lejos de aceptar los axiomas que algunos creen porque otros dicen que es así y punto, voy a explicarte de forma práctica porqué digo esto.

¿Qué es o que son las DataAnnotations?

Aunque mucha gente sabe situar perfectamente DataAnnotations, me veo en la obligación de hacer una pequeña parada para indicar que son por si te pilla de nuevas o no lo tienes claro del todo.

El atributo de validación System.ComponentModel.DataAnnotations tiene como misión la validación de los campos de un modelo de datos, e incluso de una entidad si queremos.

Gracias al atributo DataAnnotations, podemos validar nuestros modelos o incluso crear nuestras propias validaciones personalizadas.

Es bastante común encontrarnos con DataAnnotations en aplicaciones web ASP.NET MVC, aunque no se nos impide para nada el uso de DataAnnotations en aplicaciones Web API, de consola o cualquier otra. De hecho, el uso de validaciones de los campos con los que va a trabajar nuestra aplicación no lo considero una opción.

Una vez introducido de forma breve lo que son DataAnnotations, vamos al cubrir de lleno el objetivo de esta entrada, que es el de explicarte por qué a mi juicio no es una buena idea utilizarlas en nuestras interfaces (por si creías que sí).

Desarrollo de un ejemplo simple con DataAnnotations

Lo primero que vamos a hacer es crear una aplicación de consola, dentro de la cual crearemos un modelo o entidad llamada Employee.

Dicha entidad tendrá dos sencillos campos. Nombre (Name) y Edad (Age).

Sobre el campo Age agregaremos una DataAnnotation que nos indicará que el valor de esta propiedad tendrá que estar comprendido entre 18 y 150.

Nuestra entidad quedará de la siguiente manera:

Employee

using System.ComponentModel.DataAnnotations;

namespace ConsoleApplication1
{

    public class Employee : IEmployee
   
{

        public string Name { get; set; }

        [Range(18, 150)]

        public byte Age { get; set; }

    }

}

La propiedad Age de nuestro modelo está decorado con una DataAnnotation de tipo Range.

Sin embargo, a la hora de validar nuestro modelo o entidad en nuestra aplicación de consola, deberemos hacer uso de una función que se encargará de validarlo entero, permitiéndonos mostrar por pantalla el campo o campos que no cumplen la condición de validación.

Este método que nos hemos creado podría bien ser el siguiente:

public static bool DataAnnotationsValidator(object @object, out List<ValidationResult> results)
{
   
var context = new ValidationContext(@object, serviceProvider: null, items: null);
   
results = new List<ValidationResult>();
   
return Validator.TryValidateObject(@object, 
                                                  
context,  
                                                  
results, 
                                                  
validateAllProperties: true);
}

Y la llamada a este método desde nuestra aplicación de consola para forzar el error de validación sería:

        static void Main(string[] args)
       
{
           
Console.WriteLine("Ejecución iniciada");
           
Employee employee = new Employee();
           
employee.Name = "John";
           
employee.Age = 17;
           
var results = new List<ValidationResult>();
           
var modelIsValid = DataAnnotationsValidator(employee, out results);
           
Console.WriteLine(String.Format("¿Es el modelo válido? {0}", modelIsValid.ToString()));
           
if (!modelIsValid)
           
{
               
foreach (var validationResult in results)
               
{
                   
Console.WriteLine(validationResult.ErrorMessage);
               
}
           
}
           
Console.WriteLine("Ejecución finalizada");
           
Console.ReadLine();
       
}

Nuestra aplicación en ejecución queda de la siguiente manera:

Como podemos observar, nuestra aplicación funciona tal y como esperamos.

Ampliando nuestro ejemplo

Ahora bien, de repente nos llega un requisito funcional que debemos cubrir.

Supongamos que nos han encargado tratar también los empleados externos.

Un empleado externo según los requisitos que nos han hecho llegar, tendrá los mismos campos que un usuario más el campo empresa, que indicará la empresa a la que pertenece este trabajador externo.

Aquí tenemos muchas posibilidades, pero dentro del equipo de arquitectura y del equipo técnico, entre las opciones de crear una clase abstracta, una clase base o una interfaz, o modificar el modelo para que cubra ambas opciones, se ha pensado que la mejor forma de abordar esto sea con una interface.

Alguien ha pensado incluso y después de las reuniones mantenidas con la gente de negocio (básicamente RRHH en nuestro ejemplo ficticio), que es posible que en un futuro próximo haya además de los empleados internos y los empleados externos, otros empleados,… o que quizás las propiedades nombre y edad usadas en el modelo empleado, pueda ser reutilizado por otros modelos o entidades, así que no es mala idea hacer esto (aceptamos pulpo en nuestro ejemplo).

Así que hagamos un esfuerzo más e imaginemos que nuestro proyecto no sólo posee la entidad Employee, sino que hay cerca de 50 ó más entidades o partes del modelo, y que esta interfaz nos va a venir muy bien porque de un plumazo vamos a reutilizar bastante código, y poniendo una DataAnnotation en una interfaz, resolveremos el problema de tener que poner la validación de rango en todas y cada una de las entidades. No parece mala idea… a priori…

Es decir,… nuestra interfaz y clases quedarán ahora de la siguiente manera:

IEmployee

using System.ComponentModel.DataAnnotations;

namespace ConsoleApplication1
{
    
   
public interface IEmployee
   
{
       
byte Age { get; set; }
       
[Range(18, 150)]
       
string Name { get; set; }
   
}
}

Employee

using System.ComponentModel.DataAnnotations;

namespace ConsoleApplication1
{
   
public class Employee : IEmployee
   
{
       
public string Name { get; set; }
       
public byte Age { get; set; }
   
}
}

ExternEmployee

using System.ComponentModel.DataAnnotations;

namespace ConsoleApplication1
{
   
public class ExternEmployee : IEmployee
   
{
       
public string Company { get; set; }
       
public string Name { get; set; }
       
public byte Age { get; set; }
   
}
}

Bien… ahora ejecutemos nuevamente nuestra aplicación de consola.

Obtendremos una respuesta como la que se indica a continuación:

Como podemos apreciar en la respuesta de ejecución de nuestra aplicación, el modelo o entidad Employee nos indica que es correcta.

¿Cómo es posible?.

Es evidente que la interfaz nos está indicando que la propiedad Age debe estar dentro de un rango de valores que no cumple. Pero como podemos ver, a la hora de ejecutar la acción de validación no está funcionando como esperábamos.

Modificando nuestro ejemplo

Bueno… el equipo de desarrollo se ha reunido para tratar de entender un problema que está sucediendo y que se nos ha escapado en algún momento.

Se ha dedicado bastante tiempo, un tiempo perdido al fin y al cabo, así que después todo este camino recorrido se decide cambiar la interfaz por una clase abstracta.

Esta clase abstracta es la siguiente:

EmployeeAbstract

using System.ComponentModel.DataAnnotations;

namespace ConsoleApplication1
{
    
   
public abstract class EmployeeAbstract
   
{
       
byte Age { get; set; }
       
[Range(18, 150)]
       
string Name { get; set; }
   
}
}

Y nuestras clases anteriores quedarán de la siguiente manera:

Employee

using System.ComponentModel.DataAnnotations;

namespace ConsoleApplication1
{
   
public class Employee : EmployeeAbstract
   
{
       
public string Name { get; set; }
       
public byte Age { get; set; }
   
}
}

ExternEmployee

using System.ComponentModel.DataAnnotations;

namespace ConsoleApplication1
{
   
public class ExternEmployee : EmployeeAbstract
   
{
       
public string Company { get; set; }
       
public string Name { get; set; }
       
public byte Age { get; set; }
   
}
}

Si ejecutamos nuevamente nuestro código, obtendremos un resultado como el que se indica a continuación:

Y aunque no lo voy a hacer aquí, exactamente igual ocurrirá si creamos una clase base que sea heredada por Employee y ExternEmployee.

¿Y esto por qué ocurre?.

El porqué de las cosas

La explicación de este comportamiento tenemos que buscarlo en el CLR de .NET y como funciona por dentro de acuerdo a como quiere que se comporte el equipo de .NET. No obstante, y para comprenderlo mejor, vamos a hacer alguna reflexión previa.

Las clases base son heredadas, tal y como he comentado anteriormente, es decir, los métodos, propiedades y funciones de una clase base, estarán presentes en la clase que la hereda. Por esta razón, una DataAnnotation de una clase base, estará en la clase que lo hereda, en la clase derivada.

Las interfaces por otra parte, son contratos o implementaciones a llevar a cabo, y dichas implementaciones no están presentes en la clase que implementa la interfaz hasta que esta implementación se representa como tal. Esto significa por extensión, que un metadato presente en una interfaz, NO es agregado dentro de la clase que implementa dicha interfaz. Por esta razón, si una interfaz tiene una DataAnnotation, ésta no llega a la clase que implementa esa interfaz.

Pero podemos dar una vuelta de tuerca más a este asunto. Imaginemos que tenemos una clase que implementa dos interfaces, y que estas dos interfaces poseen ambas la misma propiedad, pero con la salvedad de que una de ellas tiene una DataAnnotation y otra no, o dos DataAnnotations diferentes… ¿cual de ellas es la que tenemos que usar?.

Sin embargo, las interfaces chocan en cuanto a su implementación y uso con las clases abstractas, que son otra cosa diferente y posee la herencia como parte fundamental, algo que hemos visto, sí está soportado de forma directa.

Visual Studio 2013 ha perdido el Intellisense… ¿cómo arreglarlo?

Recientemente y por motivos de rendimiento, he tenido que desinstalar de mi Visual Studio 2013 el complemento ReSharper.

El problema, es que una vez desinstalado y reiniciado el entorno de desarrollo, he perdido el Intellisense.

No digo con esto que haya causa/efecto, simplemente constato un hecho que me ha pasado a mí, algo que no merece discusión.

Lo importante de todo este asunto, es que Intellisense es como un perro guía. Inicialmente he estado programando sin Intellisense sin muchos problemas, pero desde luego, no es la mejor forma de trabajar si lo que quieres es productividad. Una ayuda es siempre bienvenida.

El problema aquí es, ¿cómo puedo recuperar el Intellisense en mi Visual Studio?.

Para hacerlo, basta con ir a Tools > Import and Export Settings.

Aparecerá una ventana que corresponde con un asistente.

La primera página del asistente nos presenta tres opciones. Seleccionaremos la opción Reset all settings (normalmente la última) y pulsaremos el botón Next.

En la siguiente página del asistente nos dirá que donde deseamos guardar la configuración actual antes de reiniciarlas, a lo cual debemos seleccionar la segunda opción, No, just reset settings, overwriting my current settings. A continuación pulsaremos el botón Next.

En la siguiente y última página del asistente, deberemos seleccionar el lenguaje de programación correspondiente a la configuración que deseamos resetear, que en mi caso es C#. Finalmente pulsaremos el botón Finish para concluir el proceso.

Aparecerá una ventana con una barra de progreso que nos indicará simplemente que se está llevando a cabo los cambios.

Unos minutos después, aparecerá una ventana confirmándonos que los cambios se han realizado.

Volveremos a nuestro código dentro de Visual Studio 2013, y observaremos que ahora sí, tenemos Intellisense.

Espero que estos pequeños pasos le sirvan a aquellos que tengan alguna vez un problema parecido al mío.

Uso de DebuggerBrowsable

Introducción

Sé que hay gente que sigue la máxima de la información es poder, y de obtener información y conocimiento de muchos sitios y no compartir nada con el resto, algo que respeto pero que no comparto, ya que entre todos podemos recorrer más camino que uno sólo.

Pero lo mejor de todo es que no estoy sólo en ese camino, y me uno al grupo de entusiastas y apasionados de la tecnología que piensan igual que yo.

El caso es que recientemente, dos de esos apasionados escribieron en sus blogs un par de entradas precedidas antes por Twitter y a la que siguieron algunos comentarios muy interesantes.

En la primera de ellas, Luis Ruiz Pavón nos habló de como sobreescribir ToString en nuestras clases para mejorar la información en modo de depuración.

Otro fenómeno como es Eduard Tomás, complementó aquella entrada con otra no menos excelente titulada TIP – DebuggerDisplay.

Lo bueno es que leyendo estas entradas, uno reflexiona, piensa y recuerda, como así ha sido el caso, de la existencia de otras clases, en este caso de DebuggerBrowsable, del que quiero hablar aquí, y cuya existencia pasa muchas veces desapercibida para los desarrolladores, pero que creo complementa a las dos excelentes entradas de Luis y Eduard.

El objetivo de la depuración

El objetivo principal de la depuración es el de preguntar o interrogar como se están comportando nuestros procesos y nuestros objetos, sus flujos y qué información va y viene.

El problema a veces, es que manejamos gran cantidad de información en pantalla que nos impide ver con relativa facilidad algunos miembros o variables. Dicho de otro modo, hay miembros y variables cuya información no nos resulta relevante y… nos estorba cuando estamos depurando.

Por suerte, dentro de .NET tenemos la posibilidad de utilizar un atributo, de nombre DebuggerBrowsable, que nos permite ocultar o mostrar un nivel por encima aquellos miembros que nos interesa ver de un vistazo rápido.

La mejor manera de comprender esto bien, es haciendo un ejemplo, así que nos pondremos manos a la obra con C#.

Entendiendo el problema

En primer lugar, mostraremos el problema para posteriormente resolverlo.

Iniciaremos un proyecto de WinForms (aunque puede ser cualquier otro).

Crearemos dentro de él, dos clases. Una clase de nombre Team, y otra clase de nombre Driver.

Serán dos clases muy sencillas.

La primera clase Team tendrá el siguiente código:

namespace WindowsFormsApplication1

{

    public class Team

    {

 

        public string TeamName { get; set; }

        public string Country { get; set; }

        public Driver Name { get; set; }

    }

}

La segunda clase Driver tendrá el siguiente código:

namespace WindowsFormsApplication1

{

    public class Driver

    {

        public string Name { get; set; }

        public string Surname { get; set; }

        public byte Age { get; set; }

    }

}

Como podemos observar, son dos clases muy sencillas.

La primera corresponde a los datos de un equipo de Formula1, y la segunda contiene los datos de su primer piloto, con su nombre, apellido y edad.

Por su parte, nuestro formulario Windows contendrá el siguiente código fuente:

namespace WindowsFormsApplication1

{

    public partial class MainForm : Form

    {

 

        public MainForm()

        {

            InitializeComponent();

            Initialize();

        }

 

        private Team Formula1Team { get; set; }

 

        private void MainForm_Load(object sender, EventArgs e)

        {            

        }

 

        private void Initialize()

        { 

            this.Formula1Team = new Team() { TeamName = "Ferrari", 

                                             Country = "Italy", 

                                             Name = new Driver() 

                                                    { 

                                                        Name = "Fernando", 

                                                        Surname = "Alonso", 

                                                        Age = 32 

                                                     } 

                                            };

        }

 

    }

}

A continuación, pondremos un punto de interrupción después de agregar un objeto de tipo Team a Formula1Team y veremos la información que nos devuelve el depurador al posicionarnos encima de la propiedad Formula1Team.

La primera información que veremos en la que se indica en la siguiente imagen:

Algo que a todas luces es correcto.

Sin embargo, si queremos acceder a Name, observamos que es del tipo Driver, y nos obliga a hacer clic sobre Name para ver el contenido de esta clase:

El problema aquí es que hemos realizado dos pasos hasta llegar a parte de la información que nos interesaba.

¿Cómo resolver esto?. ¿Tenemos alguna manera de obtener la información que deseamos de un solo plumazo en el visualizador de depuración?.

La respuesta nos la da DebuggerBrowsable, el cual aún no hemos utilizado.

Entendiendo DebuggerBrowsable

Una vez que entendemos un poco la problemática (no en todos los proyectos nos encontraremos con esta problemática o con la necesidad que he expuesto como ejemplo), vamos a ver como resolverlo. Para ello, utilizaremos el atributo DebuggerBrowsable.

Este atributo pertenece al namespace System.Diagnostics, y puede ser agregado a propiedades y campos en clases y estructuras.

Por su parte, tiene tres valores enumerados posibles pertenecientes a DebuggerBrowsableState que son:

  • Collapsed: muestra el objeto contraído, pero permite visualizar el miembro y expandirlo con el objetivo de acceder a cualquier otro miembro que lo pueda contener.
  • Never: no muestra nunca el elemento.
  • RootHidden: oculta el elemento raiz, mostrando los elementos secundarios en el caso de que el elemento sea una colección o matriz de elementos.

Un detalle de este uso es que podemos combinar estos atributos dentro de las diferentes clases. En el ejemplo anterior, tenemos un objeto de tipo Team que contiene a su vez datos de tipo Driver.

En nuestro caso, lo que nos interesa es mostrar en el depurador la información del nombre del equipo y el nombre y apellido del piloto principal del equipo.

Empezaremos por el final.

El objetivo es que el depurador nos muestre una información similar a la que se indica a continuación:

Como podemos observar, lo que obtenemos por pantalla en nuestro caso, es más relevante y nos ayuda a centrarnos en la información que consideramos clave o más importante a la hora de depurar.

El código de nuestras clases Team y Driver, quedarán de la siguiente manera en este caso:

La clase Team quedará de la siguiente forma:

using System.Diagnostics;

 

namespace WindowsFormsApplication1

{

    public class Team

    {

 

        public string TeamName { get; set; }

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]

        public string Country { get; set; }

        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]

        public Driver Name { get; set; }

    }

}

La clase Driver quedará de la siguiente forma:

using System.Diagnostics;

 

namespace WindowsFormsApplication1

{

    public class Driver

    {

        public string Name { get; set; }

        public string Surname { get; set; }

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]

        public byte Age { get; set; }

    }

}

Obviamente, el resto de miembros del objeto está ahí y no han desaparecido. El Intellisense los localiza sin problemas y podemos acceder a ellos desde código.

Sin embargo y como podemos apreciar, el uso de este atributo nos puede venir bien en diferentes situaciones. Ahí cada uno debe saber si le aporta valor o no.

Utilizar el mando de Xbox One en tu tableta o PC ya es posible

Si tienes un mando de Xbox One en casa, deberías saber que ya es posible utilizarlo en tu tableta o PC.

Microsoft ha liberado los drivers de 32 bits y 64 bits para poder utilizar el mando de la Xbox One en Windows.

Es bastante probable que los drivers se incluyan en un futuro a través de Windows Update, pero mientras tanto, puedes ya instalártelos y probarlos.

Descarga del driver de 32 bits.
Descarga del driver de 64 bits.

Como usar el mismo disco duro externo en Windows y Mac OS X

Introducción

Si eres de esas personas que tienes un ordenador con Windows y Mac, y tienes la necesidad de compartir información entre ambos ordenadores, o bien quieres pasar información a un disco duro externo o lápiz USB para usarlo en diferentes sistemas, te habrás encontrado con un típico problema.

En mi caso, dispongo de muchísimas fotos en formato RAW que quiero post-procesar con Adobe Photoshop, y para ello, a veces uso Windows y a veces uso Mac. No tengo problema en usar uno u otro, pero las imágenes las quiero tener un disco duro externo de 1 Tb y volcarlas también al disco duro cuando me apetezca desde uno y otro sistema operativo.

Formateando para Windows

Si usas Windows y formateas el disco duro, lo normal es formatearlo en formato NTFS.

El problema es que si introduces ese disco duro en un Mac, éste accederá a él en modo lectura.

Otra posibilidad es formatear el disco duro a formato FAT32. En este caso, el disco duro será accesible tanto para Windows como para Mac, pero el problema aquí es el límite de los archivos que deben tener un tamaño máximo de 4 Gb, lo cuál no es válido ya que es posible que tenga videos hechos con mi cámara de más tamaño, por lo que no es para mí una opción válida.

Formateando para Mac OS X

Si usas Mac y formateas el disco duro, lo normal es formatearlo en formato HFS+.

El problema es que si introduces ese disco curdo en un sistema Windows, ni siquiera será capaz de leerlo.

La solución

La solución a tomar entonces y en mi caso, es realmente sencilla.

Basta con formatear el disco duro a formato exFAT desde Windows.

El formato exFAT es una versión de formateo que mejora a FAT32. Es recomendable su uso en dispositivos USB.

Si no estoy equivocado, para poder usar exFAT en Mac OS X, deberás estar seguro de disponer de un sistema operativo Snow Leopard (v10.6.5) o superior. En el caso de Windows, tu sistema operativo deberá ser Windows Vista o superior.

De esta manera, podremos leer y escribir archivos desde Windows o desde el Mac, pudiendo ser esos archivos de más de 4 Gb, eliminando todas las barreras que teníamos antes.

Si tenemos curiosidad por los diferentes formatos de los discos duros, diferencias y características, te recomiendo acceder a esta información.

Office 365 Message Encryption

A finales del pasado 2013, Microsoft anunció la inminente salida de Office 365 Message Encryption.

A finales del mes de Febrero de 2014, se anunció la disponibilidad de Office 365 Message Encryption.

Office 365 Message Encryption es un servicio que nos permite enviar mensajes encriptados a destinatarios fuera de la organización.

Este tipo de servicio está pensado para empresas que posean comunicaciones donde este tipo de comunicación es esencial o muy importante.

Evidentemente, cualquiera puede subscribirse a él para usarlo, pero no es lo habitual.

Pero Office 365 Message Encryption no es nuevo, de hecho es un sustituto de EHE o Exchange Hosted Encryption.

Por otro lado, Office 365 Message Encryption se activa como servicio adicional con un incremento en el coste de aproximadamente 1,50€ por usuario al mes, a excepción de los usuarios de Office 365 E3 y Office 365 E4 para los que este servicio es gratuito. Esto último es así ya que Office 365 Message Excryption forma parte de Microsoft Azure Rights Management, que ya está incluido en las subscripciones E3 y E4 de Office 365.

De cara al administrador, éste deberá habilitar o deshabilitar a través de las reglas de transporte, el uso de Office 365 Message Encryption.

Toma de contacto con las APIs de Office 365

Introducción

Recientemente, Microsoft ha publicado un conjunto de APIs para acceder a Office 365 desde nuestras aplicaciones.

En esta entrada, vamos a introducirnos en el uso y consumo de las APIs de Office 365 desde .NET, en concreto, desde una aplicación de Windows Forms, aunque el tipo de interfaz que usemos no representa en principio ningún problema.

¿Qué nos ofrece las APIs de Office 365?

Las APIs de Office 365 nos ofrece un acceso rápido y sencillo al calendario, correo, contactos, ficheros, etc., de Office 365, reduciendo el tiempo de desarrollo y complejidad a la hora de acceder a estos recursos, abstrayéndonos de ciertas operaciones.

En esta entrada, veremos a modo de prueba de concepto y demostración, como acceder a los contactos de Office 365.

Primeros pasos

Nuestro objetivo principal será el de acceder a las APIs de Office 365 de forma sencilla desde Visual Studio para programar nuestra aplicación.

Para ello, deberemos descargar e instalar en primer lugar (si no lo hemos hecho ya) las Office 365 API Tools para Visual Studio (nota: los ejemplos de código de esta entrada han sido probados con Visual Studio 2013 Update 2).

La descarga de Office 365 API Tools para Visual Studio la encontrarás en este enlace.

Creación de nuestra aplicación

Una vez que hemos instalado las Office 365 API Tools, iniciaremos Visual Studio y crearemos un nuevo proyecto, que en mi caso ha sido un proyecto de Windows Forms al que he puesto por nombre WinFormsOffice365.

A continuación, deberemos hacer clic con el botón derecho del ratón sobre el proyecto que hemos creado y seleccionaremos la opción Add > Connected Service del menú contextual, tal y como aparece en la siguiente imagen:

En la ventana que aparecerá, deberemos conectarnos a nuestra cuenta de Office 365 e indicar sobre qué parte de Office 365 queremos acceder, y los permisos que queremos tener (lectura, escritura, etc).

En esta entrada accederemos a los contactos de nuestra subscripción de Office 365, por lo que he seleccionado el servicio Contacts y le he dado permisos de lectura y escritura.

Los permisos se pueden otorgar seleccionando el servicio al que queremos acceder, y haciendo clic en la opción Permissions.

Una vez modificado todo esto, nuestra ventana debería ser similar a la que se indica a continuación:

Pulsaremos el botón OK y acudiremos al código de nuestra aplicación.

Al realizar esta operación, Visual Studio agrega a nuestro proyecto un conjunto de ensamblados que muy posiblemente necesitemos utilizar a la hora de trabajar con la API de Office 365.

De aquí, los más destacables son:

  • Microsoft.Office365.Exchange
  • Microsoft.Office365.OAuth
  • Microsoft.Office365.OAuth.WindowsForms

Respecto al último, al estar trabajando con una aplicación de Windows Forms, se nos agrega un ensamblado específico del tipo de aplicación con la que estamos trabajando.

Por otro lado, por defecto aparecerá una clase de nombre ContactsApiSample en nuestro código que tendrá el siguiente aspecto:

   1: using Microsoft.Office365.Exchange;

   2: using Microsoft.Office365.OAuth;

   3: using System;

   4: using System.Collections.Generic;

   5: using System.Threading.Tasks;

   6:  

   7: namespace WinFormsOffice365

   8: {

   9:     public static class ContactsAPISample

  10:     {

  11:         const string ExchangeResourceId = "https://outlook.office365.com";

  12:         const string ExchangeServiceRoot = "https://outlook.office365.com/ews/odata";

  13:  

  14:         public static async Task<IEnumerable<IContact>> GetContacts()

  15:         {

  16:             var client = await EnsureClientCreated();

  17:  

  18:             // Obtain first page of contacts

  19:             var contactsResults = await (from i in client.Me.Contacts

  20:                                          orderby i.DisplayName

  21:                                          select i).ExecuteAsync();

  22:             

  23:             return contactsResults.CurrentPage;

  24:         }

  25:     

  26:         private static async Task<ExchangeClient> EnsureClientCreated()

  27:         {

  28:             Authenticator authenticator = new Authenticator();

  29:             var authInfo = await authenticator.AuthenticateAsync(ExchangeResourceId);

  30:  

  31:             return new ExchangeClient(new Uri(ExchangeServiceRoot), authInfo.GetAccessToken);

  32:         }

  33:         public static async Task SignOut()

  34:         {

  35:             await new Authenticator().LogoutAsync();

  36:         }

  37:     }

  38: }

Aunque esta clase nos puede resultar de mucha ayuda, vamos a crear nuestra propia clase con algunas cosas más.

Extendiendo nuestra aplicación

Nuestra aplicación se encargará de mostrar los contactos de nuestra subscripción y de crear nuevos contactos.

En estos momentos, nuestra subscripción tiene un conjunto de contactos tal y como se muestra en la siguiente imagen:

Para darle un poco de gracia a nuestra aplicación Windows, he agregado en ella un conjunto de controles (RichTextBox, Button, Label, LinkLabel, GroupBox, PictureBox…).

La idea como decía antes, es la de permitir mostrar dos acciones principales sobre Office 365 APIs: la posibilidad de acceder y visualizar los contactos de Office 365, y la opción de agregar un nuevo contacto a Office 365.

El aspecto de nuestro formulario Windows es el que se muestra en la siguiente imagen:

Pero lo que realmente nos importa es como podemos trabajar con Office 365 APIs.

Manos a la obra

Para ello, vamos a escribir una clase, que será muy parecida a la que Microsoft nos proporciona en modo prueba y cuyo código compartía anteriormente.

La única salvedad o diferencia es que vamos a agregar alguna instrucción de código más como la inserción de un nuevo contacto y alguna cosa más.

El código de nuestra clase a la que he puesto por nombre Office365Contact es el que se indica a continuación:

   1: using System;

   2: using System.Collections.Generic;

   3: using System.Threading.Tasks;

   4: using Microsoft.Office365.Exchange;

   5: using Microsoft.Office365.OAuth;

   6:  

   7: namespace WinFormsOffice365

   8: {

   9:     public class Office365Contact

  10:     {

  11:  

  12:         private const string ExchangeResourceId = "https://outlook.office365.com";

  13:         private const string ExchangeServiceRoot = "https://outlook.office365.com/ews/odata";

  14:  

  15:         private ExchangeClient _exchangeClient;

  16:  

  17:  

  18:         private bool _isAuthenticated = false;

  19:  

  20:         public bool IsAuthenticated 

  21:         {

  22:             get

  23:             {

  24:                 return _isAuthenticated;

  25:             }

  26:         }

  27:  

  28:  

  29:         private AuthenticationInfo _authenticationInfo;

  30:         public AuthenticationInfo AuthenticationInfo

  31:         {

  32:             get { return _authenticationInfo; }

  33:         }

  34:         

  35:         public async Task<ExchangeClient> EnsureExchangeClient()

  36:         {

  37:             if (_exchangeClient != null)

  38:                 return _exchangeClient;

  39:  

  40:             var authenticator = new Authenticator();

  41:             _authenticationInfo = await authenticator.AuthenticateAsync(ExchangeResourceId);

  42:  

  43:             _exchangeClient = new ExchangeClient(new Uri(ExchangeServiceRoot), _authenticationInfo.GetAccessToken);

  44:             _isAuthenticated = true;

  45:             return _exchangeClient;

  46:         }

  47:  

  48:         public async Task<IEnumerable<IContact>> GetAll()

  49:         {

  50:             var client = await EnsureExchangeClient();

  51:             var contactsResults = await client.Me.Contacts.OrderBy(c => c.DisplayName).ExecuteAsync();

  52:             return contactsResults.CurrentPage;

  53:         }

  54:  

  55:         public async Task Create(Contact contact)

  56:         {

  57:             if (contact == null)

  58:             {

  59:                 throw new ArgumentNullException("contact");

  60:             }

  61:             var client = await EnsureExchangeClient();

  62:             await client.Me.Contacts.AddContactAsync(contact);

  63:         }

  64:  

  65:         public async Task SignOut()

  66:         {

  67:             _isAuthenticated = false;

  68:             await new Authenticator().LogoutAsync();

  69:         }

  70:  

  71:     }

  72:  

  73: }

Atendiendo al código, podemos ver 4 métodos principales:

  • EnsureExchangeClient se encarga de realizar las operaciones de autenticación con Office 365. En el caso de que no estemos autenticados nos aparecerá una ventana para escribir nuestra cuenta de Office 365 y nuestra contraseña. Una vez hecho esto, aparecerá una información que nos solicita que confiemos en las operaciones que dicha aplicación va a realizar y que en nuestro caso será las operaciones de lectura y escritura de contactos. Esta función también sabrá si ya nos hemos autenticado anteriormente con la aplicación.
  • SignOut se encarga por su parte de eliminar los rastros de autenticación de nuestro usuario con la aplicación y forzarnos la próxima vez a volver a tener que escribir nuestra cuenta de Office 365 y aceptar los permisos de la aplicación como si fuera la primera vez que la ejecutáramos.
  • GetAll por su parte, nos permite obtener los contactos de Office 365. En este ejemplo no se ha tenido en cuenta paginación de datos ni nada parecido, y se ha optado por esta porción de código que nos servirá como PoC.
  • Create por último, se encargará de crear un nuevo contacto. Aquí utilizamos un objeto de tipo Contact. Este objeto pertenece al ensamblado Microsoft.Office365.Exchange que ha sido agregado automáticamente por Visual Studio.

Del resto de código, destacar las direcciones web de Office 365 que utilizaremos internamente para conectarnos y trabajar con Office 365.

El código de la aplicación de Windows Forms (o aplicación cliente si utilizamos un poco de abstracción) es aquí poco relevante en cuanto a la gestión interna de lo que hace, pero en términos generales nos permitirá realizar las siguientes acciones: SignIn para autenticarnos, y una vez autenticados, leer los contactos y agregar un nuevo contacto, pudiendo además, cerrar la sesión.

Ejecutando nuestra aplicación

La primera vez que ejecutamos nuestra aplicación obtendremos por lo tanto una pantalla que nos solicitará las credenciales para acceder a Office 365:

Una vez autenticados, obtendremos una segunda ventana para aceptar los permisos que otorgamos a la aplicación para acceder a la información de nuestra cuenta.

Pulsaremos el botón Aceptar.

Una vez hecho esto, nuestra aplicación de Windows Forms tendrá un aspecto similar al siguiente:

La primera operación que llevaremos a cabo será la de leer los contactos de Office 365, para lo cual haremos clic sobre el botón Read Contacts.

Nuestra aplicación tendrá entonces un aspecto similar al que se indica a continuación:

A continuación y por completar nuestro ejemplo o PoC, vamos a agregar datos en los campos que tenemos más abajo para crear un nuevo contacto.

En mi caso he agregado los datos ficticios de una persona llamada Albert Einstein y he pulsado el botón Create.

Una vez hecho, se mostrará nuevamente los contactos incluyendo a Albert.

Si acudimos ahora a Office 365, observaremos que nuestro nuevo contacto ha sido agregado a Office 365.

Recordar que esta PoC no trata de ser un guía o un patrón de cómo trabajar con las APIs de Office 365, sino únicamente una toma de contacto.

El código fuente de todo este ejemplo (cliente incluido) puedes encontrarlo en este enlace.

Conclusiones

Aunque en esta prueba de concepto hemos repasado únicamente las operaciones de lectura y obtención de todos los contactos, y de creación de un contacto en Office 365, podríamos haber llevado a cabo todas las operaciones CRUD.

También cabe destacar que en nuestro caso, hemos realizado operaciones con los contactos de un usuario, pero podríamos haber realizado operaciones con el calendario, correo, ficheros, etc.

Happy coding!

Como acceder a la facturación de Office 365

Introducción

Una pregunta muy típica de los administradores de Office 365 es la que tiene que ver con los detalles de facturación de nuestras subscripciones de Office 365.

¿Dónde encontrar las facturas e imprimirlas?.

Mi idea con esta pequeña entrada es explicar donde podemos localizarlas, ya que cuando lo hacemos por primera vez no es precisamente intuitivo y muchos usuarios se pierden.

Localizando la facturación de Office 365

Lo más fácil y rápido para ver e imprimir o descargar en disco nuestras facturas de Office 365 es acceder en primer lugar (y como es obvio) a nuestra subscripción de Office 365, en concreto al Centro de Administración de Office 365.

Una vez que hemos accedido a nuestra subscripción, prestaremos atención al menú lateral izquierdo de Office 365, y dentro de este menú, haremos clic en la opción concesión de licencias.

De esta manera, accederemos a todas nuestras licencias dentro de la subscripción de Office 365.

Podemos seleccionar nuestra subscripción y acceder a sus detalles de facturación, licencias, etc.

En nuestro caso tenemos una única subscripción por lo que acceder a la facturación de esta subscripción es realmente sencillo.

Basta con hacer clic sobre la opción del menú horizontal facturación que se encuentra justo encima de nuestra subscripción.

Dentro de esta nueva ventana, podremos acceder a la facturación de cualquier mes del año, verla e imprimirla o exportarla en formato pdf.

Como podemos ver, es más sencillo de lo que podríamos en un primer momento pensar, aunque desde mi modesto punto de vista, está un pelín rebuscado y no es muy intuitivo localizarlo requiriendo algunos pasos intermedios hasta que damos con ello.

Instalar OneDrive for Business como herramienta de sincronización con SharePoint 2013 Online y On-Premise

 

Los que hemos trabajado con SkyDrive Pro en SharePoint 2013, sabemos que a la hora de sincronizar bibliotecas de documentos no funcionaba como era de esperar.

Pues bien, Microsoft ha preparado un pequeño documento técnico para resolver este problema el cual pasa por desinstalar la versión actual de sincronización de datos en la nube, conocida hasta la fecha como SkyDrive Pro, e instalar la nueva aplicación denominada OneDrive for Business.

No tiene mucho sentido explicar punto por punto que se dice en el documento, ya que es muy sencillo seguir los pasos de instalación.

Puedes acceder a esta información en este enlace.