Mostrando las entradas con la etiqueta patrones de diseño. Mostrar todas las entradas
Mostrando las entradas con la etiqueta patrones de diseño. Mostrar todas las entradas

miércoles, 19 de agosto de 2015

12. Patrones de Diseño (III) - Facade

La programación salvaje es como una enredadera si no tenemos cuidado en muy poco tiempo se mete en todo nuestro proceso complicando cada día más su mantenimiento.

También se puede decir que es como una hidra, que crece y se convierte en un ser de muchas cabezas.

Como programadores no siempre es posible conocer la funcionalidad de todos los módulos, lo mejor siempre es tener módulos especializados y rehusarlos cuando esto sea necesario, pero existe un gran problema en esto, las muchas cabezas que puede tener un módulo y que debemos evitar, es aquí en donde nos ayuda el patrón de diseño del que hablaremos el día de hoy, el patrón Facade, o Fachada, es un patrón estructural que nos ayuda a dar visibilidad del código.

El patrón indica que se debe tener una sola clase de entrada sin importar la complejidad del código que se encuentre en la aplicación.

El patrón ordena el código de tal forma que cuando se emplea el modulo, pese a lo complejo de su interior, solo tendrá un punto por el que toda la funcionalidad sea accedida.

Este es un patrón muy útil, y realmente muy fácil de implementar que nos va a quitar muchos dolores de cabeza en el código.

Bueno siguiendo la lógica de que un programador busca menos teoría y más código, pongamos un ejemplo del uso de este patrón.


Nuevamente tomando el ejemplo de un carro, yo tengo una clase radio, la clase radio se muestra de la siguiente forma:

Como podemos ver el tablero de control en el que el usuario del carro controla el radio es nuestra clase fachada, y esta clase dispara procesos hacia adentro del radio, estos procesos cambian la estación, suben el volumen, controlan la reproducción de MP3, sin saber qué es lo que ocurre más atrás.
Ahora veamos qué pasa si esta clase creada en el punto anterior interactúa con un usuario, que en este caso es un programa que consume el servicio que se encuentra implementado bajo este patrón de diseño.


Resultado, solo un espacio de nombres, el código está estructurado y es más fácil de implementar.

Un paso más para evitar la programación salvaje, saludos



miércoles, 22 de julio de 2015

9. Patrones (II) - Decorator

El código salvaje crece de una manera incontrolada, esto hace que en muchos casos se pierda el control del mismo, y en casos extremos se tengan que hacer completos proyectos que si bien en su fase de diseño fueron muy buenos, con una arquitectura estable, conforme se van agregando nuevas funcionalidades y más desarrolladores modifican el código, estos se convierten en verdaderos monstros de Frankenstein.

Muchas piezas de código operando para crear nuevas funcionalidades, y en ciertas ocasiones por no conocer el sistema, estas hacen que el sistema sea inestable.

El tiempo de desarrollo se incrementa, la calidad baja, y de la misma forma baja la satisfacción del cliente.

Pero, ¿Hay alguna forma de modificar funcionalidad que sea no tan dolorosa?

Vamos a platicar de un patrón de diseño que es para esto, su nombre es Decorator, y se emplea para añadir de manera dinámica funcionalidad a un objeto, de esta forma podemos incrementar las características del objeto, sin que esto nos represente un cambio doloroso.

Eso si hay que cambiar un poco nuestra mentalidad para usarlo, y pensar más en términos del patrón
Su principal característica, es que nos permite agregar de manera incremental responsabilidades, el patrón lo aplicamos como si fueran capas y las capas nos brindan nuevas características, imaginemos que es una perla que se está creando y cada capa es una aplicación del patrón.

Este es un patrón estructural y lo podemos usar durante el diseño, mantenimiento o extensión de funcionalidad.

Podemos representar el patrón de la siguiente forma


Sin embargo creo que esto lo podemos ilustrar mejor con un poco de código.

Imaginemos esto somos una fábrica de carros, y vamos y vamos a ponerle el radio a uno de nuestros carros, así que crearemos una interfaz en la cual se encontrara el método encender radio

namespace decorator01
{
    public interface ICarro
    {
        void EncenderRadio();
    }
}

El radio lo vamos a implementar en nuestro modelo básico

public class CarroEstandar : ICarro
    {
        public void EncenderRadio()
        {
            Console.WriteLine("Radio FM - Mono");
        }
    }

