Buscar en este blog....

domingo, 31 de julio de 2016

The Difference (and relationship) between MVC and MVP patterns

I wrote this post like one year ago, but I did it in spanish. Yet I'm trying to write also a little more in english. So here it goes.

I think this topic is normally a bit confusing due to the big amount of information that we can easily find in the internet and the short time we can spend to analyze all this information.

The MVC Pattern (Model-View-Controller) is a well-known design pattern which is being used all around the world. In fact, there's no one in the software development who hasn't hear about it. So I'm not gonna explain it. Nevertheless, not so well known is this other pattern called MVP (Model-View-Presenter), although it has gained more terrain in the last years.

At first view one can be tempted to think "Oh, they only changed the Controller of the MVC for the Presenter of the MVP, so it's almost the same thing, but with another name!".

Well.. nothing more far away from the truth! Absolutely not! So, what is it? What is the real difference between them? While I'm not gonna explain the MVP pattern in detail, because there is A LOT of information in internet, I would like to explain what is the relationship between these two patterns. How I see it.

First of all, let's quickly remember what the MVC is about: to separate an application into three conceptually-different parts, so he have:


  • Model: makes reference to data or, better said, to representation of the information. Depending on how you interpret the pattern, the model can be directly bound to the persistence of this information. But in a wider interpretation, it can also mean the whole state of the system in a given moment. So, in its wider interpretation, we can say it embraces both the state of the system and its persistence.
  • Controller: represents the business logic. The rules on which the systems run..
  • View: represents the user interface.

Here it is worth to mention that I don't particularly agree with the separation between "Model" and "Controller", because I think often is kind of difficult -and expensive in terms of time- to totally exclude the model (the data) from the controller (the business logic i.e. the behaviour). However, I'm not saying it can't be done, but rather consider that there is actually a conceptual separaration between them, althought it might be unnecesary (this will be inherent to each situation and system).

Now let's briefly review the what the MVP pattern is about:



  • Model: this model represents the business model. Violá! It's not the same as the model of the MVC, but rather this model includes both the representation of the data and the business logic. That's why we talk about a "Business Model". That is, this model invovles the Model and the Controller of the MVC together.
  • Presenter: this is the director: on one hand it directs the events of the view to the model and on the other it updates the view with the information coming from the model. This concept does not exists directly in the MVC pattern. I mean directly, because is perfectly valid to affirm that this "Presenter" is a part of the "View" in the MVC pattern. That is, this is the logic that we are used to write into the MVC's View, no matter how basic it is!
  • View: The View, according to the MVP, is the silliest and easy-to-write code that we have.  It's just about a "View" that knows his "Presenter", to whom it delegates absolutely everything that happens in it. This View makes nothing but to delegate. The user clicks, the "View" tells the "Presenter" where did the user click. Or the other way: the "Presenter" tell the "View" to fill a ComboBox, the "View" fills the Combo with the information provided. It just does not have business logic at all!

So having this information, if we analyze it a little, we come to the conclusion that both patterns are not mutually excludent. It is not about predicting "We're using the MVC pattern or the MVP pattern", but it could be interesting thinking in a combination of them. That might lead us to something called VPCM (View-Presenter-Controller-Model).

What?! Does it actually exists?! What are we talking about?

Nothing new, to be honest. Maybe the name it's new, it doesn't even exist. But that's not the point. The point is that we are breaking down the View of the MVC in two parts: a "View" who does nothing (but to delegate) and its "Presenter" who does everything for the view. Those are, the View and the Presenter of the MVP. Something like this:


Another way to see this, is the other way: we take the Model of the MVP and we break it down in two new pieces: a Controller (which has the business logic) and a Data Model (which represents the  information). That is, we've just get the Controller and the Model of the MVC pattern. It looks something like this:



As we can see after this analysis, they are NOT mutually excludent patterns: they complement each other! We could say that one emphasize
the Backend, and the other the Frontend. MVC and MVP respectively.

I would like to have some opinions about this analysis and its conclusion.
Cheers!

domingo, 24 de julio de 2016

Writing your first Aspect with Postsharp in C#

Hi!

As some of you might remember, some years ago I started to dabble in the world of Aspects Oriented Programming. I also wrote three posts explaining what is aspect oriented programming, what are its advantages and I gave an example on how to implement aspects in Java using AspectJ. That was a few years ago. Nevertheless, those posts are more relevant than ever!! So if you don't feel that sure with AOP, I´d recommend you to read a few on what aspects are to understand it before you continuing reading.

But life and likes started taking me to and through the .NET and C# world, so I began to look for new tools. Today there are really a lot of tools and frameworks to support aspects, however I chose the one called Postsharp.

Until now, I must admit that the simplicity of this framework seems wonderful for me when compared with other like Spring.NET AOP, which requires a little more of skills when setting it up. Postsharp doesn't need to be configured!! So this is the first advantage.

That said, let's go to the point and see an example on how this framework works.

Maybe the correct thing would be to start defining some concepts that I didn't clarify in those posts, and which are usefull to understand what we are doing. But no: today we start directly with an example. After that, in other posts, I will clarify these points.


So, lets imagine a very simple scenery. It's about a well-known and complex application called "Hello, World" ;), on which we are going to add an aspect. We are going to create only one aspect, that will be responsible to intercept the program's execution just before calling the method who writes "Hello World" in to the screen.

Step 1: Add Postsharp to the project.

Once we've created an empty project (e.g. Console Application), we add the Postsharp packet to it. The simplest way to do it is, of course, using NuGet. So easy as opening NuGet and searching the framework by its name. Then adding it to the project.

Here it is worth it to mention, that once added to the project, Postsharp asks the user to download an executable to be installed (version VS > 2010). This is meant to install a component that will added to Visual Studio. Postsharp has a free version which is enough to write aspects with total freedom, but it also has two more versions which are not only not free, but very expensive for the single user, but provide already-written and already-working aspects and also the possibility to write complex aspects. I haven't had yet the chance to try them, but I'm gonna do it as soon as possible. But do not be afraid of it: get the Express version (the free one) to continue. This installation needs to be made only once. So its not a problem.

