Categorías
Desarrollo web General Temporada 2

SleepTracker 0.1-a

Siguiendo con la idea de trabajar en mini-proyectos, hace unas semanas comencé a crear una aplicación web que fuera capaz de hacer un seguimiento de las horas de sueño.

Aquí la complejidad vendría de la mano de tener que desarrollar el stack completo:

Arquitectura

En la parte del servidor he creado un pequeño server con NodeJS y Express que monta una API sencilla sobre la que realizar las consultas.

Los datos están almacenados en una base de datos MongoDB que almacena todas las entradas, tanto las completadas como las que no.

Decidí que fuera la lógica del cliente la que decidiera qué valores mostrar.

La parte del front-end la estoy haciendo con una aplicación simple en React organizada por componentes con la lógica y las consultas extraídas de ella para manejarlas de forma más sencilla.

Diseño frontend

Ahora queda la parte más visual y la de tratamiento de datos.

Una vez comprobadas las conexiones y viendo que la aplicación web es capaz de obtener todos los datos del servidor he empezado a trabajar con ReCharts (https://recharts.org/en-US) para la presentación gráfica.

Lo cierto es que, por ahora, la forma de mostrar las gráficas está siendo bastante sencilla, pero me estoy empezando a encontrar problemas a la hora de personalizar bien los estilos.

Siguientes pasos

Voy a intentar perfilar un poco mejor la presentación gráfica, adecuando los estilos al diseño de la página y terminaré de añadir algunos de los componentes restantes.

Una vez que haya terminado la parte más visual, prepararé el diseño de la inserción de datos, que ha de dividirse en dos partes:

  • Nueva entrada: En el momento de ir a dormir, para marcar el inicio del tiempo.
  • Cierre de entrada: En el momento de despertarse, para marcar el fin del tiempo.

Esto se hará desde un acceso paralelo y mucho más simple para que se puede hacer de forma rápida desde el teléfono móvil.

Categorías
Desarrollo web General

Trabajando en miniproyectos

Uno de los obstáculos con los que me estoy enfrentando a la hora de seguir mi aprendizaje en el mundo del desarrollo web es que los proyectos que inicio suelen eternizarse.

Esto, al final, tiene un efecto importante y es que afecta a la motivación y el interés por el proyecto y, por ende, en el aprendizaje, decae.

Excesiva complejidad = expansión en el tiempo

Cuando te lanzas a entender y comprender un nuevo lenguaje de programación y asimilas algunas de sus estructuras básicas y su potencia puedes tener la tentación de querer abarcar más de lo que eres capaz en realidad.

Como un Sísifo del código, te impones una roca demasiado grande y una montaña demasiado elevada.

A los numerosos parones a los que tienes que enfrentar tu motivación por tratarse de un constante proceso de aprendizaje, has de añadirle que el proyecto, por su propia complejidad, crece en el tiempo y se termina por eternizar.

Aquí es cuando el impulso inicial se diluye y, lo más normal, es el abandono prematuro del proyecto.

Agilidad, especificidad y retorno rápido

Con la idea de los mini proyectos, lo que busco es alcanzar los mismos objetivos de aprendizaje, pero segmentándolos en tareas cerradas más sencillas.

De esta forma, el proyecto tiene un principio y un final mucho más definido, se extiende mucho menos el tiempo y el retorno en forma de satisfacción al haber completado los objetivos es más inmediato.

Lista de mini proyectos

To Do App

Lista de tareas implementada con React & Typescript con un backend basado en SQLite.

Fue mi primer contacto con NES.css, un pequeño framework de CSS con un rollo pixelart muy divertido.

QuizApp

Sistema de preguntas y respuestas. Aquí también empleé React y TypeScript, aunque no desarrollé backend. En su lugar, gestioné las preguntas con un archivo JSON bastante sencillo.

La parte más interesante del proyecto fue su despliegue en Heroku y ver cómo respondía ante un acceso de un usuario externo.

Aplicación de recetas

En proceso.

Categorías
General Temporada 0

Log 0.5

Nota: Este log hace referencia a la parte 8d del curso https://fullstackopen.com/en/part8/fragments_and_subscriptions

Suscripciones en GraphQL

Resulta interesante este concepto para permitir la actualización/notificación de cambios desde el servidor hacia el cliente.

El servidor Apollo hace uso de WebSockets para ello y nos permite informar a quien esté suscrito, es decir, a los componentes que nosotros decidamos, si se produce algún cambio en nuestra base de datos.

Se programa, sobre todo, en la parte de cliente, que es quien se va a suscribir: para eso hacemos uso de una función propia de Apollo, useSubscription:

  export const BOOK_ADDED = gql`
  subscription{
    bookAdded{
      title
    author{
      name
      born
    }
    published
    genres
    id
    }
  }
`
useSubscription(BOOK_ADDED, {
  onSubscriptionData: ({ subscriptionData }) => {
   const addedBook = subscriptionData.data.bookAdded
   updateCacheWith(addedBook)
  }
})
  

En la parte del backend debemos «suscribirnos» a este suscriptor que ya habremos previamente definido en nuestro schema.

Nuestro mutation que añade libros debe cambiar, puesto que en el proceso de cambiar, debemos lanzar una llamada a nuestro suscriptor para avisarle que se va a producir un cambio y, en esa llamada, facilitarle qué estamos cambiando.

Mutation: {
    addBook: async (root, args, context) => {
      const author = await Author.findOne({name: args.author })
      const currentUser = context.currentUser
      
      if(!currentUser){
        throw new AuthenticationError("not authenticated")
      }
            
      const book = new Book({...args, author: author
      })
      try{
        await book.save()
        // Añadimos la suscripción -------------
        pubsub.publish('BOOK_ADDED', { bookAdded: book })
        // -------------------------------------
        return book 
      }catch (error) {
        throw new UserInputError(error.message, {
          invalidArgs: args,
        })
      }

Una vez se produce un cambio generado por el useMutation(ADD_BOOK…) salta el onSubscriptionData y podemos, por tanto, usar una función callback para gestionar qué hacemos con los datos añadidos:

const updateCacheWith = (addedBook) => {
    const includedIn = (set, object) => 
      set.map(p => p.id).includes(object.id)

    const dataInStore = client.readQuery({ query: ALL_INFO })
    if(!includedIn(dataInStore.allBooks, addedBook)) {
      try{
      client.writeQuery({
        query: ALL_INFO,
        data: { allBooks: dataInStore.allBooks.concat(addedBook)}
      })}catch(error){
        console.log(error)
      }
    }
  }

Este es un ejemplo de función que lo que hace es actualizar la caché de GraphQL con los datos añadidos, puesto que uno de los problemas que presenta GraphQL es precisamente la falta de actualización automática cuando se produce un cambio en la base de datos.

Utilizando este mecanismo nos aseguramos, por un lado, que la caché de GraphQL está siempre actualizada con los últimos datos que tiene la base de datos y, por otro, que todos los usuarios que simultáneamente están accediendo al servicio reciben esta actualización de forma inmediata.

GraphQL me ha parecido una solución tremendamente interesante para implementar Heres I, aunque todavía estoy en la parte más inicial del proyecto y tengo algo de margen para decidir qué camino escoger en relación a la forma que voy a utilizar para obtener los datos desde el servidor.

Categorías
General

¡Arrancamos!

start

“Un viaje de mil millas comienza con un primer paso”

Lao-Tse

Hace ya mucho tiempo que la hormiguita de crear algo, fuera lo que fuese, venía incordiándome.

Hoy, por fin, pongo la primera piedra.

Este dev.log pretende convertirse en un cuaderno de bitácora donde ir anotando las idas y venidas de un viaje que confío tenga de todo lo que uno espera al lanzarse a la aventura.

ReactDOM.render(<App ></App>, document.getElementById('root'))