Como se puede ver el modelo básico cuenta con un Radio FM con sonido mono aural, bueno viene un nuevo modelo, en el cual se requieren mejoras a este radio, así que tomamos el modelo básico y lo mejoramos

  public class CarroMejorado : ICarro
    {
        ICarro CarroBase;

        public CarroMejorado (ICarro I)
        {
            CarroBase = I;
        }
   
        public void EncenderRadio()
        {
            CarroBase.EncenderRadio();
            Console.WriteLine("Radio Satelital");
        }
}

Ahora el radio cuenta con una nueva función, sin perder la primera, si tuviéramos otro modelo, podemos crearlo ahora partiendo de cualquiera de los modelos anteriores.

public class CarroBlindado : ICarro
    {
        ICarro CarroBase;

        public Boolean DobleBlindado { get; set; }

        public CarroBlindado(ICarro I)
        {
            CarroBase = I;
        }

        public void EncenderRadio()
        {
            CarroBase.EncenderRadio();
            if (DobleBlindado == true)
            {
                Console.WriteLine("Audio Alta calidad");
            }
            else
            {
                Console.WriteLine("Audio Especial");
            }
        }
    }

Construyamos ahora nuestros carros:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Construyendo carro estandar");
            CarroEstandar cr1 = new CarroEstandar();
            cr1.EncenderRadio();

            Console.WriteLine("Construyendo carro Mejorado");
            CarroMejorado cr2 = new CarroMejorado(cr1);
            cr2.EncenderRadio();

            Console.WriteLine("Construyendo carro blindado");
            CarroBlindado cr3 = new CarroBlindado(cr2);
            cr3.DobleBlindado = true;
            cr3.EncenderRadio();

            Console.ReadLine();
        }

Al iniciar la producción vemos lo siguiente



Como podemos observar se puede agregar funcionalidad de manera dinámica de una forma mucho más libre que empleando la herencia


Di no al código salvaje

lunes, 20 de julio de 2015

7. Programar en paralelo (I)

A partir de .Net 4.0 llego a su madures la programación en paralelo por .net, la posibilidad de efectuar múltiples operaciones en forma simultánea con la finalidad de reducir tiempos, y emplear mejor los recursos de sistema.

El nuevo modelo nos permite emplear de forma simultanea los núcleos del procesador, anteriormente se requería un manejo a un nivel más bajo para lograr que las tareas se distribuyeran en forma paralela, hoy esto no es necesario.

Pero antes de considerar el uso de las funciones de .Net para programar en paralelo tenemos que hacer unas consideraciones.

¿Cuáles serán los recursos en los que se empleara la programación en paralelo?

Al emplear este tipo de programación se debe considerar que si el recurso no soporta cierta cantidad de peticiones, el rendimiento en vez de incrementarse puede verse afectado, esto es por ejemplo mandar un gran número de peticiones a una base de datos, o escritura a un disco.

¿Realmente será perceptible el cambio?

Si la cantidad de peticiones es tal que al emplear este tipo de programación se vea un cambio perceptible en el rendimiento, hay que usarla, pero si el cambio no es perceptible, no es conveniente incrementar la complejidad del código.

Bueno y como se emplea, el modelo más sencillo de programación en paralelo es la invocación de más de una función en el mismo instante de tiempo.

Para ello emplearemos Task Parallel Library, esta se encuentra dentro del espacio de nombres System.Threading.Tasks.
 
Y su invocación es tan sencilla como:
 
Parallel.Invoke(() => Tarea1(), () => Tarea2());
 
Lo mas interesante de esto es que podemos enviar la cantidad de tareas en paralelo que deseemos
 
Parallel.Invoke(() => Tarea1(), () => Tarea2(), ()=> … TareaN());
 
Sin embrago siempre estamos limitados por los recursos del equipo, un gran número de proceso paralelos puede tener como consecuencia que el sistema baje su rendimiento.

Otro punto muy importante, por lo regular los equipos productivos tienen una potencia mucho mayor que los equipos de desarrollo, por tal motivo cuando se construye un proceso en paralelo se debe tener esto en mente.


Hasta la próxima semana.

jueves, 9 de julio de 2015

6. Pensamiento Mágico, ayuda divina

Una actividad interesante, que debería desaparecer de nuestra mente, es emplear el pensamiento mágico de que solo se va a arreglar algo, si se arregla solo es que hay algo mal, algo esta tan inestable que el solo volverlo a hacer hace que funcione.

