style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Rituales de Arquitectura y patrones: De la importancia del camino medio Once and Only Once Balances Yagni – Parte 2

…escuchó a un maestro que estaba enseñándole a una niña a tocar un instrumento de cuerda. Dicho maestro le dijo que si la cuerda estaba muy floja no sonaría, pero si la cuerda del se encontraba muy tensa se rompería: la cuerda debía estar en su justa tensión para que pudiera dar música y armonía. En ese momento comprendió el camino medio

En la parte anterior de esta serie, les relate sobre YAGNI y OAOO y les dije que OAOO y YAGNI son como el Ying y el Yang. Se balancean. Sin OAOO, YAGNI lentamente nos estrangularía. Con OAOO, siempre tienes un sistema que puedes mejorar (frase de Ron Jeffries).

Yo también amarraba al gato, construía los sistemas como veía que los construían los demás, estaba en el nivel Shu de ShuHaRi a la hora de programar sistemas empresariales, ponía mis DAOs, ponía mi Servicio y ponía mi Controller.

Todos los sistemas “bien arquitectados” que conocía lo hacían, asi que lo hacia yo también. Si un sistema bien arquitectado se ve así al final, debe ser por que se veía así desde el principio… ¿no?

Pues no. Las cosas no se ven igual cuando las estas construyendo que cuando ya están terminadas. Si por ejemplo tratas de construir un arco sin soportes extra (que luego retiraras) podrías llegar la conclusión equivocada de si no puedes construirlo “sin usar soportes” lo estas haciendo mal… No es así.

Descubrí que estaba equivocado casi por casualidad, ya había leído que OAOO y YAGNI son como el Ying y el Yang. Se balancean, pero no lo había entendido mas allá del sonido de las palabras de la frase… Cuando lo entendí, escribí ese articulo sobre los epiciclos.

Lo aprendí cuando tuve contacto con programadores en PHP…

Di tu verdad serena y clara, escucha a los demás incluso al torpe y al ignorante, ellos también tienen su propia historia. Desiderata

Esos programadores en PHP no sabían que era YAGNI… no sabían nada del principio de construir lo mas simple que pueda funcionar (KISS)… jamás habían visitado c2 y con dificultad algunos de ellos leían en ingles…

Y sin embargo…

Sin embargo precisamente por eso seguían YAGNI y KISS a un extremo fascinante, no hacían absolutamente nada que no fuera esencial para terminar a tiempo el trabajo que les asignaban. Si, su código era un horror casi insoportable a la vista de alguien como lo era yo en ese momento…

Pero lo que yo necesitaba meses para construir ellos lo hacían en semanas, lo que yo necesitaba semanas ellos lo hacían en días, y lo que yo necesitaba días ellos lo hacían en horas…

Por otro lado, su apego tan intenso (e intuitivo?) a YAGNI y KISS también tenia su precio, la deuda técnica que acumulaban era brutal, y si bien podían poner funcionalidad en las manos del usuario en tiempo record, también tenían que volver a hacerlo todo casi desde cero si les pedían un cambio, sencillamente no había reutilización…

No había balance… Pero para mi fue un shock mire al otro extremo, y el otro extremo me miro de regreso… yo podía pasar horas refactorizando código para eliminar la redundancia al máximo, si el sistema estaba o no listo para la fecha de entrega era un factor secundario… Yo era todo OAOO… ellos eran todo YAGNI… Quiero pensar que aprendimos mucho ellos de mi… y yo de ellos..

Yagni significa que nosotros solo debemos implementar lo que necesitemos ahora, no lo que prevemos que vamos a necesitar. Esta estrategia (cuando funciona) elimina algunos costos por que no les permite llegar a existir (eran cosas que efectivamente nunca llegamos a necesitar), y retrasa los costos de aquellas cosas que eventualmente llegaremos a necesitar a un punto en una fecha futura. Sin embargo, un contra argumento comúnmente utilizado es que es mejor implementar cosas genéricas ahora que en el futuro…

