Mejorando el performance de SQS para millones de escrituras

Solución Procesar SQS Fargate Aurora

Hace ya casi un año que Amazon publicó que estaban desarrollando el soporte de Amazon SQS como “Event Source” para una función Lambda, y desde que la solución estuvo disponible buscaba una escusa para poder encontrar un mini proyecto para probarla.

Para el desarrollo interno de la empresa tengo un “Bot” que obtiene de manera diaria un CSV con alrededor de 1.000.000 de filas. Para todos los que estamos acostumbrados a trabajar con archivos grandes, 1M de datos no suena tan complejo, por lo que a pesar de tener mejores opciones decidí que era el momento de hacer una prueba de fuego parseando este archivo y enviando el resultado directamente a la cola fila por fila para luego ser procesado a través de una función lambda.

Este post es para comentar sobre la estructura final del proyecto, y como se fue modificando para poder funcionar de manera correcta.

Suposiciones

  • El archivo ya existe. Este POST no es sobre como crear un BOT para obtener un archivo.
  • Existe algo de conocimiento previo de lo que significa SQS, Lambda, un Trigger y Aurora.

Los problemas encontrados

A continuación una lista de problemas encontrados en el orden que fueron sucediendo.

  • El parseo inicial fue realizado a través de una función creada en NodeJS. Al parecer hasta el día de hoy el SDK de NodeJS de AWS tiene un bug en el cual el garbage collector no alcanza a borrar suficiente memoria cuando se usan sockets. Esto implica que el enviar cientos de llamados desde NodeJS hacia SQS implicaba que a pesar de tener el máximo de memoria soportado para la ejecusión, el resultado era falla de la ejecución del código. La recomendación de Amazon fue usar otro lenguaje para esta solución.
  • Luego los mensajes a SQS fueron enviados desde el parseador desarrollado en PHP sin problemas de manera secuencial, esperando que cada uno de los mensajes se enviara antes de seguir con el siguiente. Si bien esto funcionó sin problemas, el tiempo necesario para que la solución terminara fue de un poco más de 24 horas. ( Cero opción de que esto sea una solución definitiva ).

La Solución

Solución Procesar SQS Fargate Aurora
Solución Procesar SQS Fargate Aurora

Una de las características que más me gusta del desarrollo en la nube y los microservicios, es la versatilidad de como puedo manejar distintos lenguajes de programación para distintas soluciones y que todos puedan convivir sin problemas entre ellos. El BOT funciona en un contenedor de docker con PHP, y el consumidor de la cola en una función lambda utilizando NodeJS conectado a una base de datos Aurora Serverless.

Envío del mensaje a la cola

Para reducir el tiempo en que el parser del archivo CSV se utilizó una librería que trae promesas y asincronía a los desarrollos en PHP. La verdad hasta hace un par de días no sabía que esto era posible, pero la librería Guzzle Promises funciona de maravilla. Gracias a esto en vez de procesar los mensajes de la cola de manera individual los comencé a procesar por lotes de 500. Solo este cambio hizo que la solución en vez de demorarse un poco más de 24 horas, solo se demorara 86 minutos.

SQS from CSV + PHP

Si bien para la necesidad que tenía ya era un tiempo razonable, en especial por la hora a la que se ejecuta la solución, comencé a ver un par de alternativas que me permitieran reducir el tiempo de ingreso a la cola.

Encontré que en vez de mandar una fila del CSV por mensaje se aprovechaba de mejor manera la inserción en la cola si el mensaje incluía arreglos de 10 filas por mensaje. Solo este cambio significó una mejora desde los 86 minutos a 25 minutos.

PHP + SQS + CSV 25 Min

A esta altura por el momento ya quedo contento con la solución de inserción a la cola. La verdad es que se puede seguir mejorando la inserción, incluso incluyendo más filas por mensaje y comprimir el texto usando alguna librería. Es muy posible que en un futuro lo haga por curiosidad, pero por el momento me quedo contento con el tiempo de ejecución.

Procesando el mensaje.

Ya pasando por el proceso de inserción a la cola, el resto fue bastante sencillo. En la misma función lambda se ingreso como trigger directamente la cola en dónde se estaban ingresando los mensajes, con un máximo de mensajes por función de 10 ( Esto lo podemos hacer mucho más grande ! ).