¿A qué se debe ese pensamiento mágico?, podríamos adjudicarlo a muchas cosas desde la inseguridad de que los pasos que se efectuaron son los correctos o la falta de conocimiento sobre cómo opera una aplicación.

Qué caso tiene hacer 100 veces la misma operación esperando que por pura casualidad en la 97 funcione, la computadora sigue una serie de pasos, específicos que no debería cambiar por ejecutar nuevamente una operación.

Pero, ¿Qué pasa si esto ocurre?, entonces no es que el programa se arreglara por sí solo, lo más probable es que exista un problema en la inicialización de algún objeto.

Ahora me dirán, es que la primera vez fallo, pero luego continuo, en este caso puede ser algún archivo temporal que sea necesario para que opere su programa.

Es común que digan reinicia y funciona, y esto en muchos de los casos es cierto, pero si esto ocurre realmente de lo que hablamos es de una inestabilidad del sistema operativo.

Es importante entender que nada se soluciona por arte de magia y menos en un mundo en el que todo se reduce a bits, a unos y ceros, en donde sí a la computadora se le dice enciende, esta enciende, 

Cuando un sistema esta inestable se debe hacer un análisis completo, de que estamos haciendo, cual es el flujo que sigue, esto nos ayudara a tener una mayor calidad en nuestros programas.

Hay que ser curiosos y no confiar en la solución mágica.


Hasta pronto

viernes, 3 de julio de 2015

5. Herramientas - Mi propio NuGet



Divide y vencerás es una frase muy común en muchos de los entornos en los que nos desarrollamos, y en el software es algo que tiene una gran verdad, el hecho de que yo trabaje con componentes altamente especializados me ayuda a erradicar rápidamente errores y nos permite que el código sea altamente reutilizable.

Uno de los grandes problemas que ha existido a través del tiempo es como organizo mis versiones de código, para que de una manera sencilla los cambios en estos módulos especializados puedan llegar a los proyectos de mayor tamaño.

Bueno ante esto podemos hacer uso de la herramienta de administración de Paquetes llamada NuGet, NuGet es un administrador de paquetes de código abierto que trabaja sobre Visual Studio a partir de la versión 2010.

¿Qué tipos de archivos podemos poner en nuestra solución?

Prácticamente cualquier tipo de archivo, incluso en diferentes versiones de Framework dándole la posibilidad de emplear la dll en múltiples proyectos.

NuGet me permite que yo publique en la red mis dll pero también las puedo publicar en una red local, dentro de una carpeta compartida y que las consuman dentro de mi organización.
Para ello tengo que hacer lo siguiente:

1.       Descargar el NuGet Package Explorer desde la siguiente ruta:  https://npe.codeplex.com/, esta herramienta me permite generar los packetes de NuGet

2.       Al abrirlo me muestra esta pantalla:


3.       Se selecciona Create a new package

4.       Esto nos muestra la siguiente pantalla



5.       Se debe seleccionar el botón edición para editar las características del paquete


6.       Agrega la o las dll al proyecto



7.       Selecciona guardar como… y guarda este módulo en la carpeta que en que se creara tu NuGet personal.




8.       Ahora es necesario que visual studio conozca la ruta, inicia Visual Studio

Ve a Herramientas -> Administración de paquetes NuGet -> Configuración del administrador de paquetes.




9.       Y una vez dentro se selecciona la ruta en donde se encuentra nuestro paquete.



10.   Cuando buscamos el paquete este ya lo podemos usar en todos nuestros proyectos, es muy importante que se maneje el número de versión cada vez que se tengan nuevos dll ya que de esta manera NuGet tendrá la forma de asignar la nueva versión




Nos leemos pronto

miércoles, 1 de julio de 2015

4. Patrones de diseño

Un código bien diseñado, puede ser reusado con facilidad en otros proyectos,  adaptado para necesidades futuras y este operara de una manera correcta.

Pero que pasa en la programación salvaje, muchos códigos se diseñan para cumplir con un cliente específico, se tiene miedo a reutilizarlos porque se teme a que en algún momento se modifiquen y se pierda la funcionalidad original, el componente pertenece a otro más grande y reutilizarlo llega a ser complicado por el nivel de acoplamiento entre clases.

La gran cantidad de programadores que modifican un código y la poca o nula capacitación hace que cada uno de ellos implemente en sus proyectos funciones que anteriormente ya se implementaron.

