Buscar en este blog....

Mostrando entradas con la etiqueta Ingeniería de Sistemas. Mostrar todas las entradas
Mostrando entradas con la etiqueta Ingeniería de Sistemas. Mostrar todas las entradas

jueves, 30 de marzo de 2017

A tool with a fool, it's still a tool ;)

a tool with a foolTwo weeks ago a colleague came to me extremely happy, jumping like a happy Bunny to ask me if I could use the only license of NDepend that we have in the firm to get the metrics and the graphics of his new code he was proud of. Eight months back in time, we bought this tool, because I downloaded a trial version that I tried for... well, now I don't remember if it was 14 days or a month. But I was quite satisfied with it, so I asked to get a license. And I was listened. ;)

But the funny part of this story is that at that time, when I first tried it, this colleague came to me (this time not like happy Bunny) a told me "Good programmers don't need tools. I don't mean to offend you, but a fool with a tool, it's still a fool."... Now he's asking if he can get his own license too.

The interesting part of this, it's not in fact to say that "people who lives in glass houses should never throw stones", but to point out the motivational change that I noticed in this person. When he decided to throw his code in a metric tool, he also started thinking about how to write his code better. how to architect his solution, and taking care about dependencies, death code, etc.

NDepend DashboardSo, my conclusion is that when people see how good or bad his code actually is (in this case based on numeric metrics and graphics), they feel more motivated to do it better. Your quality doesn't live in the ether, you can actually see it! By the way, I must say that NDepend is a great tool, that I can fully recommend.

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!

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.

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!

martes, 26 de mayo de 2015

Llamar a un Web Service desde un Plug-in de MS Dynamics

En este post vamos a ver como se hace para que un plug-in que hemos realizado nosotros mismos realice una llamada a un web service (que puede o no ser nuestro). Como siempre, estoy utilizando la versión de Dynamics 2015.
En este caso vamos a utilizar un web service que se pueda encontrar por Internet. Se trata de un conversor de unidades que encontré en la siguiente página:

http://www.webservicex.net/

El servicio en cuestión está en http://www.webservicex.net/ws/WSDetails.aspx?CATID=2&WSID=10, aunque si por algún motivo no se encuentra, no tienen más que buscar el servicio "Currency Convertor" desde la página principal. Ahora, si la página principal no funciona más, mala surte. Eso ya es algo que me trasciende.

Primero: Agregar la referencia al servicio.

Bien, primero lo primero: agregamos la referencia al servicio web haciendo click con el botón izquierdo sobre la carpeta "References" del proyecto, y después en "Add Service Reference".
Cuando se abre la vetana, vemos un cuadro de texto que dice "Adress". Bueno, allí vamos a copiar el WSDL del servicio.

El WSDL es un archivo XML que contiene el contrato del Web Service: qué hace, y con qué lo hace. Así podemos saber qué métodos tiene para ofrecernos, y qué parámetros requieren esos métodos. Ah, y también -lógicamente- que datos devuelven!
Para nosotros, esta URL es la siguiente:

http://www.webservicex.net/CurrencyConvertor.asmx?WSDL

Bien, una vez que ponemos la URL del WSDL del servicio que vamos a usar, le damos a "Go". Aparecerá una lista con los servicios que podemos utilizar. Abajo de la lista, hay una cuadro que dice "Namespace". Allí pondremos el nombre del namespace que "contedrá" el servicio después. Para nuestro caso, podría ser, por ejemplo: "WS_Curr" (que como habéis adivinado viene de "Web Service CURRency" ;)
Le damos aceptar.
Con esto, ya podemos usar los métodos y tipos que provee el web service sin que Visual Studio se enoje y lo subraye con rojo. La variable channel es la que está representando la instancia de nuestro web service.

Segundo: Instanciar el Web Service

Segundo lo segundo: creamos una factory utlizando un Endpoint y un Binding para crear canales de comunicación con el web service. En realidad, nosotros solo vamos a utilizar un canal.

BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Name = "CurrencyConvertorSoap";
myBinding.Security.Mode = BasicHttpSecurityMode.None;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