Por lo que queda como lo siguiente :

  1. Cada mensaje contiene 10 filas con datos.
  2. Cada lambda maneja de manera “simultanea” 10 mensajes de la cola.
  3. Cada función lambda fue configurada con una concurrencia máxima de 100 para no tener que hacer mayores cambios en las conexiones a la BdD Aurora.  Para re-usar las conexiones a la base de datos se usa la librería Aurora Mysql Cluster de NodeJS.

Esto resulta en que en cada unidad de tiempo de procesamiento se pueden estar ingresando a la BdD alrededor de 10000 de lo que en su momento fueron filas con información desde un CSV, por lo tanto,  la velocidad de procesamiento e inserción a la base de datos es mucho mayor que la velocidad de inserción en la cola (Lo que podría traducirse en que quizás la mejor solución era ingresar a la base de datos de manera directa y no pasar por SQS).

Conclusión

Puede que la solución no sea la mejor para el problema dado por lo que deberé cambiarla en un futuro cercano. Sin embargo, estoy contento con el resultado del desempeño de Lambda con SQS como event source, que era lo que se quería probar desde un comienzo.

Espero poder probar el trigger desde SQS a Lambda en un proyecto en producción pronto.

 

¡Mantengamos el contacto!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

¡MANTENGÁMONOS EN CONTACTO!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

Introducción a Serverless, Amazon Lambda, Express, Node.js y DynamoDB

Aprende a realizar un REST API usando Serverless, Amazon Lambda, Express, Node.js y DynamoDB. Además usaremos un par de herramientas que hará mucho más sencilla su desarrollo.

Source: Deploy a REST API using Serverless, Express and Node.js

 

Hace un tiempo que me fasciné con la tecnología Serverless, hasta el punto que gran parte de mis desarrollos y sistemas ya están funcionando con ella. Fue a tal nivel que me vi obligado a aprender lenguajes de programación de los cuales nunca me había hecho el tiempo de aprender, en este caso NodeJS ya que nunca me gustó mucho Javascript. Para mi sorpresa ES6, en lo que está basado actualmente la nueva versión de javascript, se adecua un montón a la forma como estoy acostumbrado a programar por lo que el aprendizaje fue más sencillo.

Aprovecho de escribir este tutorial ya que por un lado un amigo – Marcelo A. –  me dijo que ya no estoy escribiendo tanto en mi blog, por lo cual he perdido tráfico, además de poder ayudar a otro amigo – Ernesto M.-  con una breve introducción de estas tecnologías.

En este ejemplo crearemos una API REST – solo usaremos el create, list, and get como ejemplos- de productos que se conectará a una tabla en DynamoDB. (Pueden ver el código del ejemplo en GitHub)

Si bien a continuación hay una lista de requerimientos que deberías tener para poder entender lo más posible este ejemplo, puedes perfectamente copiar el código desde el repositorio y probarlo directamente. Yo estaré programando directamente en Linux, pero lo que mostraré debería ser transversal.

 

Requerimientos :

  • Tener una cuenta en Amazon Web Services.
  • Tener instalado la herramienta de Serverless.
  • Tener instalado NodeJS y npm.
  • Tener un IDE ( Netbeans, Atom, Sublime, etc ) con el cual poder editar el código de manera adecuada y entendible.

Creando el Proyecto

ExpressJS es un framework de NodeJS que permite el fácil manejo de rutas y endpoints, además de un sin número de funcionalidades en las sesiones y middlewares. En este ejemplo solo lo usaremos de manera sencilla, pero bienvenidos son de poder averiguar todo lo posible, de buscar más ejercicios y ejemplos, y adaptar el conocimiento a sus necesidades.

express --view=pug productos
cd productos && npm install

Con lo anterior creamos un proyecto/carpeta llamado productos, ingresamos a la carpeta e instalamos las dependencias por defecto que trae express. El código generado tiene muchas más de las cosas que necesitamos para este sencillo ejemplo, pero los dejaremos ahí para que puedan jugar en caso de querer probar y ver que hacen. A continuación la estructura que deberíamos tener en este momento sin incluir la subcarpetas de los módulos.

├── app.js
├── bin
│   └── www
├── LICENSE
├── nbproject
│   ├── private
│   ├── project.properties
│   └── project.xml
├── node_modules
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
├── README.md
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.pug
    ├── index.pug
    └── layout.pug

Podemos notar que en la carpeta rutas tenemos una para usuarios y una de index, y podemos corroborar que estas son llamadas desde el archivo app.js.

