Buscar en este blog....

Mostrando entradas con la etiqueta Arquitectura Software. Mostrar todas las entradas
Mostrando entradas con la etiqueta Arquitectura Software. 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!

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.

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!

miércoles, 31 de diciembre de 2014

¿Cómo testear métodos privados?

A la hora de hacer los unit testing, tarde o temprano nos llega indefectiblemente la pregunta: ¿cómo testeo un método privado?

El asunto en cuestión es motivo de distintos puntos de vista, opiniones, y discusiones. Sin embargo basado un poco en la experiencia personal y la ajena, más un poco de literatura, ofrezco mi punto de vista.

Existen dos opiniones diferentes al respecto: unos dicen que los métodos privados no deben testearse, y otros que si. Ah, y bueno, están los grises que dicen que "depende de la situación". Yo me incluyo en este último grupo. La ingeniería de software es una ciencia muy "gris" todavía.

La cruda realidad, es que con muchos de los frameworks no podemos testear métodos privados, por la simple razón de que son privados y no podemos acceder a ellos. (No lo dije antes, pero doy por hecho que los tests se encuentran en un proyecto aparte de aquel que contiene el código que estamos testeando y por eso no podemos accederlos).

Los que dicen que no deben testearse métodos privados, tienen sus razones. Principalmente sostienen que solo debe testearse la interfaz de, pongámosle, una clase. Es decir, todos aquellos métodos públicos que sirven de interfaz al mundo exterior (los programadores que utilizan estos métodos). Y que a su vez, los métodos privados son solo "ayudantes" de los métodos públicos. Estos pueden cambiar con mayor frecuencia que los métodos públicos, y por tanto, una eventual modificación de los métodos privados que no debiera alterar los resultados de los métodos públicos, podría hacer fallar los tests que testean los métodos privados. Es decir que se cambió el comportamiento interno sin alterar el comportamiento externo y que, por lo tanto, solo debemos preocuparnos por testear el comportamiento externo.

Yo no estoy precisamente de acuerdo con este punto de vista. Si queremos testear el método, deberíamos poder. La realidad es que así nomás no se puede. Entonces salen alguna alternativas que voy a mencionar, y me alegraría siempre de escuchar o leer nuevas.

1) Mover los métodos privados a una nueva clase.
Si el/los método/s privados que queremos testear lo ameritan, los refactorizamos creando una -o más- nueva clase que solo los contenga a ellos -pero como métodos públicos- y no formen parte de la interfaz de nuestra clase. De esta forma seguirán estando "ocultos" hacia el mundo exterior (porque no pertenecen a la interfaz), y sin embargo ya podemos accederlos tranquilamente desde el proyecto de testing.

2)  Convertir los métodos privados en públicos.
No soy un gran entusiasta de esta opción. Creo que si un método se pensó privado, privado debe permanecer. Si se cambia a público, la razón debería tener que ver con otras cuestiones y no con el testing. Pero ya dicho, es una opción más.

3) Convertir los métodos en internal.
Desconozco si existe en otros lenguajes el equivalente a internal de C#. Con esto permitimos que las clases dentro del mismo ensamblado se puedan ver. Sin embargo, fuera del ensamblado siguen permaneciendo ocultas. Y debemos especificar a qué ensamblado le damos visibilidad (con [assembly:InternalsVisibleTo("MyTests")]).

Cuando puede utilizarse, soy partidario de la tercera forma, ya que es bastante más limpia. En otro caso, habrá que evaluar qué hacer, o incluso si coincidir con quienes dicen que los métodos privados no tiene estrictamente que testearse.

Hasta pronto!

jueves, 25 de diciembre de 2014

Fakes, Stubs y Mocks... ¿cuál es la diferencia?

Buenas!
Como me viene pasando últimamente, pasan décadas de un posteo a otro. Sin embargo y pese a ello: sigo posteando ;)

El tema de este post surgió nada menos que de darme cuenta que los conceptos que voy a explicar, no estaban adecuadamente explicados en la facultad a la que asistí. Quizás esto ya haya cambiado, pero considero que son términos importantes como para estar mezclándolos cual ensalada de frutas.

Básicamente, donde yo estudié la idea -muy genérica y nada desarrollada- de un Stub nunca se mencionó la diferencia entre Stubs y Mocks, y tampoco la diferencia entre éstos dos con un Fake. Es más, me atrevo a decir que nunca se habló de Fakes y Mocks. Pero bueno, no es el fin de este artículo evaluar ni criticar lo que tuve que estudiar, sino más bien, aclarar los conceptos.