EndpointAddress endPointAddress = new EndpointAddress("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
ChannelFactory factory = new ChannelFactory(myBinding, endPointAddress);
CurrencyConvertorSoap channel = factory.CreateChannel();

Tercero (y último): Utilizar el servicio.

Esta es la parte más sencilla de explicar para mi, y entender para ustedes -o para mí si me olvido :)-
Para usarlo, se usa como se usaría cualquier método que está en otro namespace. Si queremos ver a cuantos pesos argentinos está el euro, no tenemos más que llamar al método adecuado, con los parámetros adecuados. Y en la segunda y última linea, mostramos una excepción desde el plug-in para ver si esto funcionó o no. He aquí:

double lalala = channel.ConversionRate(Currency.EUR, Currency.ARS);
throw new InvalidPluginExecutionException("No se si te interesa, pero el EURO está a: " + lalala.ToString());


Al ejecutarse este plug-in en MS Dynamics, deberíamos ver una excepción que mostrara el mensaje con el preciod el euro.
En definitiva, llamar a un web service desde un plug-in en Dynamics es algo extremadamente simple, como pueden ver. A continuación dejo el código completo del ejemplo, y sigue la promesa de en un próximo post mostrar como registrar un plug-in en Ms Dynamics.

using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace Plugin_Prueba
{
    public class Class1 : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));            
                                    
            BasicHttpBinding myBinding = new BasicHttpBinding();
            myBinding.Name = "CurrencyConvertorSoap";
            myBinding.Security.Mode = BasicHttpSecurityMode.None;
            myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
            myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

            EndpointAddress endPointAddress = new EndpointAddress("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
            ChannelFactory factory = new ChannelFactory(myBinding, endPointAddress);
            CurrencyConvertorSoap channel = factory.CreateChannel();

            double lala = channel.ConversionRate(Currency.EUR, Currency.ARS);
            throw new InvalidPluginExecutionException("No se si te interesa, pero el EURO está a: " + lala.ToString());
        }
    }
}


Saludos y bienvenidos los comentarios con buena onda -y sin spam!-

viernes, 22 de mayo de 2015

Escribir un Plug-In para MS Dynamics CMR 2015

Esta vez vamos  a escribir un poco de código. Hoy quiero mostrar cómo escribir un plug-in para ejecutar desde Microsoft Dynamics. Si bien yo estoy utilizando la version 2015, sirve para algunas anteriores, aunque desconozco exactamente hasta donde se aplica. Próximamente, en otra entrada del blog, voy a mostrar como registrar el plugin en MS Dynamics y asociarlo a algún evento particular.

Bien, la verdad es que crear un plug-in, en términos básicos, es muy, pero muy simple! De hecho vamos a comenzar con lo primero: agregar las referencias necesarias.

1. Primero lo primero.

Obviamente, comenzamos creando un proyecto. Este proyecto será simplemente una librería de clases (Class Library).

2. Agregar las referencias necesarias.

Lo segundo que tenemos que hacer es agregar las siguientes referencias:

  1. System.Runtime.Serialization
  2. System.ServiceModel
  3. Microsoft.Xrm.Sdk.dll
  4. Microsoft.Xrm.Client.dll
  5. Microsoft.Crm.Sdk.Proxy.dll

Las dos primeras se encuentran dentro de los ensamblados del framework. Las tres restantes debemos buscarlas dentro de la carpeta /bin de la carpeta descargada del "Dynamics CRM SDK".

3. Comenzar a escribir el plug-in.

Lo primero que vamos a tener en cuenta, es que la clase del plug-in debe implementar la interfaz IPlugin, el cual nos va a obligar a implementar el método Execute, cuyo código será ejecutado por el motor de ejecución de plug-ins dentro del CRM. En definitiva, tendremos esto:

public class Class1 : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {

        }
    }
Dentro de Execute escribimos nuestro plug-in. Por supuesto, podemos valernos de otras clases y métodos para implementar lo que querramos.

4. Firmar el Plugin