Si en este momento todo sigue bien, podemos probar que el código inicial funcione de la siguiente manera :

DEBUG=productos:* npm start

Ahora podemos acceder a través de un explorador y veremos la pantalla inicial de express.

 

Exemplo de ExpressJS con NodeJS, Amazon Lambda, DynamoDB, y Serverless

 

Agregando Ruta de Productos

En este momento deberíamos ser capaces de entrar al endpoint de usuarios, pero lo que nosotros queremos es una ruta para los productos. Para lograrlo :

  1. Copiaremos el archivo de usuarios (users.js) en la misma carpeta con nombre de productos.js
  2. Agregaremos la variable productos en el archivo app.js de la siguiente manera : var productos = require(‘./routes/productos’);
  3. Le diremos a express que queremos usar la nueva ruta de productos como su mismo nombre : app.use(‘/productos’, productos);

En archivo de productos.js agregaremos dos métodos, un get y un create.

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function (req, res, next) {
    res.send('Index Productos');
});

router.get('/:id', function (req, res, next) {
    res.send('Producto ID : ' + req.params.id);
});

router.post('/', function (req, res, next) {
    res.send('CREANDO PRODUCTO');
});

module.exports = router;


Si iniciamos el servidor nuevamente deberíamos ser capaces de acceder a las rutas de index, de producto, y de creación con los verbos respectivos ( get and post ).

 

 

Agregando Serverless

Antes de poder iniciar las conexiones a la BdD con DynamoDB, debemos hacer unos cambios para utilizar la herramienta de serverless. Recuerda que debes de tener el comando serverless instalado.

  1. Agregamos la librería serverless-http
  2. Cargamos la librería de serverless-http

Para agregar la librería, abrimos la carpeta del proyecto y ejecutamos :

npm install --save serverless-http

Ahora en el archivo app.js incluimos al comienzo la librería de la siguiente manera :

const serverless = require('serverless-http');

 

Al final del archivo reemplazamos module.exports = app por module.exports.handler = serverless(app) ya que ahora es serverless quién se encargará de ejecutar el código.

Con estos cambios, solo nos falta decirle a serverless que es lo que debe de hacer, y como se debe de comportar. Esto lo hacemos con un archivo que creamos en el root del directorio llamado serverless.yml con el siguiente contenido.

# serverless.yml

service: api-rest-productos

provider:
 name: aws
 runtime: nodejs6.10
 stage: dev
 region: us-east-1

functions:
 app:
 handler: app.handler
 events:
 - http: ANY /
 - http: 'ANY {proxy+}'

Teniendo ya la configuración de serverless lista, ahora solo nos queda subirlo a Amazon Lambda. Serverless creará a través de CloudFormation todos los recursos que nuestra API pueda llegar a necesitar, para hacer el deploy simplemente ejecutamos el comando sls deploy.