Todo esto viene a colación de la importancia que han tomado los Unit Tests (Tests de Unidad) de los cuales no voy a hablar ahora para no extenderme en el tema. Doy por hecho que ya sabes lo que son.

Pero, ¿por qué es importante? 

Es de suprema importancia realizar UTs que sean legibles, que cualquier persona que nunca los vio antes pueda leerlos y darse cuenta de inmediato qué quiso testear quien lo escribió. Si esto no es así, se pierde la filosofía que está detrás de los UT, que es justamente proporcionar un método muy rápido de testeo. Si un programador tiene que dedicar mucho tiempo a entender un test que ha dado FAIL (o peor aún: muchos tests!) por el solo hecho de que se escribió mal o que es ilegible, el resultado es terriblemente predecible: no lo va a leer y lo va a dejar de lado porque entender y/o arreglar ese test le va a consumir mucho tiempo, y seguramente "tiene cosas más importantes que hacer". Se ignora el test, se lo marca como obsoleto, etc. Y allí comienza la decadencia del sistema. Y de la calidad. Y de la mantenibilidad. Y etc, etc.

Siempre es una necesidad que tengas claro los conceptos referidos a tu especialidad, a lo que te dedicas a hacer.

Antes que nada, esta entrada presupone que ya sabes lo que es un test de unidad, cual es su finalidad, y que significan las tres A (Arrange-Act-Assert). Si no es asi, sería bueno que le googlearas por ahí.

Bien, comencemos entonces:

¿Qué es un Fake?
El verbo "to fake" en inglés es fingir, falsificar. Eso es lo que es un Fake: una falsificación de un objeto. (Hablo de "objetos" por que normalmente en mi blog me refiero a la OO (orientación a objetos) por ser la que más utilizo, pero es aplicable también a otros paradigmas.)

Es decir, es un objeto que es una falsificación de otro. Se ve "igual" pero se comporta distinto.

¿Y para qué sirve?
Porque si queremos realizar pruebas de unidad, es indispensable que estas sean rápidas! Pero no sólo por esto! Sobre todo que el comportamiento de la clase (o unidad de trabajo) que estamos testeando (llamémsole UUT de "Unit Under Test") no se debe ver influenciado por el comportamiento de algún otro objeto del que pueda hacer uso. Si por ejemplo queremos testear el método de una clase que por dentro hace uso de un objeto que se comunica con la base de datos, tenemos dos problemas:

  1. El objeto que utiliza la base de datos (llamemosle "ConexionConBD") hará muy lento el testing, ya que debe conectarse con la mismísima base de datos, entorpeciendo este principio.
  2. Si el objeto "ConexionConBD" falla cuando nosotros esperamos que no falle, entonces fallará también el UUT (nuestra unidad bajo testing)..
  3. Si la mismísima base de datos falla (por la razón que fuere, cualquiera), nuevamente fallará también nuestro UUT.

Y el problema con las fallas que son "ajenas" a nuestro UUT, es que finalmente no vamos a saber si lo que falla es el UUT, o es alguno de los objetos que éste utiliza. Y pierde sentido el concepto de "Test de UNIDAD".

Entonces, para solucionarlo, inventemos un "ConexionConBD" que responda lo que nosotros queramos, cuando nosotros queramos, y como nosotros queramos. Es decir, falsifiquemos esa clase. Para ello, crearemos un Fake de la clase "ConexionConBD", la cual podemos controlar desde el test que estamos escribiendo.

No voy a entrar en detalles técnicos de como se hace, ya mucho en internet sobre como hacerlo.

Entonces....

¿Qué es un Stub?
El Stub, es ni más ni menos, un subtipo de Fake. Si, asi de simple: los Fakes se dividen en dos clases: o son Stubs, o son Mocks. ¿Y de qué depende? De según como se use, de eso depende!

En el caso anterior, podemos utilizar el Fake "ConexionConBD" para que siempre nos devuelva un valor esperado, así no nos encontramos con sorpresas. Una vez que el fake nos devuelve el valor que esperamos, podemos proseguir con el test.

Pero al usar este fake como un Stub, éste sólo puede utilizarse para devolver un valor o arrojar una exepción. Pero nada más. NADA MÁS! Es decir, el test se sigue haciendo directamente contra nuestro UUT.