Step 2: Write the "Hello World".

Actually, steps 1 and 2 are interchangeables. It is really the same. We can write first the "base" project (without aspects) and then install Postsharp.

I know it can be difficult, so I'm gonna help you. To create the "Hello World" project, you should call the method WriteLine() to write in the console, in the main class.

using System;

namespace FirstTryWithPostSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

I guess you didn't have much more complications in this step! ;) Let's move on!

Step 3: Write the Aspect.

Now the interesting part: an aspect, is nothing else but a class! Yes, that simple! Well.. but actually this class must accomplish two conditions:

  1. It must be ALWAYS serializable. This is achieved applying the "Serializable" attribute as we'll see soon..
  2. It ALWAYS inherits from one Postsharp's class, which give our class the "super powers", to put it in some way. They aren't actually superpowers, but these Postsharp's classes have methods which can be overridento redefine them. Postsharp's Core will insert them in our code during compile time. In our example, it will be inserted just before the call to Main() method.
Ok, lets create the class, which we can call AspectThatInterceptsAMethod and says this:



using PostSharp.Aspects;
using System;

namespace FirstTryWithPostSharp
{
    [Serializable]
    class AspectThatInterceptsAMethod : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
            Console.WriteLine("Entering the method: " + args.Method.Name);
        }
    }
}


Briefly I want to say that I assume that we already know where this class is being indicated as Serializable, and that the aspect (the class) inherits from the class  OnMethodBoundaryAspect, which provides the possibility to rewrite some methods. In this case, we chose the method OnEntry() which indicates that whatever we do inside it will be executed just before executing the methods to which this aspect will be applied. But like OnEntry(), there are other methods that you can also redifne: OnExit(), OnSuccess() y OnException(). Lets see how to apply this aspect to the Main() Method.

Another little detail, is that args.Method.Name give us the name of the method that was intercepted. This, and much, much more (like accesing to the parameters, and its values) are part the powerful tools with which we count.

Step 4: Indicate to which methods our aspect will be applied.