$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (2.73 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.................................
Serverless: Stack update finished...
Service Information
service: api-rest-productos
stage: dev
region: us-east-1
stack: api-rest-productos-dev
api keys:
 None
endpoints:
 ANY - https://og6f6nu8b9.execute-api.us-east-1.amazonaws.com/dev
 ANY - https://og6f6nu8b9.execute-api.us-east-1.amazonaws.com/dev/{proxy+}
functions:
 app: api-rest-productos-dev-app
Serverless: Publish service to Serverless Platform...

Serverless creó la función lambda y el API Gateway correspondiente para poder acceder a ella. En general yo SOLO creo las funciones de esta manera, ya que me gusta poder modificar los API Endpoints desde la consola de Amazon.

En este caso si accedemos a los endpoints que nos da como resultado serverless, podemos acceder a través de la web a los ejemplos que vimos de manera local anteriormente.

Accediendo a DynamoDB

Ya tenemos nuestra aplicación andando sin problemas en los servidores de amazon ( Ojo, que este ejemplo no tiene un servidor asociado! ), ahora la idea sería hacer algo útil con ella.

  1. Generaremos el nombre de la tabla de manera dinámica.
  2. Crearemos una tabla de DynamoDB de manera automática dependiendo del Stage en que se encuentre nuestro desarrollo.
  3. Generaremos los permisos que nuestra aplicación necesita para poder acceder a estos recursos.

Editaremos entonces el archivo serverless.yml para hacer todo lo anterior.

# serverless.yml

service: api-rest-productos

custom:
  tableName: 'api-rest-productos-${self:provider.stage}'
  dynamodb:
    start:
      migrate: true

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: us-east-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource:
        - { "Fn::GetAtt": ["ProductsDynamoDBTable", "Arn" ] }
  environment:
    PRODUCTS_TABLE: ${self:custom.tableName}
    
functions:
  app:
    handler: app.handler
    events:
      - http: ANY /
      - http: 'ANY {proxy+}'

resources:
  Resources:
    ProductsDynamoDBTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          -
            AttributeName: productId
            AttributeType: S
        KeySchema:
          -
            AttributeName: productId
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: ${self:custom.tableName}

Con los cambios, al hacer el deploy se generará la tabla de DynamoDB correspondiente, en este caso terminada con -dev.

Ahora modificaremos nuestra ruta de productos para poder conectar con nuestra nueva tabla.

Primero instalaremos el SDK de Amazon y lo incluiremos en nuestro código.

$ npm install –save aws-sdk

Agregamos la librería de Amazon en nuestro archivo de productos.js después de requerir la librería de express.

const AWS = require('aws-sdk');

Después de las librerías agregamos el siguiente código para poder acceder a las tablas :

const PRODUCTS_TABLE = process.env.PRODUCTS_TABLE;
const dynamoDb = new AWS.DynamoDB.DocumentClient();

Finalmente modificamos nuestro archivo de productos para poder realizar las operaciones con la tabla.

 /* GET products listing. */
 router.get('/', function (req, res, next) {
 var params = {
 TableName: PRODUCTS_TABLE
 };

dynamoDb.scan(params, function (err, data) {
 if (err)
 console.log(err, err.stack); // an error occurred
 else
 console.log(data); // successful response
 res.json(data);
 });
 });

// Get Product endpoint
 router.get('/:productId', function (req, res) {
 const params = {
 TableName: PRODUCTS_TABLE,
 Key: {
 productId: req.params.productId,
 },
 }

dynamoDb.get(params, (error, result) => {
 if (error) {
 console.log(error);
 res.status(400).json({error: 'No se pudo obtener el producto'});
 }
 if (result.Item) {
 const {productId, name} = result.Item;
 res.json({productId, name});
 } else {
 res.status(404).json({error: "Producto no encontrado"});
 }
 });
 })

router.post('/', function (req, res, next) {
 console.log("Creando Producto");
 const {productId, name} = req.body;
 console.log("productId = " + productId);
 console.log("name = " + name);

if (typeof productId !== 'string') {
 res.status(400).json({error: '"productId" must be a string -> ' + productId});
 } else if (typeof name !== 'string') {
 res.status(400).json({error: '"name" must be a string' + name});
 }

const params = {
 TableName: PRODUCTS_TABLE,
 Item: {
 productId: productId,
 name: name,
 },
 };

dynamoDb.put(params, (error) => {
 if (error) {
 console.log(error);
 res.status(400).json({error: 'No se pudo crear producto'});
 }
 console.log("Producto " + productId + " creado exitosamente.");
 res.json({productId, name});
 });
 });

Ingresando Y obteniendo datos.

Para ingresar los datos podemos hacerlo a través de CURL, generar un formulario, o simplemente usar una herramienta como PostMan.

En este caso ingresemos dos datos para probar (Recuerda cambiar la URL por la tuya !):

curl -H "Content-Type: application/json" -X POST https://og6f6nu8b9.execute-api.us-east-1.amazonaws.com/dev/productos -d '{"productId": "mySku", "name": "Mi Producto"}'
curl -H "Content-Type: application/json" -X POST https://og6f6nu8b9.execute-api.us-east-1.amazonaws.com/dev/productos -d '{"productId": "mySku2", "name": "Mi Producto2"}'
curl -H "Content-Type: application/json" -X POST https://og6f6nu8b9.execute-api.us-east-1.amazonaws.com/dev/productos -d '{"productId": "mySku3", "name": "Mi Producto3"}'

Para ver la lista de los productos ingresados simplemente accedemos al endpoint de productos

Y para ver un producto particular agregamos al endpoint el id, por ejemplo :

Mejoras al Ejemplo.

Claramente este es un ejemplo sencillo de lo que se puede lograr, algunos ejemplos de mejoras con los que podrías jugar  :

  1. Agregar seguridad,  o autorización al API. Esto lo puedes hacer directamente en API Gateway o a través de código.
  2. Usar Clases y Herencias. En este ejemplo no aprovechamos el poder de las clases para hacerlo más sencillo.
  3. Instalar plugins para poder desarrollar de manera local. El desarrollo es mucho más expedito si lo puedes de hacer local.
  4. Y lo que se te ocurra!

 

Finalizando

La combinación de herramientas presentada en este artículo puede ayudarte a tener los conocimientos básicos de la tecnología de funciones como servicio. Queda mucho por leer y aprender, pero de verdad espero que sean tan apasionados como ella como yo. Mucho éxito !

BTW, recuerda ver el código del proyecto en el GitHub : https://github.com/ctala/introduccion-serverless

¡Mantengamos el contacto!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

¡MANTENGÁMONOS EN CONTACTO!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

Base de datos de las instituciones financieras de Chile basada en la información del SBIF

Instituciones Financieras Chile – Base de datos de las instituciones financieras de Chile basada en la información del SBIF en SQL, CSV, PHP y JSON

Origen: GitHub – ctala/InstitucionesFinancierasChile: Base de datos de las instituciones financieras de Chile basada en la información del SBIF

Casi todas las cosas que comparto son debido a que no me gusta hacer el mismo trabajo más de una vez. En este caso estoy haciendo un modulo financiero para nuestro sistema ERP para conciliación bancaria, por lo que encontré que era buena idea tener la información de las instituciones bancarias de Chile.

La página que aparece en el link posee la información de las instituciones reguladas  por el SBIF, su número de resolución o código según corresponda.

Además viene en los siguientes formatos :

  1. SQL, para que lo puedas ingresar directamente a una base de datos.
  2. PHP, por si quieres usarlo en un desarrollo propio. En general es posible que igual necesites la versión SQL.
  3. CSV, por si necesitas hacer la importación a otro sistema o Base de Datos.
  4. Json, simplemente pensé que sería buena idea incluirlo. La verdad yo no lo usaría debido que lo generaría de manera dinámica.

El formato del SQL posee la siguiente estructura :

CREATE TABLE IF NOT EXISTS `instituciones` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tipo` enum('Bancos','Cooperativas de Ahorro y Crédito','Operadores de Tarjetas de Débito','Asesorías Financieras','Sociedades de Apoyo al Giro Bancarias','Sociedades de Apoyo al Giro de Cooperativas','Sociedad de Leasing Inmobiliario','Sociedades de Cobranza','Sociedades de Factoring','Emisores y Operadores de Tarjetas de Crédito','Operadores de Tarjetas de Pago con Provisión de Fondos','Sociedades Evaluadoras','Sociedades de Garantía Recíproca y Fogape','Firmas Evaluadoras de Instituciones de Garantía Recíproca','Auditores Externos','Almacenes Generales de Depósito registrados en SBIF','Firmas Evaluadoras de Almacenes Generales de Depósito') NOT NULL DEFAULT 'Bancos',
  `codigoSBIF` varchar(5) DEFAULT NULL,
  `codigoRegistro` varchar(5) DEFAULT NULL,
  `nombre` varchar(150) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `codigoRegistro` (`codigoRegistro`),
  UNIQUE KEY `codigoSBIF` (`codigoSBIF`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=133 ;

En donde :

  • id, es simplemente el campo auto incremental para la información. No tiene relación a la información del SBIF.
  • tipo, corresponde al tipo de institución que es regulada por el SBIF. Existe la gran posibilidad que solo uses el tipo Banco.
  • codigoSBIF, corresponde al código otorgado a la institución por el SBIF.
  • codigoRegistro, corresponde al número de registro que otorga el SBIF.

Espero que les sirva !

https://github.com/ctala/InstitucionesFinancierasChile/

¡Mantengamos el contacto!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

¡MANTENGÁMONOS EN CONTACTO!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

¿ Desarrollar o no Desarrollar? He ahí el dilema

En que momento debemos desarrollar un software o simplemente usar una solución ya hecha anteriormente por la comunidad.

Recuerdo ya que hace muchos años mi primer blog fue programado 100% por mi, lo desarrollé en php siguiendo un tutorial que había en un libro que compré. Cuanto me arrepentí de haberlo hecho. Un par de años después de tenerlo funcionando un robot lo llenó de comentarios y la BdD colapsó, ni si quiera me di la oportunidad de recuperar el contenido que tenía en él. Estaba demasiado molesto…

Creo que poco antes de desarrollar este CMS ( la verdad ni si quiera se puede llamar así ) pensé en usar un sistema que ya existiera, pero en ese momento ganó el sentimiento de pertenencia y no la lógica por lo que terminé desarrollándolo. Si tuviera que elegir HOY si desarrollar un CMS para blogging personal ni si quiera pensaría en algo distinto a wordpress.

¿ Entonces cuando es necesario o no desarrollar un software ?

El lunes estaba dando una clase en la que hablábamos con los chicos de los beneficios de los frameworks y esto es muy similar. Es difícil encontrar un problema que tenga que solucionarse con un software que aún no haya sido creado. Existen soluciones para manejo de empresas, para ventas en línea, para manejo de contenido, para blogging, para redes sociales incluso para páginas de matchmaking. Estas soluciones pueden ser servicios o programas gratuitos, pagados, freemiums, etc.

Algunas ventajas del software que podemos encontrar en la red :

  1. Fácil y rápida implementación.
  2. No se requiere un equipo para poder hacerla funcionar.
  3. Costo bajo ( no necesariamente gratis, pero bajo )
  4. Independencia. No dependes de alguien más, de permisos ni de licencias.
  5. Fácilmente adaptable a tus necesidades. En muchos casos puede venir con un sistema de plugins para que desarrolles tus mejoras.
  6. Comunidades activas. Personas, foros, libros y otros blogs que pueden ayudarte a realizar lo que necesitas.

¿ Cuando desarrollar tu propio software ?

  1. Cuando la solución que queremos no existe.
  2. Cuando usar una solución existente es más costoso que desarrollar una propia.
  3. Cuando las soluciones que existen no se pueden adaptar a las necesidades que tenemos.
  4. Cuando el periodo de aprendizaje del código de la aplicación es mayor que el tiempo que requiere partir un software desde 0. Esto en general pasa cuando las aplicaciones no están desarrolladas de manera adecuada o pobremente documentadas.
  5. Cuando implementar las mejoras al sistema existente requiere más tiempo que crear todo desde 0.
  6. Cuando tenemos suficiente tiempo para realizarlo ! ( Vale la pena recalcar que muchos desarrollos no durarán una noche )

 

Recuerdo en un momento querer implementar un ERP OpenSource, en su momento eran pocos en español y mucho menos los que tenían el peso Chileno, sin contar que a las personas que puse a probarlo lo encontraron excesivamente complicado por lo que desechamos esa idea.

Al final la decisión siempre va a ir por nuestro lado, el sistema de inventario que usamos en la empresa fue desarrollado  debido a lo que necesitábamos en su momento  no me lo podía dar otro, desde las estadísticas necesarias hasta el entorno amigable.

Ojo, la idea de este post no es que NO desarrolles o que SIEMPRE uses software opensource, solo que simplemente veas los pros y contras de usar cada uno de ellos y elijas la mejor opción en cada caso. Tomando esto en consideración, ¿ Desarrollaras tu siguiente proyecto ?

¡Mantengamos el contacto!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

¡MANTENGÁMONOS EN CONTACTO!

Me encantaría que te mantuvieras al día con el contenido que estoy generando. Recuerda que no es solo el blog, son las redes sociales, libros, y distintos pódcast 😎.

Hago todo lo posible para no hacer Spam,

¿ Es necesario un framework ? Simplificando el desarrollo de software

Esta es una discusión que he tenido en bastantes ocasiones con pares y alumnos. La idea de este post es explicar un poco lo que se ha logrado con todas estas discusiones.

En muchos de los casos durante la universidad no hemos tenido la necesidad de desarrollar un software complejo, un software el cual deba de adaptarse a las necesidades del entorno, las modificaciones de ciertas librerías o simplemente al tiempo. La semana pasada le di el ejemplo a un alumno sobre codeignigter, en mi caso fue el primer framework que utilicé para desarrollo web utilizando php y actualmente ( no se si vaya a cambiar pronto) ya no es compatible con las nuevas versiones de php. Esto le puede pasar a cualquier desarrolo, la cantidad de actualizaciones, parches y modificaciones que salen anualmente son muchas más de las que podemos contar. Si esto le pasa a una aplicación que es mantenida por cientos de personas en la comunidad .. ¿Que nos espera a una aplicación desarrollada por nosotros ?

Read more

Share to...