¿Y qué es un Mock?
En el caso anterior, el fake se utiliza solo para que devuelva un valor esperado, es decir, que realice un comportamiento definido y así poder proseguir con nuestro test.

Pero en otras ocasiones, el test mismo consiste en saber si el UUT se comunicó de forma esperada con otro objeto. Por ejemplo, queremos saber si el UUT llamó al objeto "ConexionConDB" de forma correcta. En este caso, no podemos hacer un assert directamente contra la UUT, ya que la UUT mismo no sabe si la llamada -a un método por ejemplo- fue realizada con éxito. Quién sabe esto, es el objeto llamado en cuestión, es decir, el objeto "ConexionConBD". Pero el "ConexionConBD" original  (aquel que se conecta con la base de datos) no está programado para decirnos si la llamada que le hicieron fue correcta, y encima, se conecta con la base de datos! (algo que queremos evitar!).

Solución: le hacemos un fake. Pero este fake no devuelve un valor, sino que simplemente recibe la llmada que le hace la UUT y, nuestro test, en lugar de hacer un assert contra la UUT, lo hace contra el Fake.



Y esta es la clave: cuándo nuestro test verifica (assert) contra un fake, este fake es un Mock.
Si en cambio la verificación se hace contra la UUT, entonces cualquier fake que haya será un Stub.

Resumiendo.

Todo fake será indefectiblemente un Stub o un Mock dependiendo de cómo se lo utilice. Es más, un fake puede ser Stub en un test, y Mock en otro test. La diferencia está en el uso que se le da a ese fake. Nada más y nada menos.

Según Roy Osherove (The Art Of Unit Testing, un libro que recomiendo totalmente y del cual saqué la idea para las imágenes) cada UT (Unit Test) no debería tener más de un Mock, y sí puede tener más de un Stub. Osherove es partidario de que si un UT tiene más de un Mock, el test pierde legibilidad y se hace más complicado de entender "inmediatamente" qué es lo que se quiere testear.

Espero que haya sido suficientemente claro, ya que es un tema de muchas confusiones por lo que he visto yo.

Hasta pronto, espero!

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!

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.

lunes, 20 de agosto de 2007

Service-Oriented Architecture (SOA)

Me enteré hace muy poco de esta -reativamente- nueva modalidad de diseño, o como bien lo indica su nombre, de esta Arquitectura Orientada a Servicios que, muy de más está decir, está orientada a los servicios. La leí de casualidad por ahi, y me puse a investigar a ver qué era. Es realmente muy interesante.

Pero como no me siento capacitado -aún- para escribir aludiendo a mis conocimientos y expresándome con mis propias palabras, he preferido dejar un par de links que son los que comencé leyendo yo; ya que me han dado una muy buena idea general del tema y, por qué no, también una idea bastante particular también.

Creo que lo único que restaría incluir en este post es algo de implmentación; no implementación propiamente dicha (utilizando alguna tecnología como .NET o Java) sino viendo algún ejemplo o mejor aún, algún caso real. Si alguien puede aportar, agradecería mucho.

Los links son:

Una intrdoucción : http://es.wikipedia.org/wiki/Arquitectura_orientada_a_servicios
Para profundizar (muy bueno): http://arquitecturaorientadaaservicios.blogspot.com/
Algo más general: http://www.mastermagazine.info/articulo/3391.php

Beneficios (no recuerdo de q web los saqué ;)

  • Reducir los costos y el tiempo de desarrollo—Los servicios SOA pueden reutilizarse fácilmente y pueden convertirse en nuevas aplicaciones compuestas
  • Reducir los costos de mantenimiento—Los servicios reutilizables reducen el grado de complejidad interna de los servicios de IT
  • Aumentar la calidad de los servicios—Una mayor reutilización de servicios crea servicios de mejor calidad en múltiples ciclos de prueba de diferentes consumidores de servicios
  • Reducir los costos de integración—Los servicios estandarizados pueden trabajar en conjunto, permitiendo que las aplicaciones dispares se conecten con rapidez y facilidad
  • Reducir el riesgo—Menos servicios reutilizables brindan mayor control sobre las políticas gubernamentales de IT y corporativas, y reducen el riesgo general relacionado con el cumplimiento

Bueno, espero que les sirva tanto como a mi.

Saludos!! Hasta pronto.