Este paso es escencial, de lo contrario ¡no podremos registrar el Plugin! Igualmente es fácil: Vamos a las propiedades del proyecto (Click izquierdo sobre el nombre del proyecto, y después en properties), y alli buscamos la pestaña "Signing". Checamos "Sign the assembly" y en "Choose a strong name key file" seleccionamos "New". Allí penemos un nombre cualquiera, pero SIN contraseña. Y listo, ya podemos compilar y registrar el plugin.

Trazas para la ejecución.

Bastante común es el caso de utilizar traces para hacer una traza de la ejecución. ¿Y ésto por qué? Porque un plug-in, como podréis imaginaros, es bastante difícil de debuggear. De hecho, la única forma es ejecutando es plug-in desde el CRM y mirando luego la traza de la ejecución. Para esto, creamos el servicio de traza con lo siguiente:

ITracingService tracingService;
tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));


y luego ir escribiendo algo que nos permita seguir la traza. Esto lo haremos llamando a:
tracingService.Trace("Paso 1");


Si intercalamos llamadas a tracingService.Trace("Paso X") dentro de nuestro código, podremos saber hasta dónde se ejecutó el plug-in. Si, por ejemplo falla, veremos que la traza nos muestras el lugar al que llegó antes de lazar la excepción. Acá muestro un ejemplo de traza:
using Microsoft.Xrm.Sdk;
using System;

namespace Plugin_Prueba
{
    public class Class1 : IPlugin
    {

        public void Execute(IServiceProvider serviceProvider)
        {

            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            tracingService.Trace("Paso 1");

            Entity entidad = (Entity)context.InputParameters["Target"];

            tracingService.Trace("Paso 2");

            if (entidad.Attributes.Contains("name") && entidad.Attributes["name"].ToString().Length > 5)
            {
                tracingService.Trace("Paso 3");
                throw new InvalidPluginExecutionException("Epa! El nombre tiene que tener más de 5 caracteres.");
            }
            tracingService.Trace("Paso 4");
        }
    }
}
Entonces, si durante la evaluación de la primera condición del if lanza una excepeción (si por ejemplo, el atributo "name" no existiera), se lanzará una excepción en el CRM y tendremos la opción de ver la traza. En la misma, figurara algo parecido a esto:
Paso 1
Paso 2
Pero no veremos "Paso 3" porque se lanzó la excepción y no se llegó a ejecutar esa parte. En la próxima entrada, veremos como registrar el plug-in para que el CRM lo pueda ejecutar. Es también algo muy sencillo.

Saludos!

jueves, 16 de mayo de 2013

Ejemplo: Implementacion del Patron Singleton en C++

Buenas! Si, después de casi dos años de inactividad, volví para mostrar la implementación de un patrón Singleton en C++.

Como sabemos, una clase que implementa este patrón, tiene una característica muy importante: no puede crearse mas que una instancia (objeto) de esa clase. Pero claro, esta caracteristica es relevante o toma importancia en algunos casos. Personalmente, donde mas utilizo este patron es cuando creo "fabricas", es decir, utilizo el patron Factory para con alguna finalidad. El patron Factory lo dejo para otro momento, y es igual de interesante y util que el Singleton pero ahora no viene al caso.

Entonces, lo importante que debemos tener en cuenta, es que sin importar cuantos objetos queramos crear, solo estaremos creando una y solo una instancia de esta clase. Si por ejemplo creamos 5 variables de una clase llamada MiClase e instanciamos dichas variables, todas las variables corresponderán a la misma instancia. Es decir, sera indistinto utilizar una u otra de estas variables para acceder a los métodos y atributos del objeto.

Pero este patron tiene dos puntos que hay que tener en cuenta:

Punto 1. No puede inicializarse "manualmente".
Es decir, no podemos hacer la asignación con new:
MiClase ObjetoA = new MiClase();

Es imposible! Y por que? Porque el constructor debe ser privado. De esta forma nos aseguramos que no se pueda andar creando instancias libre y salvajemente por ahí. Bueno, si no se pueden crear instancias... cómo hacemos para exista esa famosa única instancia?

Punto 2. Alguien debe crear la instancia única.
Y si, nada es magia en esto de la programación. Quien puede crear la instancia? Bueno, pues la misma clase! Es decir, que de alguna manera, la clase debe crear una instancia de si misma y asegurarse que sea solo una. Esto lo haremos con un método que le llamaremos, por convención nomás: getInstance().