So far we've made an aspect as god demands. But it is isolated, i.e. it is not being used! To use it, we just have to apply it as an attribute in the methods we want to be affected by it. This is made incredible easy in the following way:

 [AspectThatInterceptsAMethod]
        static void Main(string[] args)
        {


If we now run the project, we'll see that the aspect's text is showed at first, and then Main method's text. This occurs this way, because the aspect will be executed always before the method. Why? Just because we decided to overwrite the OnEntry() method. If we'd wanted to show the text before AND after the main's method, then we should have overwritten also the OnExit() method inside the aspect. Yes, only that!.

Another interesting tip is, that if we want the aspect to be applied to ALL methods of a class, it's just needed to put the attribute over the class name. Like this:

    [AspectThatInterceptsAMethod]
    class Program
    {

        static void Main(string[] args)
        {


And in this way, any method will be automatically a victim of our aspect ;) Easy, don't?

I invite you to try it by yourself!

This was an introduction to a very simple aspect. The aspects's world is very much extensive and interesting! Many wonderful things can be done but, however, like everything in software, I recommend you: always analyze which are the real advantages and disadvantages of introducing a new practice, framework or whatever. Aspects are not always needed. Remember: "Having a good hammer doesn't means that every problem is a nail".

In my experience, the use of aspects is a growing trend, but because many people is getting used to it and not being afraid of it. I'll try to come back with new things about Postsharp's aspects.

martes, 10 de mayo de 2016

Code Reviews - Parte 1

Hace pocas semanas que se me ha encargado la implementación de Code Reviews en la empresa para la cual trabajo. Si bien yo ya tenía la idea de hacer esto hace un tiempo, ahora que está "la orden" dispongo de "más y mejor" tiempo para llevarlo a cabo. Y de forma seria, es decir, como un procedimiento formal.


Como suele pasar en muchas de las empresas que desarrollan software para uso interno, la calidad del mismo es más o menos cuestionable. Si bien el software "está funcionando", cuando hay que meterle mano para actualizar, reparar bugs, o agregar nuevas características, comienza la odisea de introducirse en esos códigos de cinco o diez años de antiguedad, sucios, emparchados, manoseados por diferentes personas de las que uno solo recuerda el nombre y con suerte alguna que otra anécdota.

El problema con esto es que cuando urge algun tipo de mantenimiento siempre es un peligro modificar ese código, porque como dije "ya está funcionando" y uno nunca sabe los efectos colarterales que puede producir al modificarlo.

Existen algunas formas de minimizar el impacto de modificar estos códigos, por ejemplo, la cobertura con tests. Si tenemos el código cubierto con tests, cualquier modificación que rompa el comportamiento se verá refejada en los test que fallen. Pero seamos sinceros: casi nunca existen estos tests, o menos aún están actualizados.

Entonces podemos aplicar una segunda técnica, más humana si se quiere, pero que si está bien aplicada puede, a futuro, allanar y simplificar gran parte del camino: los Code Reviews.

Los Code Reviews, o revisiones de código, consisten en sentar a una persona para que revise una porción de código que no escribió ella misma. De esta forma, puede detectar potenciales bugs, y algunas cosas que para los compiladores es más difícil o imposible: legibilidad y calidad del código. Por ejemplo, si un método es demasiado grande, o si recibe muchos parámetros, o si los nombres de los métodos o las variables no son descriptivos, etc. Si hay codigo redundante, o código duplicado, son todos aspectos que una persona puede identificar mejor que una herramienta, y aunque hay herramientas muy buenas, el "ojo humano" tiene ventajas indiscutibles.

En fin, retomando, voy a ir comentando un poco el proceso de code reviews que implementemos, que está basado ni más ni menos que la documentación disponible en internet, ya que convengamos que no hay ningún misterio ni secreto en este tema. En fin, más adelante iré comentando como me va con esta experiencia, y que en otra empresa en la cual trabajé se hacían code reviews, pero eran muy informales, sin ningún tipo de planificación, y sin una cultura organizacional que los acompañara, lo cual no ayuda en absoluto y los hace ver como "una molestia que tengo que sacarme de encima rápido para seguir adelante".

Saludos.

lunes, 14 de marzo de 2016

Mi experiencia en el Agile Open Camp 2016

Hace una semana comenzaba a terminar el AOC 2016, la segunda edición del Agile Open Camp que se celebra en Argentina desde el año pasado. Fui afortunado al poder participar. Quiero contar un poco lo que es o, más bien, lo que fue para mi.

Pero es difícil comenzar. Es dificil describir con palabras algo que te emociona, que toca tus sentidos mucho más allá del simple aprendizaje de la filosofía Agile. Porque no se ven exactamente Metodologías Ágiles; para eso ya está plagado internet de libros y artículos. Porque no te explican cómo implementar tal o cual cosa; para eso hay manuales. Vas a compartir.

Keynote de Juan Daza, a orillas del río.

En estos Open Camps, vivís tres días y medio aislado del mundo, solo en contacto con otras decenas de personas que buscan lo mismo que vos: compartir momentos y experiencias. El tronco temático es Agile, sí, pero vos podés compartir o escuchar lo que vos quieras. Vos podés aprender de Arduino, de  microservicios, de scrum, de bitcoins, nociones sobre el movimiento Slow, e incluso podés pedir que si alguien sabe, te enseñe a tocar guitarra. Hay también quienes se ofrecen para darte un taller de astronomía o eseñarte fotografía nocturna. Pero vos podés ofrecer o pedir lo que quieras.

Pero por supuesto hay mucho de Agile, experiencias, charlas, workshops, y una modalidad que me encantó que se llama "World Cafe", en la que se discuten temas en mini sesiones de 20 minutos. Y se vive en carne propia la magia de la auto-organización del evento. Vivir la experiencia de esta auto-organización no te lo da ningún libro, ningún curso, ninguna conferencia, ningún congreso. Acá cada uno es libre de participar en lo que quiera (y si es que quiere).

En medio del evento, de pronto podés conocer a alguien con quién te das cuenta que podés combinarte y dar un taller, gestar una idea que, quien te dice, germine con el tiempo para salir a la luz en forma de un emprendimiento, un proyecto, o simplemente conocer un buen amigo.

Auto-organizando talleres.

No menor es el hecho de que el evento se realiza (al menos hasta ahora) en diferentes lugares cercanos -pero no dentro- de la ciudad de San Carlos de Bariloche (Argentina), cuyos paisajes y tranquilidad, condimentan con el sabor mágico que hace falta para crear ese ambiente relajado e inspirador que lo caracteriza y lo hace tan especial, porque convengamos que no sería lo mismo hacer el este evento en el medio de la ciudad, con los ruidos y distracciones que abudan allí. Acá estás "obligado" a compartir con la misma gente todo el tiempo, y eso tiene un efecto impresionante.

En esta edición en particular, tuvimos la oportunidad de asistir a muchísimos talleres, jugar al fútbol, al paddle, hacer caminatas por la zona en medio de árboles y bordeando ríos, meditar, y hacer un fogón en medio de lo que fue la noche más silenciosa y estrellada de mi vida; con guitarras, chistes, charlas y un corderito que rebasaba absolutamente cualquier tipo de pretención que pudierámos tener.

Cronograma tentativo.
Lo importante, dicen algunos, no es sólo pasarla bien durante los días que dura el evento. Lo importante es que, además, el evento se detenga mágicamente en el tiempo dentro de cada uno de nosotros, adoptando la curiosa forma de la motivación y, de alguna manera, pase a formar parte los días subsiguientes, y los meses, y si es posible de la vida. Es decir, que produzca un cambio en nosotros, que nos llene de energía para poder comenzar una transformación como personas, mejorar las relaciones con los demás, generar confianza, y crecer.

Sigo sintiendo que no puedo aún expresar la magia que me dejó esta experiencia. Creo que si tengo que compararlo con algo para explicárselo a quien nunca fue, es como un retiro espiritual de agilidad. No soy creyente, pero es una comparación muy acertada, porque te quedás con esa hermosa sensación de "yo puedo -y voy- a cambiar el mundo".

Para terminar, quiero citar a Mauro Strione, uno de los organizadores principales del AOC, que expresa en lindas palabras, lo que muchos sentimos una vez que terminó el evento:

"Fueron tres días llenos de energía, motivación, compromiso, ganas... y sin obligar a nadie a nada, es más, todos vienen porque quieren, no porque los mandan de su empresa. La mayoría se lo pagan de su bolsillo..."

"No se si logro transmitir de qué se trata esto, quizás suene a secta o a que estamos locos. Solamente quiero advertir que cuando los geeks descubrimos el potencial de los ceros y unos de las computadoras, transformamos el mundo en pocos años, si ahora empezamos a entender a las personas y sus relaciones, sus sentimientos y motivaciones, y logramos combinarlos con esos ceros y unos... cuidado con lo que podemos lograr!"


Fotografía de las noches de Bariloche.

miércoles, 9 de marzo de 2016

C# - Obtener canales RGB de un Bitmap

Vamos a trabajar con el siguiente bitmap tomado de internet para trabajar:

 

Para descomponer un Bitmap de tres canales (RGB) en tres Bitmaps que representen cada uno, un canal del Bitmap original, podemos hacer lo siguiente:


rgb = new Bitmap("imagen.bmp");
int width = rgb.Width;
int height = rgb.Height;

Bitmap channelRed = new Bitmap(width, height);
Bitmap channelGreen = new Bitmap(width, height);
Bitmap channelBlue = new Bitmap(width, height);

for(int x = 0; x < width; x++)
{
   for(int y = 0; y < height; y++)
   {
      Color color = rgb.GetPixel(x, y);
      Color colorRed = Color.FromArgb(color.R, color.R, color.R);
      Color colorGreen = Color.FromArgb(color.G, color.G, color.G);
      Color colorBlue = Color.FromArgb(color.B, color.B, color.B);

      channelRed.SetPixel(x, y, colorRed);
      channelGreen.SetPixel(x, y, colorGreen);
      channelBlue.SetPixel(x, y, colorBlue);
   }
}

De esta forma, obtenemos 3 bitmaps, cada uno en blanco y negro y representando la tonalidad de cada canal:

 

Esto se ve así, porque ocupamos cada canal, de cada imagen, con el canal que obtuvimos previamente. Es decir, extrajimos el canal rojo de la imagen original, y grabamos todos los canales de channelRed con ese componente. Al tener cada canal el mismo valor, se ve gris. Si quisieramos que cada imagen contenga únicamente el valor del canal que extraemos, tendríamos que dejar los otros dos canales en cero. Cambiemos entonces la parte del código que asigna los colores:

Color color = rgb.GetPixel(x, y);
Color colorRed = Color.FromArgb(color.R, 0, 0);
Color colorGreen = Color.FromArgb(0, color.G, 0);
Color colorBlue = Color.FromArgb(0, 0, color.B);

Y lo que obtenemos es esto:


Si bien el resultado es el esperado, esta forma no es precisamente rápida. En caso de imágenes más grandes, el proceso tarda más, y más. Y ni hablar si queremos operar con estos valores. Hay, claro, formas de trabajar con esto mucho más rápido, en otro momento las veremos.

lunes, 15 de febrero de 2016

¿Qué es el NDVI, o Indice de Diferencia Normalizada de Vegetación?

Esta vez no voy a hablar de ningún concepto del software, y me permito divagar por otros ámbitos que no se le parecen demasiado, como es el tema del agro. No se parecen, pero están relacionados. ¿Por qué? Porque TODO, tarde o temprano, termina esclavizando al desarrollo de software para sobrevivir. Los informáticos, somos una espcie necesaria para la industria, nos guste o no.

Hace unos años, allá a madiados de de los setenta -si mal no recuerdo-, un científico se hallaba en su trabajo, ni más ni menos que la NASA, analizando imagenes satelitales del LandSAT (un satelite que tomaba fotografías areas de la Tierra). Su estudio se orientaba al análisis de la vegetación sobre la tierra.

Este señor, cuyo nombre era Compton Tucker, después de mucho analizar, y obtener resultados, escribió un paper llamado "Red and Photograghic Infrared Linear Combinations for Monitoring Vegetation", es decir: Combinaciones Lineales del Rojo e Infrarojo Fotográfico para Monitoreo de la Vegetación". De los resultados que obtuvo, nos vamos a ocupar en este post.

Aunque a simple vista puede sonar aburrido a quienes no son del palo de la agricultura -y similares-, lo que este señor encontró es sorprendente: Un árbol en buen estado de salud refleja muchísima luz infraroja, y muy poca luz roja. Pero si este árbol se enferma, entonces comienza a reflejar muchísima menos luz infraroja, casi en la misma cantidad que la luz roja. Y si se muere dicho árbol, entonces deja de irradiar luz infraroja, comparado con la luz roja. Todo esto tiene una explicación lógica, que está relacionada con la clorofila, pero por ahora no nos interesa.

Me permito tomar prestada una imagen de internet para ilustrar este concepto con imágenes, que siempre resulta más comprensible y entretenido:


Aunque está en inglés, es bastante simple:
  • La hoja saludable (Healthy Leaf) refleja muchísismo la luz infraroja (NIR), y bastante luz verde y es por eso que un arbol sano se ve de color verde.
  • La hoja estresada (Stressed Leaf) refleja muchísimo menos infrarojo, y un poco más de rojo y verde.
  • La hoja muerta (Dead Leaf) refleja aún menos infrarojo que la estresada, y menos verde, por eso se ve más opaca y apagada.
A esta altura, tiene que estar clarísimo que nosotros los seres humanos NO podemos ver los rayos infrarojos, y por eso no nos damos cuenta si un arbol refleja más o menos luz infraroja. No señor, no podemos. Pero en nuestras casa, y a diario, contamos con una herramenta que SÍ distingue la luz infraroja: las cámaras de fotos digitales. Si alguna vez te preguntaste por qué yo no puedo ver la luz que emite un control remoto, pero cuando lo miro a través de una cámara de fotos sí puedo verla, ésta es la razón. El sensor de la cámara distingue la luz infraroja y la convierte en luz visible que puede variar entre blanco, violeta, o rosado. (TIP: esto se usa mucho para comprobar si un control remoto funciona, o no).

Volviendo al señor Compton, lo que hizo de interesante, fue describir algunos modelos que se basaban en relaciones matemáticas entre la luz roja y la luz infraroja, y que permiten comprobar el estado de salud de una vegetación.

De todas las que hizo, la fórmula que más le convenció, se llama NDVI (Normalized Difference Vegetation Index), o Índice de Diferencia Normalizada de Vegetación, y es la siguiente:


 dónde NIR representa la luz infrarroja, y Red -obviamente- la roja.

Esta fórmula nos da valores que se encuentran entre -1 y 1. Mientras más cercano al -1, peor es la salud de la planta, y mientras más cercano a 1, mejor es la salud de la planta. Los valores intermedios, corresponden a estados de estrés, aunque para comprender realmente el significado o el motivo de los números, es siempre conveniente consultar con un experto en el tema del agro.

Mediante la aplicación correcta de esta fórmula, que Compton utilizo con imagnes satelitales, podemos obtener nuevas imágenes que nos muestran el estado de la vegetación que hablamos recién. Aquí tenemos un ejemplo, pero con imagenes no-satelitales:

Primero, contamos con esta imagen normal tomada por una cámara común y corriente, y que puede también guardar los infrarojos:


Luego de aplicarle la fórmula del NDVI, obtenemos la siguiente imagen:


Donde podemos distinguir claramente qué parte de la vegetación está más saludable (la verde) y cual más seca (naranja). Y además, podemos distinguir perfectamente aquellas partes que no son vegetación (rojo).

Es sorprendente la claridad de la información que nos da la imagen! Esto se utiliza mucho con fotos aereas de cultivos, para encontrar problemas en el riego, o de otra indole que pueden estar afectando dichos cultivos. Es una forma relativamente económica y fiable, de la cual también se pueden llegar a encontrar patrones de problemas.

En este momento estoy desarrollando un software para que, dada una imágen, calcule la imágen NDVI correspondiente. De hecho, de estas imágenes que uso como ejemplo, la del NDVI fue calculada con mi software. Si bien el software está funcionando, aún debo pulir la interfaz de usuario, para hacerlo más amigable.

Esto es todo por ahora, más adelante presentaré este programa que permite automatizar el cálculo de NDVI, y en tiempos muy cortos.

Saludos!

viernes, 21 de agosto de 2015

Diferencia -y relación- entre los patrones MVC y MVP

Creo que este tema se presta un poco a confusión debido a la cantidad de información que existe en internet y el poco tiempo que disponemos para analizar toda esta información.

El patrón MVC (Modelo-Vista-Controlador) es muy utilizado y creo muy pocas personas del ambiente del desarrollo no lo conocen, por lo que no voy a hablar de este patrón.

Sin embargo, no tan famoso es éste otro patrón, que ha tomado un poco más de fuerza desde hace unos años, y sigue escalando: el patrón MVP. El patrón MVP hace referencia a: MODELO-VISTA-PRESENTADOR.

A simple vista, uno se siente tentado a pensar: "Ah! Cambiaron el Controlador del MVC por algo nuevo llamado Presentador, que debe hacer algo parecido pero con otro nombre.."

Ja! Nada más alejado de la realidad! Absolutamente no! Entonces, ¿qué es?

Si bien no voy explicar qué es, porque sería seguir agregando más información de lo mismo, y en google ya hay mucha y buena, yo quiero hablar sobre qué relación existe entre ambos patrones, y por ende, también hablar de cuál es la diferencia.

Primero que nada, recordemos rápidamente que la intención del MVC es separar una aplicación en tres partes fundamenales, pero de alguna manera relacionadas. Tenemos:

  •  Modelo: que hace referencia a los datos o, mejor dicho, a la representación de la información. Según cómo se interprete el patrón, el modelo puede estar directamente ligado a la persistencia de dicha información. Sin mebargo, en una interpretación más amplia, puede abarcar también el estado del negocio en un momento dado. Es decir que, en su versión más amplia, el modelo es el estado del negocio y la persistenca de ese estado.
  • Controlador: que representa la lógica del negocio. Las reglas que hacen al negocio.
  • Vista: que representa la interfaz con el usuario.

Acá quiero aclarar que yo particularmente no estoy muy de acuerdo con la separación entre "Modelo" y "Controlador", porque pienso que muchas veces es dificil y costoso excluir totalmente al modelo (representación de los datos) de la lógica del negocio (o sea, del controlador). Sin embargo, no estoy diciendo que no se pueda hacer, o no se deba hacer, sino más bien que hay que considerar que existe una separación coneptual de ambas cosas, sin que esto implique necesariamente llevarla a cabo (aspecto que será inherente a cada situación).


Ahoa bien, si repasamos brevemente el MVP, nos encontramos con lo siguiente:


  • Modelo: aquí el modelo representa el modelo del negocio. Voilá! No es lo mismo que el modelo del MVC, sino que este modelo incluye tanto la representación de los datos como la lógica del negocio: por eso hablamos de "modelo del negocio".  Es decir que este modelo abarca al Modelo y al Controlador del MVC juntos.
  • Presentador: El presentador es quien dirige: por un lado los eventos de la vista hacia el modelo, y por otro lado actualiza la vista con las información provenientes del modelo. Este concepto no existe directamente dentro del patrón MVC. Digo "directamente" porque es perfectamente válido afirmar que este presentador es parte de la Vista del MVC. Es decir, es la lógica que le solemos poner a la vista, por más básica que sea!
  • Vista: La vista, según el MVP, es lo más tonto y fácil del programar que hay. Se trata de una vita propiamente dicha que conoce a su presentador, a quién le delega absolutamente todo. Ella no hace nada, excepto delegar. Ocurre un click: le dice al presentador que se haga cargo del click. Asi de simple. Ocurre algún otro evento: le dice al presentador que se encargue de ese evento. Pero ella no procesa nada, no hace nada. Solo delega el trabajo al presentador.

Despues de analizar un poco esto, podemos llegar a la conclusión de que ambos patrones no son excluyentes. No es cuestión de decir Vamos a usar el MVC o el MVP, sino más bien, puede ser interesante pensar en una combinación de ambos. Algo así como un VPCM (Vista-Presentador-Controlador-Modelo).

Qué!? Eso no existe! De qué estamos hablando?

De nada nuevo, en realidad. Sólo estamos desglosando la Vista del MVC en dos partes: una vista que no hace nada, y su presentador que hace todo. Es decir, de la Vista del MVC obtenemos la Vista y el Presentador del MVP. Algo así:


 
Otra forma de verlo, es la inversa: agarramos el Modelo del MVP y los desglosamos en un controlador (con la lógica del negocio) y un modelo de datos (represetación de los datos). Es decir, del Modelo del MVP obtenemos el Controlador y el Modelo del MVC. Algo así:



Cómo podemos ver después de este análisis, NO son patrones mutuamente excluyentes: son complementarios. Por decirlo así, uno hace más hincapié en el back-end, y el otro en el front-end.
Me gustaría leer opiniones que aporten a este análisis y ésta conclusión.
 Saludos!

viernes, 31 de julio de 2015

Aspectos en C# con Postsharp (Un ejemplo muy simple)

Buenas!
Como algunos recordarán, hace unos años comencé a incursionar en el mundo de la Programación Orientada a Aspectos. En aquella época, hice tres entradas explicando qué es la programación orientada a aspectos, qué ventajas tiene, y hasta di un ejemplo de cómo implementarla en Java usando AspectJ. De eso hae ya unos años. Sin embargo, dichas entradas siguen más vigentes que nunca!! (Así que si no sabés muy bien lo que son y querés una introducción corta y clara, te recomiendo las dos primeras antes de seguir leyendo)

Sin embargo, la vida y los gustos me fueron llevando al mundo de .NET y C#, por lo que comencé a buscar nuevas herramientas. Hoy en día, hay realmente muchas herramientas y framworks para trabajar con aspectos. Sin embargo, yo preferí inclinarme al framework Postsharp.

Hasta ahora, admito me parece una maravilla la simplicidad de este framework comparado con otros, como Spring.NET AOP, que requieren un poquito más de maña con la configuración. Postsharp no necesita configurarse!!

Bueno, vamos al grano, y veamos un ejemplo de como funciona este sencillo framework.

Quizás lo correcto sería comenzar con algunas definiciones que no aclaré en los posts pasados, y que son de utilidad conceptual. Pero no: hoy comenzamos con un ejemplo, directamente. Después, en otro post aclararemos esos puntos.

Muy bien: vamos a suponer un escenario muy simple. Se trata de una compleja aplicación conocida como "Hola Mundo", a la cual le vamos a añadir un aspecto. Vamos a crear un solo aspecto que se encargue de interceptar la ejecución justo antes de ejecutar el método que escribe "Hola Mundo".

Paso 1: Agregar Postsharp al proyecto.

Una vez creado un proyecto vacío (por ejemplo, una consola), le agregamos el paquete de Postsharp. La manea más simple de hacerlo es, naturalmente, con NuGet. Tan simple como abrir NuGet y buscar el framework por su nombre. Luego agregarlo al proyecto.
Aquí vale aclarar, que una vez agregado al proyecto, Postsharp pide al usuario de descargar un ejecutable e instalarlo. (version VS > 2010). Esto es para instalar un componente agregado al Visual Studio. Postsharp tiene una versión gratuita que es suficiente para escribir aspectos con total libertad, pero también posee dos opciones más (que son pagas, y muy caras) las cuales proveen aspectos ya escritos y funcionando. Personalmente no he tenido el agrado de probar estas versiones aún. Pero sin miedo: instalá la versión Express (gratuita) para poder seguir. Esta instalación solo se realiza una vez.

Paso 2: Crear el Hola Mundo.

En realidad, los pasos 1 y 2 son intercambiables. Realmente es lo mismo. Podemos hacer primero el proyecto "base" (sin aspectos) y luego instalar Postsharp.

Para crear el proyecto "Hola Mundo", nada tan simple como en la clase principal hacer una llamada a la consola para escribir en pantalla

using System;

namespace PruebaPostSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hola Mundo!");
        }
    }
}