Si implementamos todo incrementalmente por invocación a YAGNI, el sistema puede volverse ves mas difícil de modificar, especialmente si cada vez que implementamos algo nuevo, lo hacemos siempre del modo mas simple posible

Es bueno hacer lo  mas simple que pueda funcionar, sin embargo, debemos recordar re-aplicar esa regla para mantener a todo el sistema lo mas simple posible. Esto quiere decir que refactorizaremos el código para que nada viole OAOO.

Esta refactorización, al centralizar cualquier funcionalidad en una sola clase o método, deja al sistema bien posicionado para el siguiente cambio. Cualquier cosas que necesites hacer después, podrás estar casi seguro de que poder hacerla mejorando o reemplazado un punto aislado y especifico de tu código.

Veamos ahora un ejemplo:

  • Tengo que hacer una pantalla de registro, que lleva por ejemplo, un <select> en el que despliego los paises del mundo, para que cuando una persona se registre en mi sitio, pueda presentarle contenido relevante para el país (o países) de origen. Como voy a aplicar YAGNI no hare mas que esto:
  • Controller:
public List<Country> getCountriesList() {
         logger.info("Getting countries!");
         List<Country><country> countries = getSimpleJdbcTemplate().query(
                 "select id, name from country",
                 new CountryMapper());
         return countries;
     }
  • Siguiendo YAGNI, no tengo por que hacer mas. Si esta termina siendo la única pantalla en todo mi sistema que despliega países, no habré desperdiciado mi tiempo en complejidad sin beneficios.
  • Pero entonces, resulta que si, que en otra parte del sistema, en la pantalla de registrar pedidos, cuando tengo que poner a que dirección quiero que me llegue el producto que adquiero, y entre la información a indicar en la dirección, tengo que poner el país
  • Pues es entonces, y solo entonces, -cuando ya tengo 2 lugares, conceptualmente separados, y para los que no es conveniente aprovechar un mismo controller- que agrego un servicio:
  • Servicio Countries:
public List<Country> getListOfCountries() {
         logger.info("Getting countries!");
         List<Country><country> countries = getSimpleJdbcTemplate().query(
                 "select id, name from country",
                 new CountryMapper());
         return countries;
     }
  • Controller: Registro Usuario
 public List<Country> getProductsToList() {
         return getCountryServices().getListOfCountries();
     }
  • Controller: Registro Dirección Pedido
 public List<Country> getProductsToList() {
         return getCountryServices().getListOfCountries();
     }

Es por esto que cuando un sistema esta terminado, da la impresión de que “todo se construye con capas desde el principio”. Pero ese es un error, producto de ver al sistema como algo estático, como algo que “nació” con la forma que tenia en un momento en el tiempo, y no como algo orgánico, cuya estructura va cambiando conforme se adapta a las necesidades del usuario que lo adquirió.

La arquitectura del proyecto, no es algo que se predefina antes de entender al sistema. La arquitectura es una estructura emergente, que deriva de las historias de usuario que son paulatinamente construidas conforme se la va dando forma al sistema. Si el sistema no incluye entre sus historias a la necesidad de operar sobre múltiples bases de datos distintas (Oracle, Sql Server, etc) entonces la capa de DAOs nunca tendría por que llegar a existir. Si no aporta valor, sale sobrando.