Y bueno si supero esos obstáculos ¿Cómo logro hacer un código flexible que pueda emplear en múltiples proyectos y que realmente cumpla con la característica de ser reutilizable?

Un método para lograr esto es la implementación de patrones, por desgracia en .net existe muy poca gente que hace uso de ellos, a veces por tiempo, otras por desconocimiento, o porque en su organización no existen reglas para ello.

Un patrón de diseño es una solución que ya ha sido probada y que cuenta con una efectividad probada.

Así pues desde 1990 se han creado un conjunto de patrones de diseño, que permiten hacer software de mejor calidad.

En ese 1990 se recogieron 23 patrones de diseño estos fueron agrupados en la literatura por Erich Gamma, Richard Helm, Ralph Johnson,y John Vlissides, hoy son el conjunto básico de patrones que deberíamos conocer todos los desarrolladores, estos 23 patrones se dividieron en 3 grupos creacionales, estructurales y de comportamiento.

Existen 7 patrones estructurales que son:


  • ·         Decorator
  • ·         Proxy
  • ·         Bridge
  • ·         Composite
  • ·         Flyweight
  • ·         Adapter
  • ·         Facade

Existen 5 patrones creacionales


  • ·         Prototype
  • ·         Factory Method
  • ·         Singleton
  • ·         Abstract Factory
  • ·         Builder

Y existen 11 patrones de comportamiento


  • ·         Strategy
  • ·         State
  • ·         Template Method
  • ·         Chain of Responsibility
  • ·         Command
  • ·         Iterator
  • ·         Mediator
  • ·         Observer
  • ·         Visitor
  • ·         Interpreter
  • ·         Memento

La calidad que se obtiene en un código de programación mejora cuando el desarrollador ocupa dichos patrones, ya que con esto se logra una verdadera estandarización en la codificación, y con ello acabaremos con esa programación salvaje.


jueves, 25 de junio de 2015

3. Desarrollando

De qué trata todo esto, todo esto surge de una inquietud, la inquietud de ver que muchos profesionales del cómputo se encasillan en solo hacer ABC, la inquietud de ver que todo mundo sabe programar pero solo conoce las estructuras básicas, la inquietud de ver que el tiempo pasa hay grandes logros pero en mi impresión nos estamos quedando cortos.

Tenemos el acceso a la información, pero la empleamos con fuerza bruta, ya no la depuramos, podemos construir grandes cosas pero en vez de ahorrar recursos construimos torres con más piezas de las necesarias.

Estamos cayendo en un exceso de confianza, en una facilidad por hacer entregas rápidas, a fin de cuentas si no es lo suficiente mente rápido, con más potencia al equipo con eso basta.

Hay exceso de metodologías tratando de solucionar las crisis del desarrollo, de cómputo, viendo el desarrollo desde muchos puntos de vista.

Hay otras que tratan de hacer que gente que no es de computo entienda los procesos, y buscando que las TI trabajen como una fábrica del siglo pasado.

Calidad, rapidez, costos, son palabras que están en nuestro vocabulario todos los días, sin embargo en muchos casos parece que no las entendemos.

Este blog tocara varios puntos, comentarios sobre algún tema normalmente enfocados al desarrollo, claro estos desde el punto de vista de un desarrollador más.

Técnicas y metodologías para mejorar nuestro código pienso empezar con patrones y anti patrones de diseño.

Y bueno algo que valla más allá de las bases de datos y que mejor que un poco de gráficos y animación, así que trabajaremos en un buen tutorial de DirectX, ya que realmente hay pocos que enseñen a fondo lo que es, así que hay mucho trabajo por delante.


Si una computadora más pequeña que tu celular llego a la luna, ¿Tu hasta donde podrás llegar?

miércoles, 24 de junio de 2015

2. Optimizar el performance (análisis)


Las 4 tareas de una optimización de performance son:

- Medición
- Diagnósticos de cuellos de botella
- Selección de optimizaciones
- Implementación de las optimizaciones

Nuestra principal herramienta son los contadores de rendimiento, algunas herramientas de desarrollo también nos permiten tomar una imagen de aquello que está ocurriendo en disco memoria y procesador.

Es necesario conocer el tiempo de cada una de las partes del proceso, para poder efectuar un análisis de cada uno de los componentes del mismo.