Es decir, que para obtener la unica instancia de una clase que implementa el patron Singleton, haremos algo asi:
MiClase ObjetoA = MiClase()::getInstance();

Súper fácil! Y ahora si, ObjetoA apunta directamente a la instancia única de la clase MiClase. Ahora veamos que se esconde detrás de todo esto, en términos de C++. Como toda clase de C++ tendremos los archivos .h y .cpp:

MiClase.h
En este archivo lo importante a tener en cuenta es:
  • El constructor MiClase() es privado. No podrá usarse la palabra clave new.
  • Tenemos un atributo estático llamado unica_instancia que es un puntero a la clase que lo contiene y que tambien es privado. No podra accederse desde fuera de un objeto.
  • El método getInstance() es también estático! Claro, sino no podría accederse hasta tener un objeto de la clase, y justamente este el método que crea el primer (y único) objeto, con lo cual debe ser estático si o si.
class MiClase
{
private:
 MiClase(void);
 static MiClase* unica_instancia;
 
public:
 ~MiClase(void);
 
 static MiClase *getInstance()
 {
  if(unica_instancia == NULL)
   unica_instancia = new MiClase();
   
  return unica_instancia;  
 } 
};


MiClase.cpp
Acá lo importante es inicializar la variable estática unica_instancia. La inicializamos en NULL de forma que nos aseguremos que no se crea ningún objeto hasta que se llame por primera vez a getInstance().
Atención! El caso particular de C++ requiere que las variables estáticas sean definidas en el archivo .CPP y no en el .H. Caso contrario se obtiene un error de compilación.
#include "MiClase.h"

MiClase* MiClase::unica_instancia = NULL;

MiClase::MiClase(void)
{
}
MiClase::~MiClase(void)
{
}

Por ultimo, cabe explicar brevemente lo que hace el método getInstance(). Básicamente, crea una instancia de la clase solo en el caso de que no exista una (por eso el if). Luego devuelve la instancia creada o, sino creó porque ya existia, devuelve la existente. Asi es seguro que no tendremos mas de una instancia.
Saludos!

sábado, 4 de septiembre de 2010

Ejemplo de uso del patron Observer

Ahora que hice el último patrón que se nos había encomendado implementar, el patrón Observador, voy a poner el ejemplo como hice con el patrón Command.

La idea es la siguiente: tenemos un caso de uso "Marcar Gol" que se dispara -imaginemos- cuando un sensor ubicado en un arco de fútbol detecta que pasa la pelota. Al dispararse este caso de uso, se llama al método de su experto anotarGol(), quien -entre otras cosas- llama al método actualizar() de SuscriptorGoles.

La interfaz del caso de uso "Ver Resultados" llama al método inciar() del controlador, con el cual éste se suscribe a SuscriptorGoles para que SuscriptorGoles llame al método actualizar() del controlador. Este método, lo implementa de la interfaz IObservadorGoles.

Notemos que SuscriptorGoles tiene un arreglo (o lista) de IObservadorGoles para actualizar a cada observador suscrtipto a el.

En el diagrama de clases olvidé especificarlo, pero conviene que SuscriptorGoles sea un singleton, ya que no vamos a usar más que una sola instancia de él.

Implementación en C#: Descargar

Salutes!

viernes, 3 de septiembre de 2010

La estrategia del Cartógrafo

Todos los que hayan leido el conocido libro de Craig Larman "UML y Patrones", ya saben a que me refiero. Para quienes no, y para tenerlo en mi colección bloggera de temas interesantes, lo pongo.

La estrategia del cartógrafo está explicada en la parte del libro que habra sobre la construcción de modelos conceptuales. La idea que propone es tener en cuenta tres sugerencias que seguir al momento de trazar un mapa o, en nuestro caso, modelar un dominio.

Un modelo conceptual es una especie de mapa de las cosas del dominio que estamos analizando. Las tres sugerencias para tener en cuenta son:

1) Utilizar los nombres existentes en el territorio. Los cartógrafos utilizan los nombres que se usan en ese territorio, no les inventan nuevos nombres a las cosas. Es decir, que el vocabulario que usemos cuando asignamos el nombre a los conceptos y atributos sea el mismo que se usa en el dominio. Por ej: si en un modelo de supermercado, el personal llama "Comprador" a los clientes, nosotros le llamaremos como tal y no "Cliente" o "PersonaQueCompra" o cualquier otro nombre que nos guste más.

2) Excluir las características irrelevantes. Los cartógrafos deben omitir en su mapa las cosas que no les parecen importantes, es decir, aquellas que no contribuyen con el propósito que persiguen, como por ejemplo, la población en determinados lugares, o la salinidad de la tierra, etc. En nuestro ámbito, y siguiendo con el ejemplo del supermercado, nos puede convenir excluir conceptos como "Proveedor" si es que los proveedores no son relevantes para los requerimientos actuales. Hay que tener cuidado en esto, porque algunos conceptos pueden no ser tan obvios respecto de su relevancia, y podemos omitir algo que en el futuro será necesario.

3) No agregar cosas que no existan. El ejemplo que se menciona en el libro no puede ser más claro: ¡un cartógrafo no va a poner una montaña si ésta no existe! Con esto se refiere a que es conveniente excluir todo aquello que no forma parte del dominio del sistema que se analiza.

Claro no hay que cumplirlas al pie de la letra (por algo son sugerencias) pero a mi parecer son muy simples y muy prácticas. A veces hasta pueden sonar obvias e innecesarias, pero lo que me agrada es que son muy útiles para esos momentos en que el sistema "nos puede", esos momentos en que nos perdemos en el mar de conceptos, requerimientos y descripciones que tienen los sistemas grandes...

Hasta la próxima.

sábado, 28 de agosto de 2010

Ejemplo de uso del patron Command

Buenas, gente. Decidi subir este ejemplo al blog porque tuve que hacerlo para la facultad y por ahi viene bien ver algunos ejemplos, aunque que abunden en internet.
Como dije, se trata de un ejemplo aplicado del patrón Command a un negocio que tiene que ver con una escuela.

La idea es que cuando en dicha escuela se programan las fechas de exámenes, se debe notificar a los profesores, a los padres de los alumnos, a la Dirección General de Escuelas, y debe además, mostrarse en la cartelera. Es un caso ficticio, inventado para el ejemplo. La idea es que a los profesores se les debe enviar una notificación impresa a la casa, a los padres se les avisa por e-mail, a la DGE se le puede avisr por e-mail o por notificacion escrita (da igual). Digo que da igual, porque no me he centrado en el proceso particular de cada notificación en sí, sino solo en la aplicación del patrón Command.

Cuando el experto del caso de uso "Programar Fechas de Examenes" confirma dichas fechas, se debe proceder a hacer las notificaciones para cada caso. Eso es lo que está en el ejemplo.

El lenguaje utilizado es C#, con el IDE Visual C# 2008 Express Edition. Pueden descargar el código fuente y ver el diagrama de clases.

Código Fuente : Descargar
Diagrama de Clases: Descargar o la imagen.

Saludos!

viernes, 29 de mayo de 2009

¿Validar las precondiciones?

La idea de escribir este postsurgió de una charla que esuché ayer entre un compañero de la meteria "Diseño de Sistemas" y la profesora. Él decía que las precondiciones no se debían evaluar dentro del caso de uso -o sea que no debería ser parte del flujo de ese caso de uso el validar que dichas precondiciones se cumplirian- y por el contrario, son condiciones que ya deben haberse cumplido antes de disparar ese caso de uso. La profesora, en el otro extremo le decía que sí debían validarse dentro del caso de uso.

En principio estuve de acuerdo con mi compañero, porque pensé que esa es justamente la definción de "precondición" (de hecho, la misma palabra lo dice).

Además, la definición formal de precondición es: "una operación que debe ser cierta cuando se invoca una operación". En el Manual de Referencia de UML se agrega, despues de esta definición, que el receptor no debe tener que verificar la condición.

