Categoría: Básicos de ingeniería

Aprende los fundamentos de la ingeniería de sistemas.

  • Comandos mas utilizados de Git

    Comandos mas utilizados de Git

    Estos son solo algunos ejemplos y hay muchos más comandos y opciones disponibles en Git. Puedes obtener más información sobre cualquier comando específico utilizando git help [comando] o consultando la documentación oficial de Git.

    git init

    git init: Inicia un nuevo repositorio Git.

    git init
    git clone

    git clone [URL]: Clona un repositorio existente, ten en cuenta si usas SSH.

    git clone https://github.com/jhontona/DownDownConnectPro.git
    git add

    git add [archivo]: Agrega cambios al área de preparación (staging). Puedes usar . para indicar que agregue todos los archivos desde la raíz.

    git add .
    git commit

    git commit -m “Mensaje”: Guarda los cambios en el repositorio con un mensaje descriptivo.

    git commit -m "Describo los cambios a subir"
    git status

    git status: Muestra el estado de los archivos en el repositorio. Cuales están pendientes o listos para agregar.

    git status
    git pull

    git pull: Obtiene cambios del repositorio remoto. Opcionalmente puedes indicar el origen y la rama.

    git pull origin master
    git push

    git push: Sube los cambios locales al repositorio remoto. Opcionalmente puedes indicar el origen y la rama.

    git push origin master
    git branch

    git branch: Lista las ramas locales.

    git branch
    git checkout

    git checkout [rama]: Cambia a otra rama. Especificar -b hace que se cree una nueva rama.

    git checkout -b desarrollo
    git merge

    git merge [rama]: Fusiona los cambios de otra rama en la rama actual.

    git merge desarrollo
    git log

    git log: Muestra el historial de commits.

    git log
    git remote

    git remote: Muestra las URL de los repositorios remotos configurados.

    git remote -v
    git fetch

    git fetch: Obtiene cambios del repositorio remoto sin fusionarlos.

    git fetch --all

    Es esencial comprender que cualquier acción incorrecta o malinterpretación de las siguientes opciones puede resultar en la pérdida de horas de trabajo y esfuerzo invertidos en la codificación. Para evitar cualquier inconveniente, se recomienda encarecidamente revisar y comprender los comandos y parámetros asociados antes de proceder.

    La integridad y seguridad de tu código son fundamentales, y el conocimiento preciso de las funciones y herramientas que utilizas es clave para preservar tu trabajo. ¡Recuerda, un pequeño error puede tener grandes consecuencias!

    git reset

    git reset: Deshace los cambios en el área de preparación.

    git reset --soft
    git revert

    git revert [commit]: Crea un nuevo commit que deshace los cambios de un commit anterior.

    git revert HEAD~2

    Recuerda que esta es una guía básica, así que faltan por aprende aun mas comandos y parámetros. Sin embargo es un excelente punto de partida y se listaron los comando mas usados en el día a día de un programador. Si quieres ahondar en uno de los comandos o te surge alguna duda comenta y comparte lo que sabes. Hasta la próxima!


    ¡Conviértete en un experto tecnológico! 🚀 Suscríbete a nuestro newsletter y recibe las últimas noticias, análisis y tendencias directamente en tu bandeja de entrada. No te pierdas las actualizaciones que harán que tu experiencia tecnológica sea aún más emocionante. ¡Únete a nuestra comunidad hoy! 📧✨

  • DESMITIFICANDO LOS ALGORITMOS: Calculando complejidad

    DESMITIFICANDO LOS ALGORITMOS: Calculando complejidad

    Analizar el rendimiento de un algoritmo es una parte crucial de su diseño. Para ser útil, cualquier algoritmo debe cumplir las siguientes características:

    1. Correcto: Un algoritmo debe generar resultados precisos y exactos. La verificación exhaustiva es esencial.

    2. Comprensible: No debe ser excesivamente complicado de implementar. La facilidad de comprensión facilita su aplicación práctica.

    3. Eficiente: La eficiencia es esencial para un buen algoritmo. Aunque pueda producir resultados correctos, su utilidad se ve comprometida si requiere un tiempo excesivo o una cantidad desmesurada de recursos computacionales.

    Complejidad Espacial

    El análisis de la complejidad espacial se enfoca en calcular la cantidad de memoria que un algoritmo requiere para procesar datos de entrada. Con el aumento de la informática distribuida y volúmenes crecientes de datos, este análisis se vuelve esencial. La eficiente asignación de recursos en las modernas estructuras de datos en memoria se convierte en un factor clave, especialmente en algoritmos iterativos, donde la naturaleza iterativa impacta en cómo se llenan las estructuras de datos y en los requisitos de memoria en distintas fases de ejecución.

    • En las iteraciones convergentes, la complejidad espacial disminuye a medida que el algoritmo avanza, siendo desafiante en las primeras iteraciones.
    • En las divergentes, la complejidad aumenta, y se deben establecer límites para evitar la inestabilidad.
    • En las iteraciones planas, la complejidad espacial permanece constante.

    Para calcular la complejidad espacial, se enfoca en las iteraciones más complejas, generalmente las iniciales, estimando el uso total de memoria, incluyendo estructuras de datos temporales, ejecución y valores de entrada. Este enfoque proporciona una buena estimación de la complejidad espacial del algoritmo.

    Las siguientes son pautas para minimizar la complejidad espacial:

    Computador explotando por procesar algoritmo
    1. Preferir el diseño de algoritmos como iterativos siempre que sea posible.
    2. En el diseño de algoritmos iterativos, al haber opción, optar por un mayor número de iteraciones en lugar de un menor número. Se espera que un mayor número de iteraciones más refinadas tenga una menor complejidad espacial.
    3. Los algoritmos deben traer a la memoria solo la información necesaria para el procesamiento actual, eliminando lo que no se necesita.
    4. El análisis de la complejidad espacial es esencial para el diseño eficiente de algoritmos. La falta de este análisis podría resultar en problemas de memoria insuficiente para las estructuras de datos temporales, afectando significativamente el rendimiento y eficiencia del algoritmo.

    complejidad temporal

    El análisis de la complejidad temporal estima cuánto tiempo tomará para que un algoritmo complete su tarea asignada basándose en su estructura. A diferencia de la complejidad espacial, la complejidad temporal no depende del hardware en el que se ejecutará el algoritmo, sino únicamente de su estructura. El objetivo principal del análisis de la complejidad temporal es responder a dos preguntas fundamentales:

    1. ¿Este algoritmo se adaptará a una escala mayor? Debería aprovechar la infraestructura elástica moderna de entornos de computación en la nube, utilizando más CPUs, núcleos de procesamiento, GPUs y memoria disponibles.
    2. ¿Cómo manejará este algoritmo conjuntos de datos más grandes? Es crucial evaluar cómo afecta el tamaño de los datos al rendimiento del algoritmo, asegurándose de que no solo sea preciso, sino que también pueda escalar eficientemente, especialmente en el contexto actual de “big data”.

    Para alcanzar este objetivo, dado un problema y múltiples algoritmos, debemos determinar cuál es el más eficiente en términos de tiempo. Se pueden emplear dos enfoques básicos para calcular la complejidad temporal:

    1. Enfoque de perfilado post-implementación: Se implementan diferentes algoritmos candidatos y se compara su rendimiento.
    2. Enfoque teórico pre-implementación: Se aproxima matemáticamente el rendimiento de cada algoritmo antes de ejecutarlo.

    La ventaja del enfoque teórico es que depende solo de la estructura del algoritmo, prescindiendo del hardware real, la pila de software seleccionada en tiempo de ejecución o el lenguaje de programación utilizado para implementar el algoritmo.

    Calculando la complejidad

    El rendimiento de un algoritmo típico depende del tipo de datos que recibe como entrada. Para abordar esta dependencia, se analizan distintos casos en el análisis de rendimiento:

    1. Mejor caso: Considera el escenario donde los datos de entrada están organizados de manera que el algoritmo ofrece su mejor rendimiento. Proporciona un límite superior de rendimiento.

    2. Peor caso: Estima el tiempo máximo que tomará realizar la tarea bajo condiciones específicas. Útil para garantizar un rendimiento mínimo en cualquier situación. Proporciona un límite inferior de rendimiento.

    3. Caso promedio: Divide las posibles entradas en grupos, realiza análisis de rendimiento en una entrada representativa de cada grupo y calcula el promedio del rendimiento de cada grupo. El análisis del caso promedio no siempre es preciso, ya que implica considerar todas las combinaciones posibles de entradas, lo cual puede ser complicado.

    Notación Big O

    La notación Big O indica el número de operaciones que procesará un algoritmo en lugar de mostrar el tiempo exacto de ejecución. Su objetivo es mostrar la tasa de crecimiento de un algoritmo y facilitar la comparación con otros algoritmos en términos de eficiencia.

    Reglas para la notación Big-O:

    1. La complejidad de un bucle en un algoritmo, que realiza una secuencia de pasos n veces, es O(n).

    2. Para bucles anidados, si un algoritmo realiza una función con un bucle de n^1 pasos y, para cada bucle, realiza otro de n^2 pasos, la complejidad total del algoritmo es O(n^1 × n^2).

    3. Si un algoritmo realiza una función f(n) que toma n^1 pasos y luego realiza otra función g(n) que toma n^2 pasos, la complejidad total del algoritmo es O(f(n)+g(n)).
    4. Si un algoritmo tiene una complejidad de O(g(n) + h(n)) y g(n) es mayor que h(n) para valores grandes de n, la complejidad se simplifica a O(g(n)).
      • Ejemplo: O(1+n) = O(n), y O(n2 + n3) = O(n2).
    5. Al calcular la complejidad de un algoritmo, se ignoran los múltiplos constantes.

    Complejidad en tiempo constante

    (O(1))Ejemplo: Añadir, obtener elemento, establecer elemento

    Si un algoritmo tarda la misma cantidad de tiempo en ejecutarse, independientemente del tamaño de los datos de entrada, se dice que se ejecuta en tiempo constante. Tomemos el ejemplo de acceder al enésimo elemento de un array. Independientemente del tamaño del array, llevará un tiempo constante obtener los resultados.

    Complejidad en tiempo lineal

    O(n)Ejemplo: Copiar, insertar, eliminar, iteración

    Un algoritmo se considera tener una complejidad de tiempo lineal, si el tiempo de ejecución es directamente proporcional al tamaño de la entrada. Un ejemplo simple sería sumar los elementos en una estructura de datos unidimensional.

    Complejidad en tiempo cuadrático

    O(n^2)Ejemplo: Bucles anidados

    Un algoritmo se considera que se ejecuta en tiempo cuadrático si el tiempo de ejecución del algoritmo es proporcional al cuadrado del tamaño de la entrada; por ejemplo, una función simple que suma los elementos de un array bidimensional.

    Complejidad en tiempo logarítmico

    O(logn)Ejemplo: Encontrar un elemento en una matriz ordenada

    Un algoritmo se considera que se ejecuta en tiempo logarítmico si el tiempo de ejecución es proporcional al logaritmo del tamaño de la entrada. Con cada iteración, el tamaño de la entrada disminuye por factores múltiplos constantes. Un ejemplo de un algoritmo logarítmico es la búsqueda binaria. Este algoritmo se utiliza para encontrar un elemento específico en una estructura de datos unidimensional, como en una lista en Python, siempre y cuando los elementos estén ordenados en orden descendente.

    Estas son las bases matemáticas para calcular la complejidad de un algoritmo, si tienes dudas o quieres que ahondemos en alguno de estos temas, deja tu comentario. Hasta la próxima.


    ¡Conviértete en un experto tecnológico! 🚀 Suscríbete a nuestro newsletter y recibe las últimas noticias, análisis y tendencias directamente en tu bandeja de entrada. No te pierdas las actualizaciones que harán que tu experiencia tecnológica sea aún más emocionante. ¡Únete a nuestra comunidad hoy! 📧✨

  • Desmitificando los Algoritmos: Diseño de un algoritmo

    Desmitificando los Algoritmos: Diseño de un algoritmo

    Bienvenidos de regreso en esta travesía hacia el corazón de los algoritmos, donde las soluciones matemáticas encuentran su aplicación en problemas del mundo real. Esta es la continuación de un post anterior, donde nos introducíamos a los conceptos base de algoritmos. En este articulo veremos las técnicas y recursos para diseñar un algoritmo.

    Estrategias de Diseño de Algoritmos

    Cuando nos embarcamos en el diseño de algoritmos, nos enfrentamos a tres consideraciones fundamentales para perfeccionar nuestras creaciones:

    •  ¿Este algoritmo produce el resultado esperado?
    • ¿Es esta la manera más óptima de obtener estos resultados?
    • ¿Cómo se desempeñará el algoritmo con conjuntos de datos más grandes?

    Comprender la complejidad del problema es crucial antes de diseñar la solución. Clasificamos los algoritmos según las siguientes categorías, orientadas a las características del problema:

    Algoritmos Intensivos en Datos

    Diseñados para manejar grandes cantidades de datos con requisitos de procesamiento relativamente simples. Ejemplos incluyen algoritmos de compresión aplicados a archivos enormes. En estos casos, el tamaño de los datos supera la memoria del motor de procesamiento, y se debe desarrollar un diseño de procesamiento iterativo para manejar eficientemente los datos.

    base de datos

    Algoritmos Intensivos en cálculos

    Requieren un procesamiento considerable pero no implican grandes cantidades de datos. Un ejemplo simple sería un algoritmo para encontrar un número primo muy grande. La clave para maximizar el rendimiento de estos algoritmos radica en dividirlos en fases que puedan paralelizarse.

    Algoritmos Intensivos tanto en Datos como en Cálculos

    Abordan grandes cantidades de datos y tienen considerables requisitos de procesamiento. Ejemplos notables son los algoritmos para realizar análisis de sentimientos en transmisiones de video en vivo. Estos algoritmos, los más exigentes en recursos, necesitan un diseño cuidadoso y una asignación inteligente de recursos disponibles

    La dimensión de los datos

    Al abordar las dimensiones de volumen, velocidad y variedad (los 3Vs), nos adentramos en la esencia misma de cómo los algoritmos enfrentan desafíos del mundo real.

    • Volumen: El Tamaño Esperado de los Datos El volumen representa el tamaño esperado de los datos que el algoritmo procesará. Desde conjuntos modestos hasta datos masivos, entender el volumen es esencial para diseñar algoritmos que se adapten a la escala requerida.
    • Velocidad: La Tasa de Generación de Nuevos Datos La velocidad mide la tasa esperada de generación de nuevos datos al utilizar el algoritmo. Desde procesos por lotes hasta procesos en tiempo real, la velocidad de los datos varía. Imagina un proceso en tiempo real, como la recopilación de feeds de video en vivo; aquí, la velocidad alcanza su máxima complejidad.
    • Variedad: La Diversidad de Tipos de Datos La variedad cuantifica cuántos tipos diferentes de datos se espera que maneje el algoritmo. Desde datos estructurados hasta no estructurados, la variedad desafía al diseño del algoritmo a abordar diferentes formatos y contextos de datos.

    Por ejemplo, en la dimensión de velocidad, tenemos el procesamiento por lotes como el más simple, seguido del procesamiento periódico y luego el procesamiento casi en tiempo real. Finalmente, tenemos el procesamiento en tiempo real, que es el más complejo de manejar en el contexto de la velocidad de los datos.

    Al caracterizar la dimensión informática, se analizan las necesidades de procesamiento del problema en cuestión. Estas necesidades determinan el diseño más eficiente para un algoritmo. Por ejemplo, los algoritmos complejos suelen requerir una gran potencia de procesamiento, lo que puede hacer necesario contar con una arquitectura paralela de varios nodos. En el caso de algoritmos modernos de aprendizaje profundo, que implican un procesamiento numérico considerable, puede ser necesario utilizar la potencia de unidades de procesamiento gráfico (GPUs) o unidades de procesamiento tensorial (TUPs).

    En futuros post veremos como calcular esta complejidad para poder abordar la creación de algoritmos.  No olvides dejar tus comentarios e inquietudes y nos vemos en el próximo post.


    ¡Conviértete en un experto tecnológico! 🚀 Suscríbete a nuestro newsletter y recibe las últimas noticias, análisis y tendencias directamente en tu bandeja de entrada. No te pierdas las actualizaciones que harán que tu experiencia tecnológica sea aún más emocionante. ¡Únete a nuestra comunidad hoy! 📧✨

  • Desmitificando los Algoritmos: Desde su Concepción hasta la Validación

    Desmitificando los Algoritmos: Desde su Concepción hasta la Validación

    Los algoritmos son los cimientos sobre los cuales se construyen soluciones innovadoras. En este artículo, desglosaremos los elementos esenciales que rodean a los algoritmos, desde su definición hasta las técnicas de diseño y análisis de rendimiento.

    Pensaba en un tema para escribir en el blog y caí en cuenta de que hablamos de patrones, técnicas de rendimiento, optimización, fundamentos matemáticos, estructuras de datos, etc. Pero no hemos tocado una de los conceptos mas importantes dentro de la programación. Así que este post va dedicado a conocer mas sobre que es un algoritmo, seguiremos por un viaje que nos lleve a través de los algoritmos mas usados y su razón de ser.

    ¿Qué es un Algoritmo?

    Un algoritmo es un conjunto finito de instrucciones que, dadas ciertas condiciones iniciales, pueden llevarse a cabo en una secuencia prescrita para lograr un objetivo específico y que tiene un conjunto reconocible de condiciones finales. Diseñar un algoritmo es un esfuerzo para crear una receta matemática de la manera más eficiente que pueda utilizarse efectivamente para resolver un problema del mundo real. Esta receta puede servir como base para desarrollar una solución matemática más reutilizable y genérica que se pueda aplicar a un conjunto más amplio de problemas similares.

    Una secuencia de pasos lógicos que produce un resultado…

    Las Fases de un Algoritmo

    Se debe tener en cuenta que el algoritmo depende de los requerimientos del problema, que se dividen en funcionales y no funcionales. Los requisitos funcionales especifican las características esperadas de la solución, mientras que los no funcionales abordan el rendimiento, escalabilidad, usabilidad, precisión y seguridad de los datos.

    A continuación vamos a mencionar sus fases de manera rápida para posteriormente ahondar en cada una de sus implicaciones.

    Diseño

    Aquí, se conciben y documentan la arquitectura, la lógica y los detalles de implementación del algoritmo, considerando tanto la precisión como el rendimiento. La fase de diseño es un proceso iterativo donde se comparan diferentes algoritmos candidatos, evaluando sus compromisos entre simplicidad, rapidez y precisión.

    Chica programadora diseñando algoritmo

    Codificación

    El algoritmo diseñado se traduce a un programa de computadora que implementa la lógica y arquitectura propuestas en la fase de diseño.

    La elección del lenguaje de programación y el entorno de desarrollo/producción depende de los requisitos del problema.

    Chica programadora creando algoritmo

    Implementación

    Una vez completada la fase de diseño y codificación, el algoritmo está listo para ser implementado. La implementación implica crear el entorno de producción donde el código se ejecutará, adaptándolo a las necesidades de requerimientos y procesamiento del algoritmo. Donde finalmente, procesando datos de entrada, generará salidas según los requisitos establecidos.

    Chica programadora desplegando algoritmo

    Este articulo es cortito, pero apenas es la introducción a temas mas complejos que empezaremos a trabajar en próximos post. Como las consideraciones del diseño y la complejidad de los mismo. Ve dejando tus inquietudes y comentarios. Te espero en el próximo post.


    ¡Conviértete en un experto tecnológico! 🚀 Suscríbete a nuestro newsletter y recibe las últimas noticias, análisis y tendencias directamente en tu bandeja de entrada. No te pierdas las actualizaciones que harán que tu experiencia tecnológica sea aún más emocionante. ¡Únete a nuestra comunidad hoy! 📧✨

  • En las entrañas de la Arquitectura de Microservicios en Desarrollo de Software

    En las entrañas de la Arquitectura de Microservicios en Desarrollo de Software

    En el anterior post nos introdujimos a los microservicios, en este post exploraremos a fondo los beneficios que los microservicios ofrecen, nos sumergiremos en los desafíos que plantea esta arquitectura innovadora y desvelaremos las claves para alcanzar el éxito en su implementación. Desde la agilidad en el desarrollo hasta la gestión efectiva de la complejidad, abordaremos temas cruciales como la optimización de recursos, la resiliencia en situaciones de fallo y las mejores prácticas para una implementación exitosa de microservicios.

    Beneficios de los microservicios

    1. Mayor velocidad en desarrollo: La arquitectura de microservicios acelera todos los procesos de desarrollo al permitir una compilación y tiempo de construcción más rápidos. Esto es clave para la agilidad en el desarrollo.

    2. Despliegues rápidos y tamaño reducido: Al desplegar cada parte del sistema de manera independiente, el tamaño de implementación se reduce significativamente. Esto se traduce en despliegues individuales que toman una fracción del tiempo comparado con aplicaciones monolíticas.

    3. Programación de despliegues personalizada: La arquitectura de microservicios resuelve el problema de seguir un calendario de despliegue estándar. Cada servicio puede ser desplegado de manera independiente, siguiendo su propio cronograma.

    4. Monitoreo fino y personalizado: Servicios críticos pueden ser monitoreados de manera más detallada que otros, permitiendo un control más preciso y chequeos adicionales. Permite identificar servicios claves y cuellos de botella.

    5. Pruebas automatizadas independientes: Cada microservicio puede realizar pruebas automatizadas configurables como parte del proceso de construcción y despliegue. Esto reduce el tiempo necesario para realizar pruebas en toda la aplicación.

    6. Soporte para varios lenguajes de programación: Ya no es necesario ejecutar una aplicación como un solo ejecutable. Esto permite implementar diferentes partes del sistema utilizando tecnologías diversas, adaptándose a cada problema de manera óptima. Esto lo logramos a partir de definir interfaces de comunicación.

    7. Escalabilidad más sencilla y económica: Los microservicios son más fáciles y a menudo más baratos de escalar horizontalmente. Cada parte del sistema puede escalarse de manera independiente, evitando los requisitos pesados de recursos de las aplicaciones monolíticas. Aunque cuidado, por que al seguir escalando nuestra aplicación se puede volver incluso mas costosa de mantener ya que necesitamos orquestadores y pagar por mantenibilidad de cada servicio, pero ampliaremos esto en la siguiente sección de contras.

    8. Flexibilidad en el hardware: La división de la aplicación a menudo significa reducir los requisitos de hardware para la mayoría de las partes del sistema, brindando más opciones al elegir hardware o proveedores de servicios en la nube.

    9. Aislamiento efectivo de fallos: El desacoplamiento de servicios proporciona un mecanismo de seguridad eficiente para prevenir problemas mayores en caso de fallas parciales del sistema.

    10. Facilidad de entendimiento: Los servicios son más fáciles de entender y mantener debido a tamaños de código más pequeños. Además, suelen estar asociados a procesos completos lo que puede hacer que contrastemos la funcionalidad con la experiencia de un especialista en el proceso.

    11. Optimización de costos: Ejecutar la mayoría de los componentes de la aplicación en instancias de menor costo en comparación con instancias monolíticas de alto recurso puede resultar en ahorros significativos ya que podemos potenciar los servicios críticos a demanda.

    12. Desarrollo distribuido: La eliminación del acoplamiento entre componentes contribuye a lograr más independencia en el desarrollo de código, beneficiando a equipos distribuidos.

    13. Facilidad de refactorización: Es mucho más fácil realizar refactorizaciones en microservicios debido al menor alcance de cambios y procesos de lanzamiento y prueba independientes.

    14. Libertad tecnológica: Cambiar a nuevas tecnologías es más fácil con la arquitectura de microservicios, ya que cada servicio es más pequeño y estructuralmente independiente.

    15. Toma de decisiones independiente: Los desarrolladores son libres de elegir lenguajes, bibliotecas y herramientas que mejor se adapten a sus necesidades, fomentando la toma de decisiones distribuida.

    Desafíos de la Arquitectura de Microservicios

    Veamos de cerca algunas de las posibles complicaciones y limitaciones que podríamos enfrentar al adoptar esta innovadora arquitectura.

    1. Mayor uso de recursos: Al tener múltiples componentes en lugar de compartir el mismo espacio de proceso, la necesidad de comunicación entre ellos aumenta, generando mayor carga en la red. Esto se traduce en más tráfico, latencia y uso de E/S. Además, la carga total de CPU y RAM también es mayor debido a la ejecución independiente de cada componente. Todo esto repercute finalmente en los costos de implementación y mantenibilidad.

    2. Dificultades en la depuración: Diagnosticar y depurar suele ser más difícil con varios servicios. Por ejemplo, si varios servicios procesan una solicitud que falla, un desarrollador debe acceder a los registros de varios servicios para entender la causa de la falla.

    3. Necesidad de pruebas de integración complejas: La separación de un sistema implica la construcción de un conjunto extenso de pruebas de integración y otros controles automatizados que monitorizan la compatibilidad y disponibilidad de cada componente.

    4. Consistencia en transacciones: La dispersión de datos en las aplicaciones de microservicios dificulta la realización de cambios transaccionales y atómicos en el sistema.

    5. Divergencia en versiones y librerías: Los servicios pueden utilizar diferentes versiones de bibliotecas, algunas de las cuales pueden ser incompatibles u obsoletas. Esto complica las actualizaciones del sistema y la solución de problemas, incluyendo correcciones de vulnerabilidades de software.

    6. Deuda técnica en un sistema distribuido: La deuda técnica en el software se refiere a compromisos o decisiones que los desarrolladores toman durante el proceso de desarrollo de software que, a corto plazo, aceleran la entrega de un producto pero generan problemas a largo plazo. Estos compromisos pueden incluir la implementación de soluciones rápidas y poco robustas, la omisión de pruebas exhaustivas, el uso de código desactualizado o el incumplimiento de estándares de codificación. Abordar la deuda técnica es más complicado en un sistema distribuido donde cada componente es propiedad de un equipo diferente y suele convertirse en una bola de nieve hasta que los problemas son mas que evidentes.

    7. Observabilidad: Gestionar múltiples aplicaciones implica desafíos adicionales en la recopilación y uso de eventos del sistema, como registros, trazas y métricas. Los desarrolladores deben asegurarse de que todos estos datos estén disponibles para análisis, incluyendo información contextual necesaria para depurar problemas entre los servicios.

    8. Duplicación de funcionalidades: En entornos de desarrollo altamente distribuidos, no es raro tener múltiples componentes realizando roles similares en el sistema. Es crucial establecer límites claros y decidir de antemano qué roles específicos se asignan a cada componente.

    9. Propiedad y responsabilidad: La propiedad se vuelve crucial cuando varios equipos mantienen y desarrollan componentes independientes. Es fundamental definir contratos de propiedad claros para abordar solicitudes de desarrollo, problemas de seguridad y mantenimiento.

    Como hemos ilustrado, el modelo de microservicios tiene sus desafíos, pero ser conscientes de estos problemas y abordarlos de manera proactiva es clave para el éxito.

    Claves para el éxito en el desarrollo ¿Cómo implementar Microservicios?

    Hemos explorado sus beneficios, desafíos comunes y ahora es momento de resumir las claves esenciales para aprovechar al máximo el modelo de microservicios en el desarrollo de aplicaciones.

    1. Introducción gradual: Evita implementar la arquitectura de microservicios demasiado pronto si el producto aún está poco definido o podría experimentar cambios significativos. Comienza con una aplicación monolítica y divídela a medida que se definan claramente las capacidades comerciales y los límites, reduciendo así la carga de trabajo y estableciendo interfaces adecuadas entre los componentes. También podrías definir servicios muy generales y claramente identificables.

    2. Modelo de negocio único: La decisión de adoptar microservicios debe basarse en diversos factores, como el tamaño y distribución del equipo, así como la geografía. Un equipo local pequeño puede sentirse cómodo trabajando con una aplicación monolítica, mientras que un equipo distribuido geográficamente podría beneficiarse enormemente al dividir la aplicación en múltiples microservicios para lograr mayor flexibilidad. Identifica procesos y como funcionan estos a nivel de negocio, puede que tu aplicación se parezca a otra pero no significa que debes copiar al detalle.

    3. Planificación para escenarios de falla: Dado que en la arquitectura de microservicios hay numerosas interacciones entre los componentes a través de llamadas remotas y eventos, se incrementa la posibilidad de diversas fallas. Construye el sistema considerando todos los posibles escenarios de falla y las diferentes formas de abordarlos.

    4. Abrazar la automatización: Con componentes más independientes, se requieren verificaciones más estrictas para lograr una integración estable entre los servicios. La inversión en una automatización sólida es crucial para lograr un alto grado de confiabilidad y asegurar que todos los cambios sean seguros para ser implementados.

    5. Modelo de negocio vs jerarquía: Aunque es común dividir la aplicación en servicios basados en la estructura organizativa, donde cada equipo es responsable de su propio servicio, esto solo funciona bien si la estructura organizativa se alinea perfectamente con las capacidades de negocio de los microservicios. En lugar de seguir un modelo servicio-por-equipo, define dominios y procesos de negocio claros alrededor de los cuales se estructura el código.

    6. Enfoque en pruebas de integración: Asegúrate de tener pruebas integrales para las integraciones entre tus microservicios, realizándose automáticamente.

    7. Mantener la compatibilidad hacia atrás: Recuerda mantener tus cambios compatibles hacia atrás para garantizar que las nuevas modificaciones sean seguras para implementar. Lo mas aconsejable es construir sobre las definiciones que ya tienes para que se mantenga la retrocompatibilidad.

    A medida que desvelamos los secretos detrás de esta arquitectura de desarrollo, recordemos que el futuro tecnológico nos espera con infinitas posibilidades. Así que, ¡prepárense para abrazar la era de los microservicios y conquistar nuevos horizontes en el desarrollo de software! No olvides dejar tu comentario y dudas ¡Hasta el próximo encuentro!


    ¡Conviértete en un experto tecnológico! 🚀 Suscríbete a nuestro newsletter y recibe las últimas noticias, análisis y tendencias directamente en tu bandeja de entrada. No te pierdas las actualizaciones que harán que tu experiencia tecnológica sea aún más emocionante. ¡Únete a nuestra comunidad hoy! 📧✨

  • Descubriendo el Mundo de los Microservicios en Desarrollo de Software

    Descubriendo el Mundo de los Microservicios en Desarrollo de Software

    La arquitectura de microservicios ha emergido como una piedra angular para muchas empresas en todo el mundo. Este enfoque revolucionario ha transformado la manera en que concebimos y construimos aplicaciones, permitiendo una mayor flexibilidad y escalabilidad. En este artículo, exploraremos a fondo qué es exactamente la arquitectura de microservicios y cómo ha llegado a ser la elección predeterminada para el desarrollo de software en numerosas compañías.

    ¿Qué es un Microservicio?

    El término servicio se refiere a un conjunto de funciones o tareas que un programa o aplicación proporciona para cumplir con una o varias funciones específicas. Estos servicios son a menudo parte de una arquitectura más amplia y se diseñan para realizar tareas específicas de manera eficiente y modular. Aquí hay algunas características clave de los servicios en programación:

    1. Funcionalidad específica: Un servicio generalmente se centra en una funcionalidad específica o conjunto de funciones relacionadas. Por ejemplo, un servicio puede encargarse de gestionar la autenticación de usuarios, procesar pagos, o proporcionar acceso a bases de datos.

    2. Interfaz definida: Los servicios suelen tener una interfaz claramente definida que especifica cómo se pueden acceder y utilizar. Esto se puede lograr mediante API (Interfaz de Programación de Aplicaciones) o mediante protocolos de comunicación específicos.

    3. Independencia: Los servicios son diseñados para ser independientes y modularizados. Esto significa que pueden ser desarrollados, probados y actualizados de manera independiente, lo que facilita la gestión y mantenimiento del sistema completo.

    4. Comunicación: Los servicios a menudo se comunican entre sí o con otras partes del sistema. La comunicación puede ocurrir a través de diversos mecanismos, como llamadas a API, mensajes, o servicios web.

    5. Reusabilidad: Dado que los servicios están diseñados para realizar funciones específicas, pueden ser reutilizados en diferentes partes de una aplicación o incluso en diferentes aplicaciones. Esto promueve la eficiencia en el desarrollo y la mantenibilidad del código.

    6. Escalabilidad: La arquitectura basada en servicios facilita la escalabilidad de una aplicación, ya que los servicios pueden ser escalados de manera independiente según las necesidades de carga de trabajo específicas.

    7. Tecnologías: Los servicios pueden implementarse utilizando diversas tecnologías, como microservicios, servicios web, funciones en la nube, entre otros, dependiendo de los requisitos del proyecto.

    Ahora, si hablamos específicamente de microservicios estamos hablando de un servicio aun mas especializado, es decir que al momento de planificar nuestra arquitectura debemos procurar identificar los procesos para generar sus abstracciones de manera clara pero simple; pongamos un ejemplo para entenderlo mejor: Podemos tener un servicio que se encargue de la gestión de usuarios,  en donde tenemos procesos como registro, autenticación, obtener perfil y actualizar datos, ahora esto se podría separar en dos microservicios, por una parte podríamos tener un microservicio encargado de lo que tiene que ver con el registro y autenticación y el otro de los datos de sesión o perfil; claro que esto no es así tan fácil, esto requiere un análisis concienzudo, entender los procesos y que encaje con nuestra arquitectura empresarial. Cualquier servicio puede ser tratado como microservicio siempre y cuando tenga cohesión lógica y estructural.

    ¿Qué es una arquitectura de Microservicios?

    Muy fácil, es un enfoque de diseño de software que organiza una aplicación como un conjunto de servicios pequeños e independientes. Cada servicio se centra en una tarea específica y puede ser desarrollado, implementado y escalado de manera independiente. Estos servicios se comunican entre sí a través de interfaces bien definidas.

    Aquí hay algunas características clave de la arquitectura de microservicios:

    1. Descomposición en servicios: En lugar de construir una aplicación monolítica, la arquitectura de microservicios divide la funcionalidad en servicios más pequeños, cada uno ejecutando un proceso independiente. Cada servicio se enfoca en realizar una tarea específica dentro del dominio de la aplicación.

    2. Independencia y escalabilidad: Cada servicio es independiente y puede ser desarrollado, implementado y escalado de manera autónoma. Esto permite a los equipos de desarrollo trabajar de manera más eficiente y facilita la escalabilidad, ya que solo los servicios que necesitan más recursos pueden ser escalados.

    3. Comunicación a través de APIs: Los microservicios se comunican entre sí a través de APIs bien definidas. Esto significa que cada servicio expone una interfaz clara que especifica cómo otros servicios pueden interactuar con él. La comunicación puede realizarse de manera síncrona o asíncrona, según los requisitos.

    4. Despliegue independiente: Los microservicios pueden ser desplegados de forma independiente, lo que facilita la implementación continua y la actualización de servicios sin afectar toda la aplicación. Esto mejora la agilidad del desarrollo y reduce el tiempo de inactividad.

    5. Resiliencia y tolerancia a fallos: La arquitectura de microservicios fomenta la resiliencia al diseñar servicios que son autónomos y pueden manejar fallas de manera aislada. Si un servicio falla, no debería afectar a los demás servicios en la aplicación.

    6. Poliglota: Cada servicio puede ser desarrollado en el lenguaje de programación más adecuado para su tarea específica. Esto permite a los equipos utilizar las tecnologías más apropiadas para cada servicio, según sus necesidades.

    7. Gestión de datos descentralizada: Cada servicio puede tener su propia base de datos, y la gestión de datos se realiza de manera descentralizada. Esto evita la dependencia de una única base de datos monolítica.

    8. Orientación al dominio de negocio: Los microservicios se organizan en torno a las capacidades del negocio, lo que facilita la comprensión y mantenimiento del sistema. Sobre como entender y trabajar el dominio del negocio te deje unos post de arquitectura empresarial.

    Ejemplo en Archimate de una arquitectura de microservicios

    Las empresas a nivel mundial han adoptado tan ampliamente el modelo de arquitectura de microservicios que casi se ha convertido en la forma estándar de desarrollo de software. Estas compañías cuentan con decenas, cientos e incluso miles de microservicios a su disposición.

    En pocas palabras, la arquitectura de microservicios organiza una aplicación como una colección de servicios, llamados microservicios, cada uno de los cuales es responsable de una parte específica de la lógica de la aplicación, generalmente definida por una capacidad comercial particular.

    Tomemos como ejemplo una aplicación de mercado en línea. La aplicación puede tener múltiples funciones, como búsqueda, carrito de compras, pagos, historial de pedidos y muchas más. Cada función puede ser tan diferente que el código puede (y en algunos casos, debería) ser completamente independiente del resto de la aplicación. En este ejemplo, la búsqueda y los pagos técnicamente no tienen nada en común. En el modelo de arquitectura de microservicios, cada componente sería un servicio independiente que desempeña su propio papel en el sistema.

    Desafíos… Separar la Aplicación en Servicios:

    Organizar cada parte de la aplicación como un servicio separado no es necesariamente un requisito. Al igual que con cualquier modelo de arquitectura o aspecto del desarrollo de software, los ingenieros deben ser cuidadosos al elegir un enfoque o solución particular, realizando un análisis inicial y comprendiendo la solución en las condiciones dadas.

    El dilema monolítico

    Para entender la motivación detrás de la arquitectura de microservicios, primero, veamos el enfoque opuesto: las aplicaciones monolíticas o “monolitos”. Estas aplicaciones son construidas y ejecutadas como un solo programa, con una arquitectura simple que no implica dividir la aplicación en partes independientes.

    Ventajas de los Monolitos:

    • Código Compacto: Al no dividir la aplicación, el código base es más pequeño, evitando complejidades asociadas a la comunicación entre componentes.

    • Flexibilidad en la Lógica de la Aplicación: Permite cambios estructurales o lógicos fácilmente en las etapas iniciales de desarrollo, donde la agilidad es clave.

    • Alcance Reducido: No todos los servicios necesitan descomposición; servicios simples pueden permanecer integrales.

    ¿Cuándo los monolitos se vuelven problemáticos?

    • Tamaño y Despliegues Lentos: A medida que la aplicación crece, el tiempo de construcción, inicio y despliegue puede volverse excesivamente lento.

    • Imposibilidad de desplegar partes independientemente: La incapacidad de actualizar partes específicas puede ralentizar el desarrollo y lanzamiento.

    • Amplitud de impacto: Errores en una función afectan toda la aplicación, generando posibles problemas significativos.

    • Cuello de botella en escalabilidad vertical: A medida que la aplicación crece, es difícil escalarla aún más debido a limitaciones en CPU y RAM.

    La arquitectura de microservicios surge cuando los monolitos se vuelven demasiado grandes. Los desarrolladores enfrentan problemas como tamaños de aplicación masivos, despliegues lentos y dependencias no deseadas entre componentes. Aquí es donde entran los microservicios.

    En el siguiente post, exploraremos cómo la división de la aplicación en microservicios aborda estos problemas y qué aspectos debes tener en cuenta. ¡Mantente atento para descubrir cómo esta arquitectura puede revolucionar tu enfoque de desarrollo! No olvide dejar tus comentarios e inquietudes. Hasta la próxima.


    ¡Conviértete en un experto tecnológico! 🚀 Suscríbete a nuestro newsletter y recibe las últimas noticias, análisis y tendencias directamente en tu bandeja de entrada. No te pierdas las actualizaciones que harán que tu experiencia tecnológica sea aún más emocionante. ¡Únete a nuestra comunidad hoy! 📧✨

  • Desconectando cables y conectando emociones: Soledad informática

    Desconectando cables y conectando emociones: Soledad informática

    Estaba haciendo una introspección y no pude dejar de notar que mi circulo social es reducido, y que además muchos de las personas jóvenes con quien trabajo en tecnología están solos o tienen relaciones algo toxicas. Hoy en día, no es un secreto que existe un fenómeno paradójico donde entre mas conexión digital tenemos mas desconexión humana existe, se a incrementado la soledad y las personas tienden a sentirse menos felices y poco realizadas. Podemos hablar sobre sus causas, sobre la influencia de las redes, las tendencias, tópicos y si eres tan friki como yo, hasta podríamos integrar la ecuación de Drake para cuantificar por que estamos solos(LOL), pero en este post quiero simplemente dar una opinión ligera, divertida y algunos tips para hacer update a nuestra cpu y lograr ser parte de la red de la vida y no solo limitarnos a compartir memes.

    Código solitario

    Es bien sabido que los informáticos tienen una relación íntima con sus computadoras. Pero, ¿Por qué prefieren la compañía de líneas de código en lugar de personas? La respuesta es más sencilla de lo que parece: ¡El código no te pide prestado dinero, ni te deja plantado en la cafetería! Fin del análisis…

    Pero enserio, la naturaleza de nuestro trabajo, centrada en la lógica y la resolución de problemas, puede llevar a una inmersión profunda nuestros propios pensamientos, creando una barrera invisible con el resto del mundo. A veces, el código puede ser un mejor compañero de conversación que el vecino del otro piso; yo también he pasado horas peleando con una instrucción o buscando como solucionar un bug entre mundos de respuestas de Stackoverflow y cuando llegas a la solución es la mejor sensación, te olvidas de todas esas horas y te felicitas como el campeón que eres. Y esto no se limita a los informáticos, la verdad es que muchas profesiones y sobre todo después de pandemia, nos acostumbramos a la comodidad de la casa y explorar el mundo por medio de un dispositivo. Lo digo por experiencia propia, por ejemplo me entere de la pandemia fue por el miedo a perder los sabores, amo comer y mi mayor terror fue perder el gusto, por lo demás ya vivía aislado y encerrado en mis temas y proyectos.

    Y hoy salgo aquí gritando al mundo que esta mal encerrarnos, esta mal dejar pasar la vida y no sacar nada de ella, independientemente de que creas, como vivas y que esperas para tu futuro debes tomar esas pequeñas oportunidades que aparecen cada día. Carpe diem. Y es que no soy una historia de redención, sigo luchando con salir, con dejar la comodidad y buscar la aventura.

    Cada día suelo hablar con una amiga que se ha convertido en mi gurú en este cambio, he tenido altas y bajas y quienes me conocen saben que soy muy introvertido, aun así cada vez que salgo alguna payasada me ocurre y me he dado cuenta que esas situaciones y compartirlas con los demás es lo que mas alegría me da.

    Habilidades blandas en el mundo binario

    Las habilidades blandas, esas que no tienen nada que ver con la suavidad de las almohadas, son la clave para romper este hielo digital. Comunicación, empatía, trabajo en equipo y otras habilidades sociales pueden parecer tan ajenas como un lenguaje de programación exótico, pero son esenciales para salir del modo “solitario” y abrazar el modo “social”.

    Pequeños cambios día a día van haciendo hábitos y van creando una hermosa historia que dejar plasmada en Wikipedia. A veces tratamos y nos cuesta pero esos pequeños amigos que se quedan te impulsan a buscar mas y a ir tras las aventuras. Muchas veces me repito: No lo haces por ti lo haces por las historias. Y creo que esa es una excelente manera, busca tu motivación, busca tu ancla para no perderte solo en internet.

    Desenchufando la soledad

    Primero ten en cuenta que nuestra droga es digital y que parece que no genera ningún perjuicio, así que es difícil tratarla y lleva tiempo. Ahora como logramos salir de la guarida y sumergirnos en el mundo real? Aquí van algunos consejos prácticos:

    • Outsourcing: Debemos hacernos con un par de amigos que nos motiven a salir, que no sean solo chats y juegos de computadora. Lo peor que puedes hacer es buscar mas amigos digitales, tener un millón de amigos en Facebook es equivalente a estar en un edificio de solo chismosos, nada bueno sacaras escuchando babosadas.
    • Agregar a lista de deseados: Este particularmente me ha servido, y es que encontrar esas cosas que te gustan te motivan a salir. En mi caso a sido la fotografía, acampar, la astronomía y ver a mi perro huir de perros mas pequeños. Por cierto, las mascotas son un gran aliado para empezar a socializar por si te sientes intimidado de hablar con otros.
    • -f: Fuérzate a buscar esas aventuras.

    También me gustaría incluir algunos puntos que podemos practicar en la oficina, podrías implementar con tus compañeros.

    • Eventos tecnológicos con toque humano: Organiza eventos tecnológicos que no se centren solo en códigos y algoritmos, sino también en historias y experiencias. ¡Que se hable de los fallos más épicos o de los proyectos más locos!
    • Talleres de habilidades blandas: Ofrece talleres que combinen la tecnología con el desarrollo personal. Aprender a trabajar en equipo puede ser tan emocionante como descubrir un nuevo framework.
    • Mentoría intergeneracional: Fomenta la conexión entre informáticos más experimentados y aquellos que están dando sus primeros pasos en el mundo tecnológico. La sabiduría de la experiencia puede ser tan valiosa como el código más eficiente.

    Código abierto, corazón abierto

    En resumen, la clave está en balancear el amor por el código con la apertura al mundo exterior. Los informáticos, como cualquier ser humano, también necesitan socializar y compartir experiencias. Desenchufemos esos cables de la soledad y conectemos en el mundo real. Y si no eres informático pero estas vinculado al mundo de la tecnología también es probable que estés cayendo en el ostracismo informático, así que ponte las pilas, sal mas al mundo real y que no te de miedo compartir quien res al mundo.

    Así que ya sabes, la próxima vez que veas a un informático absorto en su pantalla, invítale un café y pregúntale sobre su código favorito. ¡Te sorprenderá la cantidad de historias que pueden contar más allá de las líneas de código! ¡Feliz navegación en este maravilloso océano digital! 🚀💻


    ¡Conviértete en un experto tecnológico! 🚀 Suscríbete a nuestro newsletter y recibe las últimas noticias, análisis y tendencias directamente en tu bandeja de entrada. No te pierdas las actualizaciones que harán que tu experiencia tecnológica sea aún más emocionante. ¡Únete a nuestra comunidad hoy! 📧✨

  • Introducción estadística

    Introducción estadística

    Conceptos básicos

    • Población: Conjunto del cual se quiere extraer características.
    • Muestra: Subconjunto de la población. Es muy importante que este conjunto represente la población, es decir que involucre sus particularidades y características.
    • Inferencia estadística: Proceso para obtener conclusiones de una población a partir de un análisis sobre una muestra.
    • Variable(atributo): Representa el valor de una cualidad de una población, este valor puede variar de registro a registro.
      • Ordinales: No numéricas en la que existe un criterio de orden.
      • Nominales: No numérico y no admiten criterio de orden.
      • Discretas: Toman un número finito de valores, son contables.
      • Continuas: Toman un número infinito de valores en un rango continuo.

    Análisis de variables cualitativas

    Podemos usar una tabla de frecuencias para resumir y facilitar la comprensión de los datos. Esta tabla simplemente consiste en tener cada uno de los valores que puede tomar la variable y la cantidad de repeticiones(frecuencia) que hay en los datos.

    Otra manera, que a mi particularmente me gusta mucho es representar el análisis por medio de gráficos de por ejemplo pie o barras(hay muchos mas). Estos permiten comprender los datos de manera muy visual y fácil, y te da una ventaja al momento de exponer sobre el tema. Tienen una facilidad tremenda de ser comprendidos y causan un impacto a nivel profesional muy bueno.

    Análisis de variables cuantitativas

    Podemos usar medidas de tendencia central:

    • Media
      \bar{x}=\frac{1}{N}\sum_{i=1}^{N}x_i
    • Mediana
      Impar, \bar{x} es el valor en la posición \frac{N}{2}
      Par, \bar{x}=\frac{1}{2}(X\begin{bmatrix}\frac{N}{2}\end{bmatrix}+X\begin{bmatrix}\frac{N}{2}+1\end{bmatrix})
    • Moda
      Valor mas repetido en el conjunto de datos X

    Medidas de posición como en el diagrama de caja y bigotes.

    Medidas de dispersión:

    Medidas de distribución:

    • Coeficiente de asimetría
      Mide la simetría de la distribución de una variable respecto a la media aritmética
      A=\frac{\sum_{i=1}^{N}(x_i-\bar{x})^3}{N\cdot \sigma^3}
    • Curtosis
      Mide el grado de apuntamiento o achatamiento de la distribución de frecuencia respecto a una distribución normal
      K=\frac{\sum_{i=1}^{N}(x_i-\bar{x})^4}{N\cdot \sigma^4}-3
  • Aplicación de una sola página

    Aplicación de una sola página

    Una aplicación de una sola página, como su nombre lo indica, es un sitio donde su frontend se construye dinámicamente desde javascript en una única página, pero se hace de tal manera que cada uno de sus componentes o módulos se va cargando progresivamente, de esta manera se logra brindar una experiencia mucho más fluida. Veamos un ejemplo mas grafico para ver como funciona una petición(request) de una página comúnmente.

    Proceso de petición de una pagina. En paginas convencionales cada vez que hacemos una petición el servidor nos responde con todo el contenido y refresca la pagina.

    Imaginemos que entramos, por ejemplo, a una página construida en PHP (la web suele estar repleta de estos sitios). Nuestra carga inicial es cuando hacemos la petición al dominio, por ejemplo jhontona.com, el DNS se nos redirecciona al servidor que se encargará de brindarnos el contenido que solicitamos, suele ser común los .html (contenido), .css (estilos) y .js (funcionalidad). El problema es que cada vez que se procesa una nueva petición, por ejemplo al enviar un formulario, el cliente requiere hacer una nueva llamada al servidor, este la procesa y reenvía todo el contenido mas la respuesta para el usuario. Esto genera que el sitio se recargue en su totalidad.

    En sus inicios la web eran solo bloques de texto, pero ahora tenemos imagen y video, el cual es demasiado costoso de enviar, sobre todo en redes lentas; para apalear un poco este problema los navegadores guardan en memoria (cache) los archivos más comunes (los mismos que miramos antes) con el objetivo de eliminar de la descarga esos archivos que previamente se habían cargado.

    Las aplicaciones de una sola página (SPA) justamente se aprovechan de este sistema, enviando solamente el contenido que el usuario requiere en ese momento. Veamos como lo hace.

    En nuestro esquema parece que no cambia mucho pero en la pagina esto tiene una gran repercusión, ya que en múltiples peticiones al servidor solo se trae la información que se necesita en ese momento y esto se agradece mucho sobre todo en redes móviles, ya que hacen que nuestras paginas carguen mucho más rápido al solo traer lo que necesitamos para una carga inicial y a partir de esta vamos trayendo los fragmentos necesarios a medida que el usuario navega en nuestro sitio.

    Para crear este tipo de sitios de una sola página se suele trabajar con javascript, este justamente se ejecuta en el cliente y se encarga de hacer las peticiones de manera incremental, podríamos por ejemplo con javascript puro ir haciendo nuestras peticiones a un servicio he ir mostrando la información como deseamos; pero afortunadamente no toca iniciar desde cero, entre los mas reconocidos frameworks tenemos Angular, React y VUE. Todos estos frameworks tienen el mismo objetivo, construir sitios SPA, pero utilizan diferentes enfoques. En un próximo post veremos por que usar Angular y sus características.

  • Programación orientada a objetos (POO)

    Programación orientada a objetos (POO)

    La programación orientada a objetos (POO o sus siglas en ingles OOP) es un estilo(paradigma) de programación. Donde todo se comporta como un objeto, es decir, se hace una abstracción de un concepto y se lleva a código fuente.

    El concepto de abstracción es muy importante entenderlo ya que es la base de la programación orientada a objetos. Consiste en aislar un objeto de su contexto, e identificar este objeto ¿Qué hace?¿Cómo lo hace? y ¿Para que lo hace?. Estas preguntas se resuelven haciendo una análisis del sistema y llevándolo a modelos de código, donde se expresan las características del objeto deseado. Durante este análisis (abstracción) se identifican las características esenciales y las no esenciales, esto con el fin de generar la representación en código.

    Ahora veamos los conceptos por los que esta compuesto la forma de trabajo orientada a objetos.

    Clase

    Una clase es la abstracción de un objeto/concepto concreto, que tiene tiene propiedades(atributos) y realiza algunas acciones(funciones o métodos) y se pueden crear uno o mas copias de este a partir de un modelo.

    Vamos a ver como esta compuesto. Para ejemplificar y que quede mas claro los conceptos vamos a usar el típico ejemplo de una fabrica de vehículos. Supongamos que queremos construir un carro.

    Atributo

    Un atributo es una característica propia de una clase, por ejemplo, en el caso del carro los atributos pueden ser color, cantidad de ruedas, material, etc.. (podemos listar N cantidad de atributos, siempre y cuando sean necesarios para la descripción o funcionamiento de la clase).

    Método

    Un método es una acción que realiza nuestra clase. Netamente en programación es una porción de código encapsulado que se ejecuta en respuesta a alguna llamada, interacción u otra acción(método). Por ejemplo, en nuestro carro, algunos eventos pueden ser: encender, acelerar, frenar… El termino de encapsulamiento es muy importante en la programación orientada a objetos, ya que todo nuestro código debe ir correctamente estructurado, y los métodos deben ser concretos y bien definidos. (Para profundizar en código limpio te dejo este post). El encapsulamiento se refiere a la agrupación de elementos propios con el objetivo de crear un mayor nivel de cohesión y reutilización del código. En alguna literatura y arquitecturas de trabajo tenemos una separación(clasificación) de estos métodos en métodos, funciones y eventos, pero por lo general usaremos método o función para referirnos a lo mismo.

    Con estos conceptos ya podemos plantear un ejemplo completo de nuestra clase carro, así­ que lo pasaremos a código. Utilizare C# para hacer el ejercicio, aplicado a un proyecto de consola. Podríamos utilizar cualquier otro lenguaje que soporte este paradigma, yo elijo este simplemente por que la lectura de código se me hace muy sencilla y así­ todos podemos ver y entender los ejemplos un poco mejor.

     

    Clase vehí­culo

    public class Vehiculo {
        private string color;
        private int cantidadRuedas;
        private string material;
    
        public void encender() {}
        public void acelerar() {}
        public void frenar() {}
    }

    En el anterior ejemplo de código podemos ver la construcción de la clase vehículo, en donde le asignamos algunos atributos y métodos. Podemos ver que estamos usando unas palabras clave antes de declarar un atributo o método(private, public). No entrare a explicar como usarlas en este lenguaje, si no que dará una definición general, aplicable a cualquier lenguaje. Estas palabras nos indican el alcance(scope) de un atributo, método u objeto. ¿Qué quiere decir con alcance? Pues el nivel de visibilidad dentro del contexto. Es decir a que tiene acceso el contexto de un objeto. Aquí entramos a otro concepto fundamental de la programación orientada a objetos, el principio de ocultación. Esto quiere decir que cada objeto esta ligado a su propio contexto y aislado para el resto del entorno. Por ejemplo en nuestra clase vehículo, seria publico el color del carro, pero, por ejemplo, la marca del motor, no queremos que todos la conozcan, por lo que seria privado, o protegido. Este principio aplica para todos los objetos con los que se trabaje.

    En el ejemplo de código anterior deje los atributos como privados, si queremos exponerlos utilizaremos una función GET(obtener valor) o SET(asignar valor) para por medio de ellas tener acceso a este valor.

    Hemos hablado bastante de los objetos e hicimos un ejemplo de la declaración de una clase. No hay que confundir objeto y clase, son términos totalmente diferentes. Un objeto es la instancia de una clase, es decir, la clase anterior es nuestro modelo abstracto y una instancia de este objeto seria un vehículo como tal. Veamos un ejemplo de la creación de un objeto de tipo vehículo con código.

     

    Instanciando una clase

    Vehiculo modelo1 = new Vehiculo();
    Vehiculo modelo2 = new Vehiculo();
    Vehiculo modelo3 = new Vehiculo();

    Hemos creado varias instancias(objetos) de la clase vehículo, ahora hagamos algunos experimentos.
    Antes de continuar aclaro que a nuestra clase Vehiculo le agregue los getters y setters para trabajar con los atributos, a continuación voy a colocar un ejemplo para el atributo color.

    GET y SET

    public string getColor() {
        return this.color;
    }
    
    public void setColor(string color) {
        this.color = color;
    }

    En la mayoría de lenguajes lo pueden hacer de esta manera, pero en el código completo también encontraran otro modo para hacerlo con una notación propia del lenguaje.

    Bueno ahora si continuemos. Creamos tres vehículos, a cada uno vamos a asignarle las ruedas, un color y un material, finalmente imprimimos en pantalla el color de cada uno.

    Usando los métodos get y set

    modelo1.cantidadRuedas = 4;
    modelo2.cantidadRuedas = 4;
    modelo3.cantidadRuedas = 4;
    modelo1.setColor("Rojo");
    modelo2.setColor("Amarillo");
    modelo3.setColor("Azul");
    modelo1.material = "Aluminio";
    modelo2.material = "Plastico";
    modelo3.material = "Fibra De Carbono";
    Console.WriteLine(modelo1.getColor());
    Console.WriteLine(modelo2.getColor());
    Console.WriteLine(modelo3.getColor());

    Tenemos en este momento una clase Vehiculo, con la cual hemos creado tres carros, pero si lo pensamos bien podemos crear otro tipo de vehículos como una bicicleta, moto u otro tipo de vehículo sobre ruedas. Así­ que vamos a tocar otro pilar de la programación orientada a objetos.

    Herencia

    Aunque las clases se crean para estar aisladas de un contexto, estas se deben relacionar con otras, para así dar sentido y funcionalidad a ese contexto; este concepto podemos entenderlo como una relación padre-hijo, donde el hijo hereda propiedades y características del padre, dependiendo del scope que tengan estas características definidas el hijo podrá o no heredar características que estén como publicas o protegidas en el padre.

     

    Veamos el código. Agregaré dos clases para mostrar como funciona la herencia.

    Clase Carro que hereda de la clase Vehiculo

    public class Carro : Vehiculo {
        public Carro() {
            this.cantidadRuedas = 4;
            this.setColor("Dorado");
            this.material = "Hierro";
        }
    
        public Carro(string color, string material) {
            this.cantidadRuedas = 4;
            this.setColor(color);
            this.material = material;
        }
    }

    Clase Bicicleta que hereda de la clase Vehiculo

    public class Bicicleta : Vehiculo {
        public Bicicleta() {
            this.cantidadRuedas = 2;
            this.material = "Aluminio";
            this.setColor("Cromado");
        }
    
        public Bicicleta(string color) {
            this.cantidadRuedas = 2;
            this.material = "Aluminio";
            this.setColor(color);
        }
    }

    Podemos hablar de otro termino viendo el ejemplo, y son los constructores, no son propios de la programación orientada a objetos, pero se están convirtiendo en un estándar para todos los lenguajes que apuntan a este paradigma. Acerca de este tema solo voy a decir que el constructor es un método que se caracteriza por tener el mismo nombre de la clase y es el encargado de inicializar la instancia de la clase. Un tema mucho mas importante, y que si es propio de este paradigma es el concepto de polimorfismo, este atributo de la programación orientada a objetos nos permite crear varios métodos con el mismo nombre pero que se comporten de manera diferente dependiendo de los parámetros que recibe. En el código anterior podemos ver el ejemplo, donde hay dos constructores para cada clase y así ilustrar esta característica. También lo podríamos hacer con cualquier otro método.

    Hemos revisado el concepto de herencia y ahora podemos segmentar nuestra aplicación en diferentes clases con cierta relación, esto nos lleva a otro principio de la programación orientada a objetos. La modularidad, que se refiere a la capacidad de separar estas clases y agruparlas en módulos, es decir, secciones que comparten un mismo contexto.

    Por ultimo nos queda un ultimo termino que ver, este es la recolección de basura, que se refiere a la capacidad del lenguaje de eliminar de memoria los objetos que ya no se van a usar. La mayoría de lenguajes que usan este paradigma lo hacen de manera automática.

    Y esto es todo amigos… Dejamos por aquí esta introducción a POO, espero les halla sido de mucha utilidad, recuerden dejar sus comentarios y preguntas.

¡Hola a todos los entusiastas de la tecnología! Quería informarles que en mi blog utilizamos cookies para mejorar la experiencia de usuario. Estas pequeñas herramientas nos ayudan a personalizar el contenido y ofrecer funciones específicas. Al continuar explorando el sitio, aceptas nuestro uso de cookies. Puedes obtener más información sobre cómo las utilizamos en nuestra política de privacidad. ¡Gracias por ser parte de esta comunidad tecnológica! 🍪    Más información
Privacidad