Se debe tomar en cuenta la velocidad de los componentes, una escritura en disco es más lenta que una escritura en memoria, y la memoria siempre será más lenta que el procesador, peor aún, si vive el almacenamiento en red, si está en la nube, si consume servicios, es necesario identificar en donde se encuentran cada uno de los cuellos de botella.

¿Cómo vamos a optimizar?, podemos iniciar procesos paralelos y aprovechar la capacidad del procesador, si algo se guarda en disco podemos mantenerlo más tiempo en memoria, si tenemos mucha información podemos hacer objetos más ligeros, divide y vencerás, has tareas específicas para que puedan ser medidas e incluso separadas y agrupadas.

Este punto es muy importante, tener cargada solo la información que vamos a emplear, muchas veces por hacer objetos genéricos se carga información que no es necesaria, al final todo esto se traduce en lecturas y escrituras que cuando se habla de grandes cantidades de información pueden representar el colapso del sistema.

Por más que tengamos mucha memoria disponible, hay que pensar que esta no es infinita, liberarla cuando sea necesario, analizar los objetos para determinar cómo se libera la memoria en cada parte del proceso.

¿Los componentes externos responden adecuadamente?, ¿cómo está la velocidad de acceso a discos?, ¿tengo errores?, ¿Se me encolan peticiones?

Hay que ver el sistema como un todo, y este todo abarca el sistema como tal, el sistema operativo, los dispositivos de hardware (tarjetas de red, discos, memoria), bases de datos, los desarrolladores tendemos a cegarnos y pensar que todo está en el código, es muy importante conocer toda la pintura y no solo los personajes que se encuentran en ella.

¿Cómo es nuestro diseño?, hay 2 puntos importantes que muchas veces nos generar grandes problemas de rendimiento y cuellos de botella, y tienen que ver directamente con el diseño.

-Arquitectura
-Frameworks

Porque la arquitectura, la premisa fundamental al construir una arquitectura es que esta deberá ser lo más sencilla posible, ¿Por qué?, porque una arquitectura sencilla es entendible, es fácil de implementar, y es rápida.

Al tener menos capas, la información pasa por menos lugares, cada capa se traduce en tiempo, objetos demasiado genéricos pueden ser muy grandes, o efectuar una gran cantidad de operaciones para llegar al resultado, como consecuencia se pierde el desempeño, crea una arquitectura acorde a tus necesidades, cada sistema es diferente, tiene diferentes requisitos por lo que su arquitectura debe ser diferente.

Frameworks, los frameworks son muy útiles, ya que implementan las mejores prácticas o nos facilitan el trabajo, pero muchos de ellos tienen el gran error que mencione en el punto anterior, objetos demasiado genéricos, objetos que son muy grandes, accesos a memoria para obtener tipos u objetos hacen una gran cantidad de operaciones para estar listos para los diferentes eventos para los que son programados, todo esto reduce el desempeño de tu sistema.

Mientras más cerca estemos del lenguaje maquina más rápido operara el sistema, no digo con esto que empleemos ensamblador en el desarrollo, lo que digo es que hay que buscar emplear funciones nativas del lenguaje, que sean ligeras y que controlemos completamente.

Si cumplimos todo lo anterior, saldremos de esa computación salvaje, en la que dependemos de la velocidad de los procesadores y no de un orden en la programación.

No todo lo que brilla es oro y no todo lo nuevo es lo mejor.

Pero recuerda como diría algún arquitecto de sistemas, todo depende… depende de la situación en la que te encuentres y de que tan alto requieras la optimización de tu código.

Bueno esto solo es un comentario

Carlos


Referencia
                Enhancing Performance Optimization of Multicore/Multichip Nodes with Data Structure Metrics

                Ashay Rane, James Browne

lunes, 22 de junio de 2015

1. Reflexión sobre el papel del Arquitecto

Vivimos una época de cambios, en las que tenemos mucha información al alcance de nuestras manos, mucha más información que en cualquier otra época de la humanidad, el día de hoy es muy fácil creerse experto en uno o varios temas, y sistemas es uno de esos temas en los que existen muchas personas que se consideran expertas en el área.

La computación es fácil, es lógica dicen muchos.

Si hay tantos expertos ¿Por qué hay tantos problemas en los sistemas? ¿Por qué muchos no son exitosos? Y ¿Por qué otros que si tienen cierto éxito se caen en cuanto empiezan a crecer? ¿Por qué antes con equipos menores a lo que es un celular de hoy en día se podía hacer el mismo trabajo de cómputo?, ¿Quién es el responsable?, ¿Qué herramientas tengo?