Aunque con estos argumentos parece tener la última palabra mi compañero, la profesora tenía algo más que razón. Quizás su punto de vista no encaja exactamente con el del paradigma de orientación a objetos, o mejor dicho, con las definiciones que se proponen en UML. ¿Entonces está mal su punto de vista?

No. Si recordamos los principios básicos de la orientación a objetos, uno de ellos se refería a la capacidad de reutlizar componentes. Componentes que son de un sistema, pero sirven para otro, pueden ser reutilizados para evitar volver a construirlos. Un caso de uso, por ejemplo, puede ser reutilizado si dos sistemas tienen algun requisito en común. Este caso de uso tendrá sus propias precondiciones que el peimer sistema (llamémosle sistema A) se encarga de "poner a punto" antes de llamarlo. Con "poner a punto" me refiero a que el sistema sabe que caso de uso se llamará -previo al caso de uso que vamos compartir- de forma que el sistema queda en un estado tal que el caso de uso que vamos a compartir tiene "verificadas" esas precondiciones.
¿Pero quien me asegura que esto sea realmente asi? o peor aún, ¿quien me asegura que el nuevo sistema (sistema B) también se encargue de llamar al caso de uso compartido con las precondiciones validadas? Nadie.

Entonces, quizás sea esto lo que la profesora quería decir. Si el mismo caso de uso verificara sus precondiciones, entonces no hay problema de reutilizarlo, ya que el mismo se asegura -donde quiera que lo pongan- que las condiciones se validen. De no validarse, sencillamente no se ejecutará. Esto evita que el sistema llegue a estados no válidos, o de resultados incorrectos.

Entonces, ¿para qué están las precondiciones? Bueno, es un dato más sobre la interfaz del caso de uso. Si conozco las precondiciones, no necesito saber que hace un caso de uso -qué valida y que no- sino simplemente usarlo. Es decir, la precondición como tal es un aspecto más bien ligado al análisis y al diseño, mientras que la verificacion de ésta está más ligada a la implementación.
También ayudan a percibir los flujos posibles entre casos de uso: un caso de uso solo podrá ejecutarse si anteriormente, otros casos de uso han dejado el sistema en un estado tal que éste pueda ejecutarse.

miércoles, 29 de abril de 2009

Avances de UML: Modelado en Colores (Parte 1)

UML tal y como se lo usa en la mayoría de lo casos, nos permite mantener un nivel de abstracción que elegimos nosotros mismos. Y lo elegimos según cual sea el nivel de detalle que nos interese percibir en un determinado modelo. Por ejemplo, en una clase de análisis, no nos importa conocer el tipo de dato que un atributo puede tener; con saber con el atributo existe nos basta; e incluso, si nos abstraemos más aún, podemos lograr que ese mismo atributo sea totalmente irrelevante, a tal punto que desaparezca por completo de la clase (aunque cuidado, para niveles menores de abstracción, éste seguirá existiendo).

Técnicas de abstracción hay muchas, y más de una vez nosotros mismos tenemos nuestras propias formas “simplificar un modelo” aún sin pretenderlo conscientemente.

Como ejemplo, en UML, podemos agrupar los elementos que se pueden manipular como un todo en los llamados paquetes. Y esto, nos permite concentrarnos en el paquete como una sola cosa, y no como los muchos componentes que puede contener. Esto es realmente útil cuando tenemos demasiados elementos para analizarlos todos en detalles, y más aún, cuando algunos de esos elementos no los queremos analizar en detalle.

Utilizar paquetes, es sólo una forma de abstraernos de algunos aspectos del dominio. Seguramente existen muchas otras, pero sin duda una de las más interesantes, tiene que ver con el uso de colores en los diagramas de UML.

Peter Coad, Eric Lefevre y Jeff De Luca realizaron investigaciones sobre este último punto: el uso de colores para el modelado de sistemas. El lenguaje que utilizaron para “colorear” fue el Lenguaje Unificado de Modelado (UML). El resultado de estas investigaciones, es una notable técnica, que nos permite identificar a simple vista, los distintos tipos de elementos que existan en un dominio de negocio dado, y además nos permite saber qué tipos de elementos son. A este “tipo de elementos” ellos les llamaron: arquetipos. (“archetypes”, en inglés). En su libro “JAVA Modeling COLOR with UML” ([Coad99]) explican con detalle ésta técnica.