Este paso fue  fácil, no? ;) Sigamos!

Paso 3: Crear el Aspecto.

El aspecto es, nada más y nada menos, que una clase. Si así de simple. Bueno, es una clase con dos particularidades:

  1. SIEMPRE debe ser serializable. Esto se logra aplicando el atributo "Serializable" como ya veremos.
  2. SIEMPRE hereda de alguna clase padre proveniente de Postsharp, la cual le da los "poderes" de aspecto, por decirlo de alguna manera. En realidad, no son poderes, sino son clases que le permiten redefinir métodos (override) que ya tienen y que luego el core de Postsharp va ubicar en nuestro código. (Para nuestro ejemplo, lo ubicaría justo antes del llamado a "Main()".

Creemos una nueva clase, que se llame AspectoQueInterceptaUnMetodo y dice así:

using PostSharp.Aspects;
using System;

namespace PruebaPostSharp
{
    [Serializable]
    class AspectoQueInterceptaUnMetodo : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
            Console.WriteLine("Entrado al método: " + args.Method.Name);
        }
    }
}

Brevemente quiero dar por sentado que ya sabemos donde esta indicado que la clase es serializable, y que el método hereda de la clase OnMethodBoundaryAspect, la cual le provee la posibilidad de reescribir algunos métodos. En este caso, elegimos el método OnEntry() que indica que lo que haga ese método se hará justo antes de ejecutar los métodos a los que se les aplica ese aspecto. Pero también hay otros: OnExit(), OnSuccess() y OnException(). Veamoslo en acción.