El mundo de computo cambia muy rápido hace solo unos cuantos años una computadora no tenía más de 4 Megas en RAM, 100 Megas de disco y un procesador de 33 MHz, hoy incluso un celular tiene más poder que eso.

La mayoría de los sistemas no hacen más almacenar información y consultarla, pese a los cambios tecnológicos siguen siendo ABC, si esto es así, ¿no deberíamos ser expertos en ellos?, y ser la mayoría de ellos exitosos.

La respuesta es Sí, entonces ¿Qué es lo que está pasando?

Bueno todo esto puede recaer en un individuo que día a día ha perdido su función, porque cada vez hay más personas que toman ese roll sin saber realmente que es lo que debería de hacer, esto hablando de un Arquitecto de sistemas.

¿Por qué el?, porque él es el principal responsable en la construcción de una aplicación. Él es el que debe conocer el ADN de la aplicación, sin embargo, el arquitecto de sistemas no necesariamente es el mejor desarrollador, o el mejor DBA, tampoco es el genio que vive encerrado en su cubículo y lo ven solo las noches de luna llena.

El arquitecto es aquel, que sabe que es lo que se quiere, que conoce las piezas, que puede defenderlas, que puede armarlas y lo más importante que puede transmitir que es lo que quiere, alguien que puede separar el todo y convertirlo en algo tan abstracto como un programa, sin necesidad de que él lo desarrolle.

Él debe conocer a todos aquellos involucrados en el sistema tener la capacidad para traducir entre diversos idiomas, traducir una imagen que vive en la mente de aquel que desea el sistema en imágenes que puedan servir para que uno o más desarrolladores puedan darle vida a este nuevo ser.


Platiquemos un poco, y veamos una gran analogía, la analogía de la palabra arquitecto, un arquitecto se define según la real academia de la lengua española como la persona que ejerce la arquitectura, y la arquitectura se define como el Arte de proyectar y construir edificios.

Ahí caemos en 2 cosas primero que nada es un Arte, sistemas por si solo es un Arte, es un trabajo que si bien tiene reglas, tiene mejores prácticas, muy pocos realmente las conocen, y aún menos las aplican, de construir edificios, realmente es lo que hacemos nosotros construimos edificios sobre los que circula la información.

Entonces que es un arquitecto, es aquel que es capaz de construir una torre de babel sin que esta colapse en el intento, y lo más importante debe manejar la complejidad nunca incrementarla, el mejor diseño de arquitectura no es aquel que tiene más capas, y que solo es capaz de entender el que lo creo y un grupo de personas cercanas, no el mejor diseño es el que es el más sencillo, aquel que puede entender cualquiera de los desarrolladores que conforman el equipo, y que cumpla con todo aquello que sea necesario en el proyecto.

Sencillez ante todo, el arquitecto no debe demostrar que él sabe lo que otros no saben, por el contrario debe balancear el proyecto para que aquellos que no saben puedan participar en él. No es un dios, es un maestro, no tiene la verdad absoluta, pero debe tener la visión de un todo.


Debe conocer, lo que fue, lo que es y lo que será. Ver el mapa desde arriba, pero poder entrar y revisar un detalle, debe tener ambas visiones la visión macro y la visión micro.

Entonces ¿Quién puede ser un arquitecto?

Aquel que comprenda el proyecto, que conozca, los requerimientos, que sepa quiénes son sus programadores, que pueda balancear sus complejidad, que pueda proponer, que sepa decidir que conviene al proyecto y que no necesariamente escoja lo más reciente en el mercado.

Un maestro, un aprendiz, un director, un escucha y un orador.

Es el papel más complicado en el desarrollo, porque realmente de él depende el éxito o el fracaso.

Imaginen que un arquitecto, que construye un rascacielos, realmente no entendiera el concepto, o ideara algo tan complejo que nadie pudiera construirlo, ¿Qué pasaría? Los proyectos se irían al fracaso, bueno lo mismo ocurre con un arquitecto de software, él debe comprender su verdadera responsabilidad, que no es eso diseñar, sino conocer el todo comprenderlo, transformarlo y obtener el resultado que espera que solicito el proyecto.

No es una tarea fácil, y hacerlo bien mucho menos.

Bueno solo es un comentario...Carlos