Esta técnica de coloreado nos permite analizar un modelo y entenderlo rápidamente por encima. El hecho de usar color en un modelo –por ejemplo, en un diagrama de clases- no da una perspectiva general de cómo está conformado el modelo, aún antes de mirarlo con detalle, porque como veremos más adelantes, estos modelos siguen un patrón genérico llamado “Componente de Dominio Neutral” (Domain-Neutral Component).

Esta técnica, además de ayudar a quién examina un modelo, también ayuda a diseñar modelos. Esto es así porque si tenemos en cuenta que los procesos de negocio siguen ciertos patrones (algo que Coad y los otros notaron), entonces se puede armar un modelo con sólo identificar las partes del dominio donde se pueden ajustar esos patrones.

(continuará..)

jueves, 26 de marzo de 2009

¿Generalizacion o Inclusion? Esa es la cuestion.

Esta pregunta surgió en un curso de Diseño de Sistemas, en tanto la profesora pretendia poner a prueba los conocimientos conceptuales supuestamente adquiridos por los alumnos en el curso anterior de Analisis de Sistemas. Todos tiraban ideas, pero costo un buen tiempo entre los cincuenta alumnos llegar a una conclusion importante.

Podemos imaginarnos el siguiente diagrama de Casos de Uso. Si la descripcion del sistema dice que “los pacientes pueden internarse por obra social o de forma particular”, es casi evidente –intuitivo incluso- pensar en una especialización de un caso mas general denominado “Internar”. Algo así:

Esto a simple vista nos resulta correcto, aceptable y hasta tipico y seguimos adelante. Pero la pregunta que podria surgirnos es. ¿Por que especializamos? ¿Por que no incluimos? Es decir, ¿estaria mal el siguiente diagrama?
Que diferencia presenta con el anterior, si ambos pueden hacer exactamente lo mismo. Para asegurarnos de esto, recordemos que es una generalizacion y que es una inclusion.

Inclusion: Es una forma de interaccion, un caso de uso dado puede "incluir" otro. El primer caso de uso a menudo depende del resultado del caso de uso incluido. Esto es util para extraer comportamientos comunes desde multiples casos de uso a una descripcion individual, desde el caso de uso que lo incluye hasta el caso de uso incluido. El comportamiento del caso incluido es colocado dentro del comportamiento del caso de uso base. No hay parametros o valores de retorno.

Generalizacion: Un caso de uso dado puede estar en una forma especializada de un caso de uso existente. Esto se asemeja al concepto orientado a objetos de sub-clases. En la practica puede ser util generalizar comportamientos comunes, describirlos una vez, y enfrentarse a los detalles excepcionales en los casos de uso especializados. Entonces la Generalizacion es la actividad de identificar elementos en común entre conceptos y definir las relaciones de un concepto general y un concepto especializado. Es una manera de construir clasificaciones taxonomicas entre conceptos.

Ya tenemos definidos ambos tipos de relaciones. Las definiciones parecen indicar que estos conceptos son bastante diferentes el uno del otro, y, de hecho los son, pero ¿donde radica la diferencia en el ejemplo dado? Es posible implementar un sistema usando el modelo con generalizacion, y funcionaria de la misma manera que si se implementara el modelo de inclusion.

En el primero, el paciente va a internarse activando el CU “Internar”. Supongamos que el paciente tiene una obra social: entonces el C.U. que se activa es “Internar con Obra Social” aplicando los pasos generales de “Internar” y en el punto indicado se siguen los pasos que pertenecen a la especializacion que, en este caso, se es “Internar con Obra Social”.

En el segundo modelo, el paciente activa directamente el caso de uso “Internar con Obra Social”, el cual realizara los pasos referidos a una internación con obra social llamara al caso de uso “Internar” en el momento que deba realizar los pasos generales.
Como vemos, ambos funcionan sin problemas. La pregunta –insisto- es: ¿porque el segundo no se utiliza?

Dejo abierta la pregunta para quien quiera pensarlo un poco.
Saludos.