130 lines
No EOL
9.3 KiB
Markdown
130 lines
No EOL
9.3 KiB
Markdown
|
|
## TLDR
|
|
|
|
- [[#Time Tracking|Time Tracking]]
|
|
- [[#Planear|Planear]]
|
|
- [[#Planear#Entradas|Entradas]]
|
|
- [[#Planear#Salidas|Salidas]]
|
|
- [[#Planear#Nombres|Nombres]]
|
|
- [[#Realizar un mock de la salida|Realizar un mock de la salida]]
|
|
- [[#¿Cómo genero la salida?|¿Cómo genero la salida?]]
|
|
- [[#Realizar la implementación|Realizar la implementación]]
|
|
- [[#Realizar pruebas|Realizar pruebas]]
|
|
- [[#Descansar y repetir|Descansar y repetir]]
|
|
- [[#Ejemplo de recursividad|Ejemplo de recursividad]]
|
|
|
|
## Cosas a tener en mente
|
|
|
|
- [Accept that Everything Is a Draft](The%20cult%20of%20done.md#Accept%20that%20Everything%20Is%20a%20Draft), siempre se puede volver a ello y mejorarlo. Por ahora, esto es un prototipo...
|
|
- Contrario al punto anterior, si algo fue lanzado al mundo, ya se fue, no quedarse modificando lo mismo para siempre.
|
|
- Concentrarse en una cosa a la vez:
|
|
1. Escribir algo que funcione.
|
|
2. Mejorar la implementación, performance y corregir bugs.
|
|
3. Limpiar y refactorizar, sólo si queda tiempo/energía y es necesario ([good enough](Good%20Enough.md)).
|
|
|
|
## Time Tracking
|
|
|
|
Esto no es con el objetivo de reportar lo realizado o de maximizar la productividad, si no con el de evitar la fatiga y la visión de túnel. Puedes utilizar la técnica, metodología y/o longitud que prefieras o sea más apta para la tarea, pero lo ideal es tomar descansos regulares. Esto ayudará fisiológicamente a nuestro cuerpo (ojos, espalda, cuello, etc) y a nuestra mente.
|
|
|
|
Algunas metodologías que pueden ser utilizadas incluyen:
|
|
- Pomodoro
|
|
- Flowtime
|
|
|
|
## Planear
|
|
|
|
Similar a la resolución de problemas en matemática, debemos asegurarnos de que entendemos lo que debemos realizar, con que datos contamos o necesitamos y que es lo que debemos entregar. Mientras mayor claridad tengamos sobre esto, más fácil será realizar la tarea. Con el tiempo este proceso se vuelve algo automático que hacemos mentalmente, pero es buena idea realizar el ejercicio concientemente para facilitar el trabajo.
|
|
|
|
En caso de lenguajes tipeados como Typescript, C++, Rust u otros, definir los tipos de datos es algo necesario durante el desarrollo, si bien podemos hacerlo durante o despues de escribir la funcionalidad, hacerlo antes tiene sus ventajas:
|
|
|
|
- Claridad de la información con la que contamos y lo que debemos producir, por lo que no necesitaremos modificar la definición del tipo de retorno multiples veces a medida que desarrollamos la funcionalidad, por ejemplo.
|
|
- Reduciremos la cantidad de código en rojo, alertas y errores de compilación que nos distraerán de desarrollar la funcionalidad.
|
|
|
|
En lenguajes no tipeados como Javascript, Python o Lua, también podemos aplicar definiciones de tipo para funciones, metodos, clases y otros mediante comentarios, que nos ayudarán tanto a definir nuestras entradas y salidas como al lector del código ya que el editor les dará información sobre como utilizarlo:
|
|
|
|
En caso de Javascript, se puede utilizar [JSDocs](https://jsdoc.app/)
|
|
|
|
### Entradas
|
|
|
|
Debemos definir que información necesitamos (o contamos) para realizar la tarea, definir esto en primera instancia nos ayudará en la etapa de ejecución a que ya sabemos que tenemos disponible y sus posibles variaciones, por lo que podemos correr los aplicar validaciones y asegurarnos de cumplir todos los posibles casos.
|
|
|
|
Algunas cosas que son buena idea considerar en este momento:
|
|
- Las entradas deben ser acotadas, Ej: no pasar parámetros demás a una función.
|
|
- Seguir estándares y buenas prácticas, Ej: La programación funcional dice que no debemos modificar un parámetro.
|
|
|
|
### Salidas
|
|
|
|
¿Cuál será la forma final de la funcionalidad? Debemos definir el tipo de dato que mejor se acomode a lo que vamos a realizar, ¿Es mejor un array o una tupla? ¿Quizá entregarlo como un hash-map?
|
|
|
|
### Nombres
|
|
|
|
Definir un buen nombre para los elementos utilizados en el algoritmo, esto puede incluir el nombre de la función o método que estemos creando, los parametros, el nombre de la clase, el archivo, módulo, etc.
|
|
|
|
Algunas recomendaciones:
|
|
- Usar un sustantivo para _datos_ ó _información_ (_variables_ ó _propiedades_), este debe ser descriptivo y puntual para describir lo que contiene.
|
|
- _userData_ es muy amplio y ambiguo, _userAddress_ es algo más acotado y aceptable
|
|
- Usar verbos para _funcionalidad_ (_funciones_ ó _métodos_), hay que describir lo que **hace**, no lo que es.
|
|
- _activateUserAccount_ en ves de _userAccountUpdater_
|
|
- Ajustarse a las convenciones definidas (Ej: Casing).
|
|
- Evitar nombres ambiguos o vagos (Ej: aux, util), estos nombres son aceptables si se pueden especificar más. Ej: una carpeta llamada _utils_ con archivos más especificos dentro.
|
|
- Usar palabras completas, evitar abreviaciones y **NO** usar una sola letra. Los editores de texto proveen autocompletado, por lo que no hay beneficio en escoger un nombre más corto para evitar escribir más, solo aumentamos la legibilidad del código.
|
|
- **NO** usar _magic numbers_ (números escritos en duro en el código), es mejor convertirlos en una variable para saber porqué es ese numero en especifico o en un ultimo caso, dejar un comentario.
|
|
|
|
|
|
Para mayor información, [este](https://www.youtube.com/watch?v=K9ohUuZhWnY) video es un buen recurso:
|
|
|
|
<iframe width="560" height="315" src="https://www.youtube.com/embed/K9ohUuZhWnY?si=hIc_uxB9XTttO__E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
|
|
|
## Realizar un mock de la salida
|
|
|
|
En caso de tipos de datos simples, podemos simplemente devolver _0_ de una función por ejemplo, pero en caso más completos podemos devolver un json completo con la información que necesitamos de una REST API y así sabremos que tenemos que producir este resultado final. La idea es despejar nuestra mente sobre el _que_ entregar y así luego solo preocuparnos sobre...
|
|
|
|
## ¿Cómo genero la salida?
|
|
|
|
Con todos los actores definidos podemos hacer un outline del _"paso a paso"_ necesario para realizar obtener la salida o realizar la acción deseada, este puede ser un punteo simple y en orden de las cosas a realizar. Para mayor claridad podemos escribirlo como un comentario en el código para que podamos verlo a medida que desarrollamos la funcionalidad.
|
|
|
|
## Realizar la implementación
|
|
|
|
Finalmente realizamos el paso a paso que definimos para poder crear la funcionalidad deseada. Es importante que para este punto sigamos las normas de la estrategia de time tracking definidas para evitar la visión de túnel y la fatiga.
|
|
|
|
## Realizar pruebas
|
|
|
|
Una ves terminada nuestra funcionalidad, debemos realizar algunas pruebas para saber si funciona correctamente en distintos contextos, estas puedes ser a mano, con pruebas unitarias, pruebas end to end, etc. Sólo debemos aplicar las pruebas y no hacer un trabajo correctivo aún, pues debemos realizar el siguiente paso antes de corregir.
|
|
|
|
Algunas ideas para probar la funcionalidad son:
|
|
|
|
- Volver a leer el requerimiento y seguirlo paso a paso.
|
|
- Probar esta funcionalidad con todos los tipos de usuario que apliquen.
|
|
- Realizar casos extremos.
|
|
- Intentar hacer fallar la funcionalidad a propósito para ver el manejo de errores.
|
|
|
|
## Descansar y repetir
|
|
|
|
Una vez completada la funcionalidad (exitosamente o no) debemos descansar un momento, levantarse y realizar alguna acción completamente agena a lo que estábamos realizando, darle un tiempo a nuestro cerebro de descansar y así nuevamente evitar la visión de túnel y la fatiga. En caso de que la funcionalidad no haya pasado las pruebas exitosamente, o si tenemos tiempo de mejorar nuestra funcionalidad, podemos repetir todos este proceso, pasando más rápido o saltando los pasos que no sea necesario realizar tan en profundidad nuevamente.
|
|
|
|
## Ejemplo de recursividad
|
|
|
|
Podemos ver un ejemplo de como aplicar esta guía para realizar una tarea compleja y dividirla en sub tareas donde tambien aplicamos esta guía. Notar que en este ejemplo está simplificado y no se detallan las entradas y salidas como deberían.
|
|
|
|
Debemos producir un servicio para una REST API que guarde un campo en la base de datos:
|
|
1. Servicio POST:
|
|
- Entrada: JSON con datos.
|
|
- Salida: HTTP 201, como cuerpo un JSON con el mensaje "recurso creado con éxito" ó HTTP 422 con los errores adecuados en caso de fallo.
|
|
- Funcionalides:
|
|
1. Ruta en la aplicación:
|
|
- Entrada: JSON con datos.
|
|
- Salida: HTTP 201, como cuerpo un JSON con el mensaje "recurso creado con éxito" ó HTTP 422 con los errores adecuados en caso de fallo.
|
|
- Funcionalidad:
|
|
1. Controlador:
|
|
- Entrada: JSON con datos.
|
|
- Salida: HTTP 201, como cuerpo un JSON con el mensaje "recurso creado con éxito".
|
|
- Funcionalidad: Lógica del controlador.
|
|
2. Validaciones:
|
|
- Entrada: JSON con datos.
|
|
- Salida: Ninguna en caso de éxito, HTTP 422 con los errores adecuados en caso de fallo.
|
|
- Funcionalidad: validaciones especificas para los campos.
|
|
2. Documentación de API:
|
|
- Entrada: Ninguna.
|
|
- Salida: Documentación sobre como utilizar este servicio.
|
|
- Funcionalidad: Documentación sobre como utilizar este servicio.
|
|
|
|
En este simplificado ejemplo, podemos ver que para realizar la funcionalidad completa de crar un servicio POST que guarde un registro en la base de datos, podemos aplicar esta guía a cada funcionalidad, para segmentar su complegidad y poder concentrarnos en una sola tarea a la ves para realizarla bien. |