En el caso de ejemplo anterior podemos ir aun mas lejos. Modernamente, la mayor parte de la aplicaciones son RIAs construidas sobre HTML5 y JavaScript, en donde la logica en Java (o en C# o en Groovy o en Scala…) meramente actua como una capa de intercambio de datos y seguridad entre la capa de persistencia (tipicamente una base de datos) y las capa de logica de negocios y presentacion (que suelen ubicarse totalmente en JavaScript)

Por que entonces nos empeñamos en usar POJOs que no aportan valor? Por que nuestro codigo no se ve asi:

public List<Map<String,?>> getCountriesList() {
         logger.info("Getting countries!");
         List<Map<String,?>> countries = getSimpleJdbcTemplate().queryForList("select id, name from country");
         return countries;
     }

Para que complicarnos la existencia con un (o varios) POJO (o DTO) si nuestro sistema es tan simple (a nivel de Java) que los métodos expuestos por nuestros controladores solo hacen CRUD y es el código en JavaScrip el que realmente se encarga de darles vida a los datos? Que caso tiene trabajar con POJOs, si nuestro modelo de dominio es anémico?

Enfoques como OData, convierten, de un plumazo en obsoleta toda esta parafernalia de hacer controllers para construir lentamente y por pasos una API de consulta que podría derivarse automáticamente del modelo de datos. Pero OData no es mas que un mecanismo de consultas, que viene a eliminar la necesidad de seguir amarrando el gato… digo, de hacer una capa de controllers a la medida cada vez

¿Por que Oracle, SqlServer, MySQL, Postgresql, etc no ofrecen directamente un API Odata (o algo parecido) en vez de obligarnos a reinventarla cada vez?

Tal parece que nuestras tradiciones humanas nos hacen vivir en ciclos dentro de ciclos:

  1. Inventamos Cobol, para exponer mediante procedimientos nuestros datos
  2. Inventamos las bases de datos relacionales (cuya implementación nunca completamos) para permitir el accceso a datos mediante expresiones de consulta (SQL)
  3. Inventamos entonces los procedimientos almacenados, para encapsular proceduralmente nuestras expresiones de consulta
  4. Inventamos despues mapeadores objeto relacionales, para conseguir compatibilidad entre multiples bases datos y poder consultarlas con un lenguaje de expresiones de consulta unificado…
  5. Inventamos despues  SOAP, para encapusular mediante procedimientos nuestros objetos
  6. Descubrimos que paralelamente, alguien habia inventado REST, que permite consultar recursos mediante expresiones de consulta representadas por una URL…

Y asi… una y otra vez, procedimientos, expresiones, procedimientos, expresiones, enfoque procedural, enfoque declarativo…. y cada vez que reinventamos la rueda, sentimos que estamos rompiendo esquemas… cuando en realidad, solo le dimos una vuelta mas a la rueda de la moda…

¿Encontraremos algun dia el equilibro? (O quizá ya lo hemos encontrado... y mas bien falta que nos demos cuenta...)

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de echan

Si .. parece que el software

Si .. parece que el software empresarial es un oceano, pecera, charco o lo que sea, aunque no necesariamente por ingenuidad viven y mueren en el, hay quienes hacen software de esta manera porque les va "bien" y se sienten comodos aplicando los mismos patrones una y otra vez y no queran salirse de el por las mismas razones ... es un mercado y cubren una necesidad.

Pero definitivamente yo no seria tan pesimista con el "reinventamos la rueda ..." y "sentimos que estamos rompiendo esquemas" etc... no es fenomeno universal .. hay cosas my interesantes al otro lado de la banqueta, por poner un ejemplo basta echar una miradita al Strange Loop (https://thestrangeloop.com/archive/2012) ..y en lo personal me gustaria ver un cambio de actitud de la comunidad programera hacia alla (entendiendo que tambien hay excepciones) .. pero creo que ésto requiere un cambio cultural.

Imagen de ezamudio

strangeloop

Me pareció medio "buzzword loop"... big data, Scala, scalability, analytics...

Imagen de luxspes

One Javascript

Cada vez mas parte del codigo de las aplicaciones se tiene que correr en el cliente, y con el desaucio de Silverlight y Flash, parece que el unico camino en JavaScript

One JavaScript to rule them all, One JavaScript to find them,
One JavaScript to bring them all and in the darkness bind them

Siento que un punto interesante a favor de Ceylon va a ser su compilado de JavaScript... sospecho que eventualmente todos van a tener que usar JavaScript como una especie de JVM-IL/CLR

Otra vuelta al ciclo...

Con un lenguaje como Ceylon para hacer desarrollo web, las cosas mejoraran (JavaScript es una tortura para cualquier cosa realmente compleja), pero por otro lado es triste... sospecho que aquellos lenguajes que no se adapten a ser compilados a JavaScript seran victimas de una especie de evento de extinción masiva... (o al menos fuerte reducción de sus nichos ecológicos....)

Imagen de echan

porque esperar a

Imagen de echan

mi post anterior fue

mi post anterior fue pregunta.. :) es decir.. ¿porque esperar a Ceylon? .. si ahora puedes usar cualquiera de la lista

Imagen de luxspes

Interesante lista (por

Interesante lista (por cierto, puedes editar tus posts)

En cuanto a en mi caso por que esperar... pues en general me gustan las ideas que implemente Ceylon y como es un lenguage naciente, es mas probable que los frameworks que aparescan a su alrededor se diseñen desde el principio para aprovechar que compila en JavaScript, a diferencia de otros casos en los que la compilacion hacia javascript es una cuestion posterior a la liberacion original del lenguaje

Aunque igual y hay otros que podria ser interesante investigar en esa lista...

Imagen de echan

oops crei que eran

oops crei que eran inmutables, mucho fp ultimamente :) .. supongo que tenemos nuestras preferencias ... a mi me llama la atencion http://ympbyc.github.io/LittleSmallscript/ pero creo es solo una curiosidad y va ser muy complicado que en algun momento pueda despegar.

En cuanto a Ceylon no conozco mas que la intro que tienen en la pagina veamos como levanta porque tiene buena competencia (si es que existe) con Kotlin.. ambos parecen un subconjunto de Scala con algunas variaciones sintacticas .. claro que en este momento mi opinion es poco fundada porque no he visto mas que el intro de ambos. De cualquier forma les falta algunas millas por recorrer para que se pueda ver su verdaddero potencial.

Imagen de Nopalin

La arquitectura del proyecto,

La arquitectura del proyecto, no es algo que se predefina antes de entender al sistema. La arquitectura es una estructura emergente, que deriva de las historias de usuario que son paulatinamente construidas conforme se la va dando forma al sistema.

No creo que sea algo emergente, al igual que en la ingenieria, la arquitectura se planea desde el inicio con mucha información. Se define el sistema al inicio, se entiende el sistema al inicio, se establecen alcancen del cliente y tambien tuyos como proveedor, en base a eso se crea la arquitectura y por ende la estructura y según las historias de usuario, creas la facilidad y comodad de uso. Dejar la arquitectura a como van surgiendo las cosas me da la impresión de que no se hace un análisis del mismo.

¿Por que Oracle, SqlServer, MySQL, Postgresql, etc no ofrecen directamente un API Odata (o algo parecido) en vez de obligarnos a reinventarla cada vez?

¿Que pasaria cuando un fabricante agregue funcionalidad extra al api OData, como hacen actualmente con SQL? Eso siento yo que te amarra y pierdes independencia.

Un ejemplo mio: en la mayoria de los sistemas que hago hay una cláusula de reuso de código para poder acomodarlo en algun otro cliente que tenga casi las mismas necesidades, con modificaciones mínimas. Pero resulta que el segundo cliente quiere postgres en lugar de oracle, se volveria tedioso andar modificando algo que se supone ya esta implementado y funcionando. Creo que en cierta forma las apis creadas en distintos niveles es para aliviar la carga en ese sentido, ser vendor-independant, no es por que se pretenda reinventar la rueda.

Ahora, ¿que pasaria si dentro de 5 o 10 años google saca su propio scripting para chrome con su implementación funcionando un 50% más rapido que javascript? ¿estaría reinventando la rueda?

Saludos

Imagen de ezamudio

V8

Chrome sacó V8 para no tener que usar un lenguaje distinto y ejecutar javascript mucho más rápido. Y trae SPDY para poder conectarse mucho más rápido que con HTTP (a los servidores que usen SPDY por supuesto, que por ahora pues creo que nomás son los de google, pero abrieron el estándar y es cosa que otros lo empiecen a implementar).

Esa cláusula de reuso de código está interesante. Le dan algún descuento al cliente por aceptarla? Porque si yo te pido que me hagas un sistema, es un trabajo por encargo y al final el código es MIO, no de ustedes, por lo que no deberían poder usarlo de nuevo con otros clientes.

En cuanto a lo de la arquitectura emergente, creo que a eso se refiere exactamente luxspes, nopalin: están hablando de lo mismo. Yo no lo entendí como que luxspes diga que la arquitectura se hace sobre la marcha, sino que durante el análisis de lo que piden le vas dando forma al sistema, en contraste con traer ya tu arquitectura rígida que siempre usas y que llegas a la junta con el cliente ya decidido a que vas a hacerlo en capas cuando ni sabes qué te van a pedir aún.

Imagen de Nopalin

Alomejor tienes razón y estoy

Alomejor tienes razón y estoy entendiendo todo mal a lo que se refiere luxpess, pero hablando por experiencia propia, al cliente, que son empresas que su negocio no es el software, generalmente no le interesa que reuses el codigo siempre y cuando las aplicaciones no se vean como las de ellos. Entonces basandome en eso, las aplicaciones siempre de los siempre las hago cliente-servidor, y obviamente el server siguiendo el modelo bsi-dao-database, para poder migrar el GUI a otro framework de escritorio o web o lo que sea. Por eso cuando luxpess hablaba de que no se debe hacer asi hasta que el cliente no te lo pida, no concordaba por que al menos para mi era distinto a lo que alomejor estan acostumbrados a hacer. No digo que siempre acomodo la aplicacion en otro cliente, pero al menos la parte fuerte, que es la lógica, esta ahi lista para funcionar.

Con lo de la cláusula, pues no hacemos descuentos, el contrato dice que el codigo es de ellos y de nosotros, con la condicion de que si lo reusamos tenemos que cambiar en almenos el 50% de la parte gráfica. El backend como no se ve, puede quedarse igual.

Sobres

Imagen de ezamudio

reuso

La pregunta respecto de la cláusula de reuso era más bien para luxspes, quien originalmente la mencionó. Ahora ya sé que ustedes también la aplican. Como dije, interesante.

Si yo tuviera una empresa que no es de sistemas y tuviera que hacer por ejemplo un sistema de contabilidad o nómina o para manejar el restaurante o bar o lo que fuera, y mando hacer un software para resolver ese aspecto de la empresa que no es mi core business, pediría que el código fuera todo mío (es decir yo lo registro en indautor), para poder aplicarle GPL después y publicarlo y si otros lo quieren usar pues que lo aprovechen. Supongo que eso a ustedes no les gustaría porque entonces no pueden reusar conmigo código de otros clientes porque lo voy a terminar publicando. O podemos llegar a un acuerdo pero la cosa es que si no es mi core business quiero al final publicarlo y hacerlo software libre.

Por otra parte, si mando hacer software que se va a volver parte de mi core business, entonces jamás aceptaría que reusen ese código. Tendría que haber cláusulas incluso de confidencialidad, porque no quiero que después vayan con mi competencia a venderle el mismo software que me hicieron a mi.

Y por último, digo que es interesante porque hasta donde yo sé, legalmente los trabajos por encargo (como cuando el cliente les pide a ustedes hacer un sistema) son propiedad intelectual de quien lo paga. Es decir el cliente puede ir con indautor y registrar el código como suyo. Supongo por eso tienen que especificar todo ese rollo de que el código es de ambos...

Imagen de paranoid_android

Amarrando y desamarrando el gato

Justamente me encontré un artículo, lástima que no guarde la página donde desamarran parte del gato.

Resulta ser que meterle interfaces a cada capa e instanciar la clase le cuesta al procesador en un servidor 7% del rendimiento, y en una aplicación móvil le cuesta 20% con lo que puede hacer la aplicación potencialmente lenta.

Sin embargo por acá se está usando una herramienta llamada sonar de calidad de código que justamente indica como mala práctica de java instanciar una clase sin usar una interfaz.

Buenos Post

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">