Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support for the Spanish language has been added. #140

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions LANGS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
* [English](en/)
* [Spanish](es/)
* [Chinese](zh/)
* [Japanese](jp/)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Welcome to the tribe.

## Contents

**Also available in [Chinese](zh/README.md) and [Japanese](jp/README.md)**
**Also available in [Chinese](zh/README.md), [Japanese](jp/README.md) and [Spanish](es/README.md)**

1. [Beginner](en/1-Beginner)
- Personal Skills
Expand Down
1 change: 1 addition & 0 deletions en/7-Contributions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ There are a number of ways to contribute to "How to be a Programmer".
Currently this guide has been translated from English into the following languages:

- Chinese by [ahangchen](https://github.com/ahangchen)
- Spanish by [Maximiliano Murua](https://gitlab.com/maximiliano.murua)

**If you provide the initial translation of the guide into another language, you become legible to become a contributor on this project to help maintain and review changes made to the translation.**

Expand Down
21 changes: 21 additions & 0 deletions es/1-Beginner/Personal-Skills/01-Learn-To-Debug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Aprende a depurar
[//]: # (Version:1.0.0)
Depurar es la piedra angular de ser un programador. El primer significado del verbo "depurar" es eliminar errores, pero el significado que realmente importa es ver la ejecución de un programa examinándolo. Un programador que no puede depurar de manera efectiva está ciego.

Los idealistas, aquellos que creen que el diseño, el análisis, la teoría de la complejidad y cosas por el estilo son más fundamentales que la depuración, no son programadores en activo. El programador en activo no vive en un mundo ideal. Incluso si eres perfecto, estás rodeado y debes interactuar con código escrito por grandes empresas de software, organizaciones como GNU y tus colegas. La mayoría de este código es imperfecto y está imperfectamente documentado. Sin la capacidad de obtener visibilidad en la ejecución de este código, el menor tropiezo te dejará permanentemente atrás. A menudo, esta visibilidad solo se puede obtener mediante experimentación, es decir, depuración.

La depuración se trata de la ejecución de programas, no de los programas en sí mismos. Si compras algo a una gran empresa de software, por lo general no llegas a ver el programa. Pero aún así, surgirán situaciones en las que el código no cumple con la documentación (hacer que tu máquina entera se bloquee es un ejemplo común y espectacular) o donde la documentación no dice nada. Más comúnmente, cometes un error, examinas el código que escribiste y no tienes idea de cómo puede estar ocurriendo el error. Inevitablemente, esto significa que alguna suposición que estás haciendo no es del todo correcta o que surge alguna condición que no anticipaste. A veces, el truco mágico de mirar fijamente el código fuente funciona. Cuando no lo hace, debes depurar.

Para obtener visibilidad en la ejecución de un programa, debes ser capaz de ejecutar el código y observar algo al respecto. A veces esto es visible, como lo que se muestra en una pantalla o el intervalo de tiempo entre dos eventos. En muchos otros casos, implica cosas que no están destinadas a ser visibles, como el estado de algunas variables dentro del código, qué líneas de código se están ejecutando realmente o si ciertas afirmaciones se mantienen en una estructura de datos complicada. Estas cosas ocultas deben ser reveladas.

Las formas comunes de examinar el "interior" de un programa en ejecución se pueden categorizar de la siguiente manera:

- Usando una herramienta de depuración,
- Printlining: Haciendo una modificación temporal al programa, generalmente agregando líneas que imprimen información, y
- Logging: Creando una ventana permanente en la ejecución del programa en forma de un registro.

Las herramientas de depuración son maravillosas cuando son estables y están disponibles, pero la inserción de líneas de impresión (printlining) y el registro (logging) son aún más importantes. Las herramientas de depuración a menudo quedan rezagadas con respecto al desarrollo del lenguaje, por lo que es posible que no estén disponibles en un momento dado. Además, debido a que la herramienta de depuración puede cambiar sutilmente la forma en que se ejecuta el programa, puede que no siempre sea práctica. Finalmente, hay algunos tipos de depuración, como verificar una afirmación contra una estructura de datos grande, que requieren escribir código y cambiar la ejecución del programa. Es bueno saber cómo usar herramientas de depuración cuando son estables, pero es fundamental poder emplear los otros dos métodos.

Algunos principiantes temen la depuración cuando requiere modificar el código. Esto es comprensible, es un poco como una cirugía exploratoria. Pero debes aprender a tocar el código y hacerlo saltar; debes aprender a experimentar con él y comprender que nada de lo que hagas temporalmente lo empeorará. Si sientes este miedo, busca a un mentor; perdemos a muchos buenos programadores en el delicado inicio de su aprendizaje debido a este miedo.

Siguiente [¿Cómo depurar dividiendo el espacio del problema?](02-How-to-Debug-by-Splitting-the-Problem-Space.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# ¿Cómo depurar dividiendo el espacio del problema?
[//]: # (Version:1.0.0)

Depurar es divertido, porque comienza con un misterio. Piensas que debería hacer algo, pero en cambio hace algo diferente. No siempre es tan simple; cualquier ejemplo que pueda dar será más artificial en comparación con lo que a veces sucede en la práctica. Depurar requiere creatividad e ingenio. Si hay una clave única para depurar, es utilizar la técnica de dividir y conquistar en el misterio.

Supongamos, por ejemplo, que creaste un programa que debería realizar diez cosas en una secuencia. Cuando lo ejecutas, se bloquea. Como no lo programaste para que se bloqueara, ahora tienes un misterio. Cuando miras la salida, ves que las primeras siete cosas de la secuencia se ejecutaron con éxito. Las últimas tres no son visibles en la salida, así que ahora tu misterio es más pequeño: 'Se bloqueó en la cosa #8, #9 o #10'.

¿Puedes diseñar un experimento para ver en qué cosa se bloqueó? Claro. Puedes usar un depurador o podemos agregar declaraciones de impresión (o su equivalente en el lenguaje en el que estás trabajando) después de #8 y #9. Cuando lo ejecutemos nuevamente, nuestro misterio será más pequeño, como 'Se bloqueó en la cosa #9'. Encuentro que tener en cuenta exactamente cuál es el misterio en cualquier momento ayuda a mantener el enfoque. Cuando varias personas trabajan juntas bajo presión en un problema, es fácil olvidar cuál es el misterio más importante.

La clave para dividir y conquistar como técnica de depuración es la misma que para el diseño de algoritmos: siempre y cuando dividas bien el misterio por la mitad, no tendrás que dividirlo muchas veces y depurarás rápidamente. Pero, ¿cuál es la mitad de un misterio? Aquí es donde entra la verdadera creatividad y experiencia.

Para un principiante real, el espacio de todos los posibles errores parece abarcar cada línea del código fuente. No tienes la visión que desarrollarás más adelante para ver las otras dimensiones del programa, como el espacio de las líneas ejecutadas, la estructura de datos, la gestión de memoria, la interacción con el código externo, el código riesgoso y el código simple. Para el programador experimentado, estas otras dimensiones forman un modelo mental imperfecto pero muy útil de todas las cosas que pueden salir mal. Contar con ese modelo mental es lo que ayuda a encontrar efectivamente el punto medio del misterio.

Una vez que hayas subdividido equitativamente el espacio de todo lo que puede salir mal, debes tratar de decidir en qué espacio se encuentra el error. En el caso sencillo en el que el misterio es: "¿Qué línea desconocida hace que mi programa se bloquee?", puedes preguntarte: "¿Se ejecuta la línea desconocida antes o después de esta línea que juzgo que se ejecuta en el medio del programa en ejecución?" Por lo general, no tendrás la suerte de saber que el error existe en una sola línea, o incluso en un solo bloque. A menudo, el misterio será más como: "O bien hay un puntero en ese gráfico que apunta al nodo incorrecto, o mi algoritmo que suma las variables en ese gráfico no funciona". En ese caso, es posible que debas escribir un pequeño programa para verificar que los punteros en el gráfico sean correctos y así decidir qué parte del misterio subdividido se puede eliminar.

Siguiente [¿Cómo eliminar un error?](03-How-to-Remove-an-Error.md)
9 changes: 9 additions & 0 deletions es/1-Beginner/Personal-Skills/03-How-to-Remove-an-Error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ¿Cómo eliminar un error?
[//]: # (Version:1.0.0)
He separado intencionalmente el acto de examinar la ejecución de un programa del acto de corregir un error. Pero, por supuesto, depurar también significa eliminar el error. Idealmente, tendrás un entendimiento perfecto del código y llegarás a un momento de "¡Ajá!" donde verás perfectamente el error y cómo solucionarlo. Pero dado que tu programa a menudo utilizará sistemas insuficientemente documentados en los que no tienes visibilidad, esto no siempre es posible. En otros casos, el código es tan complicado que tu comprensión no puede ser perfecta.

Al corregir un error, quieres hacer el cambio más pequeño que solucione el error. Puedes notar otras cosas que necesitan mejoras, pero no las corrijas al mismo tiempo. Intenta emplear el método científico de cambiar solo una cosa a la vez. El mejor proceso para esto es poder reproducir fácilmente el error, luego implementar tu corrección y volver a ejecutar el programa para observar que el error ya no existe. Por supuesto, a veces es necesario cambiar más de una línea, pero aún así debes aplicar conceptualmente un cambio único y atómico para corregir el error.

A veces, hay varios errores que parecen ser uno solo. Depende de ti definir los errores y corregirlos uno a la vez. En ocasiones, no está claro qué debería hacer el programa o cuál era la intención del autor original. En este caso, debes ejercitar tu experiencia y juicio, asignar tu propio significado al código. Decide qué debería hacer y coméntalo o acláralo de alguna manera, luego haz que el código se ajuste a tu interpretación. Esta es una habilidad intermedia o avanzada que a veces es más difícil que escribir la función original en primer lugar, pero el mundo real a menudo es complicado. Puedes tener que corregir un sistema que no puedes reescribir.

Siguiente [¿Cómo depurar utilizando un registro (Log)?](04-How-to-Debug-Using-a-Log.md)
13 changes: 13 additions & 0 deletions es/1-Beginner/Personal-Skills/04-How-to-Debug-Using-a-Log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ¿Cómo depurar utilizando un registro (Log)?
[//]: # (Version:1.0.0)
*Registro* es la práctica de escribir un sistema de manera que produzca una secuencia de registros informativos, llamada un registro. *Printlining* es simplemente producir un registro simple, generalmente temporal. Los principiantes absolutos deben comprender y utilizar registros porque su conocimiento de programación es limitado; los arquitectos del sistema deben comprender y utilizar registros debido a la complejidad del sistema. La cantidad de información proporcionada por el registro debería ser configurable, idealmente mientras el programa se está ejecutando. En general, los registros ofrecen tres ventajas básicas:

- Los logs pueden proporcionar información útil sobre errores que son difíciles de reproducir, como aquellos que ocurren en el entorno de producción pero que no pueden reproducirse en el entorno de prueba.
- Los logs pueden proporcionar estadísticas y datos relevantes para el rendimiento, como el tiempo transcurrido entre declaraciones.
- Cuando son configurables, los logs permiten capturar información general para depurar problemas específicos no anticipados sin tener que modificar y/o volver a implementar el código solo para abordar esos problemas específicos.

La cantidad de información que se incluye en el log es siempre un compromiso entre la información y la concisión. Demasiada información hace que el log sea costoso y produce una *ceguera al desplazamiento*, dificultando encontrar la información necesaria. Muy poca información puede hacer que no contenga lo necesario. Por esta razón, hacer configurable lo que se produce en el log es muy útil. Típicamente, cada registro en el log identificará su posición en el código fuente, el hilo que lo ejecutó si es aplicable, el tiempo exacto de ejecución y, comúnmente, una pieza adicional de información útil, como el valor de alguna variable, la cantidad de memoria libre, el número de objetos de datos, etc. Estas declaraciones de log están distribuidas por todo el código fuente, especialmente en los puntos de funcionalidad principales y alrededor del código riesgoso. Cada declaración puede recibir un nivel y solo producirá un registro si el sistema está configurado actualmente para producir ese nivel. Debe diseñar las declaraciones de log para abordar problemas que anticipa. Anticipe la necesidad de medir el rendimiento.

Si tiene un log permanente, la impresión temporal ahora se puede hacer en términos de los registros del log, y algunas de las declaraciones de depuración probablemente se agregarán permanentemente al sistema de registro.

Siguiente [¿Cómo entender problemas de rendimiento?](05-How-to-Understand-Performance-Problems.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# ¿Cómo entender problemas de rendimiento?
[//]: # (Version:1.0.0)
Aprender a entender el rendimiento de un sistema en ejecución es inevitable por la misma razón que aprender a depurar. Incluso si comprendes perfectamente el costo preciso del código que escribes, tu código hará llamadas a otros sistemas de software sobre los que tienes poco control o visibilidad. Sin embargo, en la práctica, los problemas de rendimiento son un poco diferentes y un poco más fáciles que la depuración en general.

Supongamos que tú o tus clientes consideran que un sistema o un subsistema es demasiado lento. Antes de intentar acelerarlo, debes construir un modelo mental de por qué es lento. Para hacer esto, puedes utilizar una herramienta de perfilado o un buen registro para descubrir dónde se está gastando realmente el tiempo u otros recursos. Existe un famoso dicho que establece que el 90% del tiempo se gastará en el 10% del código. Añadiría a eso la importancia del gasto de entrada/salida (E/S) en los problemas de rendimiento. A menudo, la mayor parte del tiempo se gasta de alguna manera en la E/S. Encontrar la E/S costosa y el 10% costoso del código es un buen primer paso para construir tu modelo mental.

Hay muchas dimensiones para medir el rendimiento de un sistema informático y muchos recursos consumidos. El primer recurso a medir es el tiempo del reloj de pared, el tiempo total que pasa para la computación. Registrar el tiempo del reloj de pared es particularmente valioso porque puede informar sobre circunstancias impredecibles que surgen en situaciones donde otro perfilado es impracticable. Sin embargo, esto no siempre representa toda la imagen. A veces, algo que tarda un poco más pero no consume tantos segundos del procesador será mucho mejor en el entorno informático con el que realmente tienes que lidiar. De manera similar, la memoria, el ancho de banda de red, el acceso a la base de datos u otros servidores pueden, al final, ser mucho más costosos que los segundos del procesador.

La competencia por recursos compartidos que están sincronizados puede causar bloqueo y privación. El bloqueo es la imposibilidad de avanzar debido a una sincronización incorrecta o demandas de recursos. La privación es la incapacidad para programar adecuadamente un componente. Si se puede anticipar de alguna manera, es mejor tener una forma de medir esta competencia desde el inicio de tu proyecto. Incluso si esta competencia no ocurre, es muy útil poder afirmar eso con confianza.

Siguiente [¿Cómo solucionar problemas de rendimiento?](06-How-to-Fix-Performance-Problems.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ¿Cómo solucionar problemas de rendimiento?
[//]: # (Version:1.0.0)
La mayoría de los proyectos de software pueden acelerarse de 10 a 100 veces con relativamente poco esfuerzo en comparación con la velocidad que tienen al momento de su lanzamiento inicial. Bajo la presión del tiempo de llegada al mercado, es sabio y efectivo elegir una solución que haga el trabajo de manera simple y rápida, aunque menos eficientemente que alguna otra solución. Sin embargo, el rendimiento es parte de la usabilidad y a menudo debe considerarse más cuidadosamente en algún momento.

La clave para mejorar el rendimiento de un sistema muy complicado es analizarlo lo suficientemente bien como para encontrar los *cuellos de botella*, o los lugares donde se consumen la mayoría de los recursos. No tiene mucho sentido optimizar una función que representa solo el 1% del tiempo de computación. Como regla general, debe pensarlo detenidamente antes de hacer cualquier cosa a menos que piense que hará que el sistema o una parte significativa de él sea al menos el doble de rápido. Por lo general, hay una manera de hacerlo. Considere el esfuerzo de prueba y aseguramiento de la calidad que requerirá su cambio. Cada cambio conlleva una carga de prueba, por lo que es mucho mejor tener algunos cambios importantes.

Después de haber logrado una mejora del doble en algo, es necesario al menos reconsiderar y tal vez volver a analizar para descubrir el siguiente cuello de botella más costoso en el sistema y abordarlo para obtener otra mejora del doble.

A menudo, los cuellos de botella en el rendimiento son un ejemplo de contar vacas contando patas y dividiendo por cuatro, en lugar de contar cabezas. Por ejemplo, he cometido errores como no proporcionar a un sistema de base de datos relacional un índice adecuado en una columna que consulto con frecuencia, lo que probablemente lo hizo al menos 20 veces más lento. Otros ejemplos incluyen realizar E/S innecesaria en bucles internos, dejar declaraciones de depuración que ya no son necesarias, asignación de memoria innecesaria y, en particular, el uso inexperto de bibliotecas y otros subsistemas que a menudo están mal documentados en cuanto al rendimiento. Este tipo de mejora a veces se llama *fruto de bajo hanging*, lo que significa que se puede recoger fácilmente para proporcionar algún beneficio.

¿Qué haces cuando comienzas a quedarte sin "fruto de bajo colgado"? Bueno, puedes alcanzar más alto o derribar el árbol. Puedes seguir haciendo pequeñas mejoras o puedes rediseñar seriamente un sistema o un subsistema. (Esta es una gran oportunidad para usar tus habilidades como buen programador, no solo en el nuevo diseño sino también en convencer a tu jefe de que es una buena idea). Sin embargo, antes de argumentar a favor del rediseño de un subsistema, debes preguntarte si tu propuesta lo mejorará cinco a diez veces.

Siguiente [¿Cómo optimizar bucles?](07-How-to-Optimize-Loops.md)
15 changes: 15 additions & 0 deletions es/1-Beginner/Personal-Skills/07-How-to-Optimize-Loops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ¿Cómo optimizar bucles?
[//]: # (Version:1.0.0)
En ocasiones, te encontrarás con bucles o funciones recursivas que tardan mucho tiempo en ejecutarse y son cuellos de botella en tu producto. Antes de intentar hacer que el bucle sea un poco más rápido, tómate unos minutos para considerar si hay alguna manera de eliminarlo por completo. ¿Podría funcionar con un algoritmo diferente? ¿Podrías calcular eso mientras calculas algo más? Si no encuentras una forma de evitarlo, entonces puedes optimizar el bucle. Esto es simple; mueve cosas hacia afuera. Al final, esto requerirá no solo ingenio sino también una comprensión del costo de cada tipo de declaración y expresión. Aquí tienes algunas sugerencias:

- Elimina operaciones de punto flotante.
- No asignes bloques de memoria nuevos innecesariamente.
- Combina constantes.
- Mueve la entrada/salida (I/O) a un búfer.
- Evita las divisiones.
- Evita las conversiones de tipo costosas.
- Muévete con un puntero en lugar de recalcular índices.

El costo de cada una de estas operaciones depende de tu sistema específico. En algunos sistemas, los compiladores y el hardware realizan estas acciones por ti. Un código claro y eficiente es mejor que un código que requiere entender una plataforma particular.

Siguiente [¿Cómo manejar el costo de la entrada/salida (E/S)?](08-How-to-Deal-with-IO-Expense.md)
Loading