Otro detalle, es que en args.Method.Name tenemos almacenado el nombre del método que fue interceptado antes de llamar al aspecto. Esto, y mucho más (como acceso a los parametros, y los valores de los parámetros) son poderosas herramientas con las que podemos contar.
 

4) Indicar qué metodos serán afectados por el aspecto.

Hasta aquí tenemos un aspecto hecho y derecho. Pero está aislado: es decir, nadie lo usa. Para usarlo, solo debemos definirlo como atributo de el/los métodos a los que queremos que afecte.

De la siguiente manera:

 [AspectoQueInterceptaUnMetodo]
        static void Main(string[] args)
        {


Si ahora ejecutamos el proyecto, vemos que se muestra primero el texto del aspecto, y luego el del método Main. Esto es porque el aspecto siempre se ejecuta antes que el método. Si quisieramos que se ejecute después, deberíamos sobre escribir el método OnExit(). Si queremos que se ejecute antes y después, deberíamos sobreescribir ambos métodos: OnEntry() y OnExit(), y asi de simple funciona esto.

Otro tip interesante, es que si queremos que el aspecto se aplique a TODOS los métodos de una clase, solo basta con colocar el atriuto sobre la clase en cuestión:

    [AspectoQueInterceptaUnMetodo]
    class Program
    {

        static void Main(string[] args)
        {


Y de esta forma, cualquier método automáticamente será víctima de nuestro aspecto!! Simple, no?

Te invito a que pruebes vos mismo!

Esto fue una sencilla introducción a un aspecto muy simple. El mundo de aspectos es mucho más grande e interesante! Se pueden hacer cosas realmente estupendas pero, sin embargo, como todo en el software, siempre hay que analizar las ventajas y soluciones reales que esta (o cualquier otra) práctica puede conllevar. No siempre se necesitan aspectos.

En mi experiencia, el uso de aspectos es una tendencia que está creciendo, porque mucha gente está animándose a desarrollar con aspectos cada vez más gracias a los frameworks como postsharp, Spring.NET, etc Y si bien aún no es tan común, y aún no se lo práctica de la mejor forma, esto está cambiando de forma veloz, como todo en este campo.

Próximamente iremos mostrando cosas nuevas, más interesantes y más avanzadas!

Saludos!

viernes, 5 de junio de 2015

Web Service que recibe y devuelve JSON

La verdad es que si JSON se utiliza tanto hoy en día, decididamente su simplicidad de uso es uno de los factores más decisivos para esta tendencia.

Actualmente estoy haciendo unos Web Services en C# que deben ser consultados por un cliente enviando como request una cadena en formato JSON. Y no solo eso, el cliente también espera que el WS le devuelva su respuesta.. también en formato JSON.

Esto es, tremendamente simple de lograr. Para mostrar, voy a crear un proyecto muy simple. No será un WS porque no amerita la complicación. Quiero decir que lo que voy a hacer aquí se aplica a un WS o a un proyecto cualquiera... de hecho, voy a hacerlo para un método aislado.

Vamos a hacer una calculadora. Pero para darle un poco de "complejidad", vamos a hacer la calculadora reciba una lista de pares de números. Se tomarán los números de cada uno de estos pares y se los sumará. De forma que se devolverá una lista de "sumas". Por ejemplo:

Una lista para enviarle a la calculadora podría ser:
listaEntrada = [5,2],[1,-3],[-2,-2]
y la correspondiente lista de respuesta:
listaRepsuesta = 7,-2,-4

¿Estamos de acuerdo? Bien. Sigamos.

Si el Web Service va a recibir la lista de pares en formato JSON, debemos definir exactamente cómo.Podemos imaginar algo así:

{
    "pares": 
    [
  {
   "numero1":"5",
   "numero2":"2"
  },
  {
   "numero1":"1",
   "numero2":"-3"
  },
  {
   "numero1":"-2",
   "numero2":"-2"
  } 
    ]
}


y por lo tanto, la siguiente respuesta:

{  
   "sumas":[  
      7,
      -2,
      -4
   ]
}


Entonces, considerando esta decisión, vamos a armar dos entidades: una entidad para tener los datos de entrada, y otra entidad para poner los datos de salida. Las mismas podrían llamarse sumaRequest y sumaResponse, por ejemplo.

Escribamos estas entidades entonces, pero además agregamos una nueva: "Pares". Esta entidad, es el "tipo de dato" (por llamarlo de alguna manera) que contiene dos enteros, los cuales vamos a sumar.

public class sumaRequest
{
 public List<pares> pares { get; set; }
}


public class Pares
{
 public int numero1  { get; set; }
 public int numero2  { get; set; }
}


public class sumaResponse
{
 public List<int> sumas { get; set; }
}


Bueno, creando objetos de estas entidades y llenándolos con la información necesaria, ya podríamos trabajar perfectamente. LA operación suma, recibe la lista, y simplemente la procesa. Es decir, esto:

sumaResponse hacerTodasLasSumas(sumaRequest request)
{
 sumaResponse ret = new sumaResponse();
    ret.sumas = new List<int>();

 foreach(Pares pareja in request.pares)
 {
  int suma = pareja.numero1 + pareja.numero2;
  ret.sumas.Add(suma);
 }

 return ret;
}

Bueno, esto es muy lindo, pero aún no hemos metido a JSON en todo esto. Pero en realidad, es muy poco lo de tenemos que hacer. Solo hay que desserializar sumaRequest de un string que nos llegue, por otra parte serializar sumaResponse antes de devolverlo al usuario/cliente.

Para esto vamos a agregar el paquete JSON.NET desde Nuget (o la línea de comandos, como quieran). Una vez agregado, modificamos las entidades que directa o indirectamente entran en el JSON.
La diferencia entre entrar directamente o indirectamente, es simple: sumaRequest entra directamente, porque es la entidad que contiene la información del JSON de forma directa. Lo mismo ocurre con sumaResponse, que contiene la información directa que queremos almacenar. Sin embargo la entidad Pares entra de manera indirecta, ya que en realidad, debemos utilizar su contenido dentro del JSON, pero sólo por ser parte de la entidad sumaRequest.
Las entidades, las modificamos de la siguiente manera:

[JsonObject(MemberSerialization.OptIn)]
public class sumaRequest
{
 [JsonProperty(PropertyName = "pares")]
 public List<Pares> pares { get; set; }
}


[JsonObject(MemberSerialization.OptIn)]
public class Pares
{
 [JsonProperty(PropertyName = "numero1")]
 public int numero1  { get; set; }

 [JsonProperty(PropertyName = "numero2")]
 public int numero2  { get; set; }
}


[JsonObject(MemberSerialization.OptIn)]
public class sumaResponse
{
 [JsonProperty(PropertyName = "sumas")]
 public List<int> sumas { get; set; }
}


Lo que hemos hecho con el atributo JsonObject, es indicar que una clase forma parte de una Serializacion/Deserialización JSON (sin importar si es de forma directa o indirecta). Y con el atributo JsonProperty indicamos que el campo en cuestión debe ser serializado. Este atributo además permite especificar cómo se llama el campo cuando la información ser serializa/deserializa a JSON. Claramente, ambos nombres no tienen porqué coincidir.

Finalmente, y para terminar, debemos indicar en algun punto de código, que una string recibida debe deserializarse como entradaRequest, y que sumaResponse debe serializarse como salida. Esto lo hacemos con las funciones JsonConvert.DeserializeObject e JsonConvert.SerializeObject respectivamente. Nos queda así:

public string operacionDelWebService (string jsonRequest)
{
 sumaRequest objectRequest = JsonConvert.DeserializeObject<sumaRequest>(jsonRequest); // (1)

 sumaResponse objectResponse = hacerTodasLasSumas(objectRequest);    // (2)

 string response = JsonConvert.SerializeObject(objectResponse); // (3)

 return response;
}


Como vemos, la funcion -que podría ser la operación visible del WS- recibe y devuelve una cadena, ambas en formato JSON.

En (1) convertimos la cadena en formato JSON a objetos conocidos por nosotros (Deserializamos).
En (2) operamos normalmente con los objetos que conocemos.
En (3) convertimos la respuesta a un string con formato JSON. (Serializamos).

Luego se devuelve el string y todos contentos.
Espero que haya sido de utilidad y simple de entender.

Dejo el código completo funcional.


using Newtonsoft.Json;
using System;
using System.Collections.Generic;

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

            string stringEntrada = " {\"pares\":[{\"numero1\":\"5\",\"numero2\":\"2\"},{\"numero1\":\"1\",\"numero2\":\"-3\"},{\"numero1\":\"-2\",\"numero2\":\"-2\"}]}";
            string stringSalida;

            WebService ws = new WebService();

            stringSalida = ws.operacionDelWebService(stringEntrada);
            
            Console.WriteLine("Respuesta del WS:\n{0}", stringSalida);
        }
    }

    class WebService
    {
        public string operacionDelWebService(string jsonRequest)
        {
            sumaRequest objectRequest = JsonConvert.DeserializeObject<sumaRequest>(jsonRequest);

            sumaResponse objectResponse = hacerTodasLasSumas(objectRequest);    // (2)

            string response = JsonConvert.SerializeObject(objectResponse); // (3)

            return response;
        }
        sumaResponse hacerTodasLasSumas(sumaRequest request)
        {
            sumaResponse ret = new sumaResponse();
            ret.sumas = new List<int>();

            foreach (Pares pareja in request.pares)
            {
                int suma = pareja.numero1 + pareja.numero2;
                ret.sumas.Add(suma);
            }

            return ret;
        }

        [JsonObject(MemberSerialization.OptIn)]
        public class sumaRequest
        {
            [JsonProperty(PropertyName = "pares")]
            public List<Pares> pares { get; set; }
        }

        [JsonObject(MemberSerialization.OptIn)]
        public class Pares
        {
            [JsonProperty(PropertyName = "numero1")]
            public int numero1 { get; set; }

            [JsonProperty(PropertyName = "numero2")]
            public int numero2 { get; set; }
        }

        [JsonObject(MemberSerialization.OptIn)]
        public class sumaResponse
        {
            [JsonProperty(PropertyName = "sumas")]
            public List<int> sumas { get; set; }
        }
    }
}

miércoles, 27 de mayo de 2015

Registrar un Plug-in en Microsoft Dynamics CRM 2015

Ahora si, llegó el momento prometido. Hemos hecho plugins, hemos llamado a webservices desde los plugins... pero ¡no hemos dicho como registrarlos para poder usarlos! Bueno, ahora mostramos cómo (es muy fácil!)

Igual, quiero aclarar que no pretendo dar información exhaustiva, sino solo la necesaria para probar los plugins que escribimos, y por lo tanto las indicaciones que voy a dar son muy básicas. Para más detalles y profundizar en el registro de plugins en el CRM, favor de remitirse a documentación más precisa.

Lo primero es descargar el SDK del Dynamics, esto se consigue acá. Después de descomprimirlo, vemos que hay una carpeta /tools y allí dentro, una carpeta llamada /PluginRegistration. Allí es dónde está la herramienta que se usa para registrar los plugins.

La abrimos, y vemos que necesitamos conectarnos al Dynamics. Creamos la conexión y entramos. Si, así de simple. Una vez dentro, vemos una pantalla igual -o similar- a ésta:



Daremos click a "Register" y luego "Register New Assembly":




Luego nos aparece una ventana para elegir el ensamblado que queremos agregar. Obviamente, el ensamblado es el de nuestro plugin, el cual ha compilado perfectamente. Seleccionamos la DLL correspondiente a nuestro plugin. Para buscar la DLL, le damos click a los 3 puntitos:


Una vez seleccionado el ensamblado, le damos click a "Register Selected Plugin", y si todo sale bien, aparece un cuadro de diálogo informándonos de dicha situación. Además, el plugin figura ahora en la lista de los plugins y workflows registrados.

Con ésto ya tenemos registrado el plugin, es decir, ya está "adentro" del CRM. Pero no hemos dicho cuándo queremos que se ejecute, por lo que ahora solo nos resta registrar un paso. Desplegamos el elemento de nuestro plugin y hacemos click derecho y "Register New Step":

Aparecerá una ventana así, o similar:


Aca detengámosnos un poco. El campo Message indica el "evento" sobre el cual queremos actuar. En este caso, yo seleccioné el evento de creación de una nueva entidad. Otra opción podría ser "Update", "Delete", etc.
El campo Primary Entity permite especificar la entidad sobre la que vamos a atender el evento de creación. Yo seleccioné "account" por ser una que viene por default. Y finalmente, indiqué que el plug-in se ejecute previamente a la validación (pre-validation) de los datos ingresados. Esto lo hice para evitar que me almacene siempre una nueva account, ya que yo solo quiero probar si funciona el plugin, no andar registrando una nueva cuenta cada vez. Aquí por supuesto elijan la opción más conveniente para su caso.

Finalmente, le damos a "Register New Step" y se registrará el paso. Con esto, ya podemos ir al CRM, y probar de crear una nueva cuenta y ver si el plugin se ejecuta, o no.

Un tip: el campo "Run in User´s Context" indica bajo cuál usuario el plugin se ejecutará. Con la opción "Calling User", con cualquier usuario que intente registrar una cuenta se ejecutará el plugin.

Espero que haya sido útil, y bienvenidos los buenos comentarios y sin spam! ;)

Saludos!