--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/programming-guidelines.xml Thu Sep 07 16:46:51 2006 -0400
@@ -0,0 +1,2120 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "/usr/share/sgml/docbook/dtd/xml/4.1.2/docbookx.dtd" [
+<!ENTITY Emacs "<application>Emacs</application>">
+<!ENTITY Vim "<application>Vim</application>">
+<!ENTITY ChangeLog "<filename>ChangeLog</filename>">
+]>
+
+
+<article class="techreport" id="index" lang="es">
+
+ <articleinfo>
+ <title>Guía de programación de GNOME</title>
+
+ <authorgroup>
+ <author>
+ <firstname>Federico</firstname>
+ <surname>Mena Quintero</surname>
+ <affiliation>
+ <address>
+ <email>federico@gnu.org</email>
+ </address>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Miguel</firstname>
+ <surname>de Icaza</surname>
+ <affiliation>
+ <address>
+ <email>miguel@kernel.org</email>
+ </address>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Morten</firstname>
+ <surname>Welinder</surname>
+ <affiliation>
+ <address>
+ <email>terra@diku.dk</email>
+ </address>
+ </affiliation>
+ </author>
+ <othercredit>
+ <firstname>Germán</firstname>
+ <surname>Poó Caamaño</surname>
+ <contrib>Traducción al español</contrib>
+ <affiliation>
+ <address>
+ <email>gpoo@ubiobio.cl</email>
+ </address>
+ </affiliation>
+ </othercredit>
+ </authorgroup>
+ <copyright>
+ <year>2000</year>
+ <holder>The Free Software Foundation</holder>
+ </copyright>
+ <copyright>
+ <year>2004</year>
+ <holder>GNOME Foundation, respecto de la versión en español.</holder>
+ </copyright>
+
+ <abstract>
+ <para>
+ Este artículo contiene varías guías y sugerencias para los
+ programadores de GNOME, así como ciertas políticas que
+ deberían seguirse cuando se escriben programas para GNOME.
+ Es un intento para que los programadores puedan aprender
+ acerca del proceso de desarrollo de GNOME y su filosofía.
+ GNOME es un esfuerzo de equipo, así que será útil para
+ que los programadores sepan «la forma de hacer la
+ cosas».
+ </para>
+ </abstract>
+ </articleinfo>
+
+ <!-- Introduction -->
+
+ <sect1 id="intro">
+ <title>Introducción</title>
+
+ <para>
+ GTK+, la biblioteca de interfaz de usuario básica de GNOME, nos
+ ha enseñado algunas lecciones importantes en el diseño de software.
+ El código de GTK+ es limpio, consistente, mantenible y tiene
+ sentido. Tal código no sólo provoca placer al trabajar con el,
+ sino que además es un incentivo para las buenas prácticas de
+ programación para aquellos que quieran extenderlo y modificarlo.
+ </para>
+
+ <para>
+ En este artículo intentamos presentar algunas sugerencias y
+ guías que debería tener en cuenta cuando escriba código para
+ el proyecto GNOME. Presentamos algunas de las políticas
+ que deben seguirse cuando se modifica el código de otras
+ personas, usando el repositorio CVS y asegurándose de que su
+ código se ajusta para ser incluído en GNOME. También
+ presentamos información que será útil para los mantenedores
+ de paquetes.
+ </para>
+
+ <para>
+ Además de este documento, asegúrese de leer los Estándares de
+ Programación de GNU. Estos se encuentran disponibles en el
+ nodo indo <filename>(Standards)</filename> en la documentación
+ estándar de GNU.
+ </para>
+ </sect1>
+
+ <!-- The Importance of Writing Good Code -->
+
+ <sect1 id="good-code">
+ <title>La importancia de escribir buen código</title>
+
+ <para>
+ GNOME es un proyecto de software libre muy ambicioso y, como tal,
+ está compuesto por muchos paquetes de software que son más o menos
+ independientes el uno del otro. Mucho del trabajo en GNOME lo
+ realizan voluntarios; programadores que vienen y se van
+ en cualquier momento y que serán capaces de dedicar
+ diferentes cantidades de tiempo al proyecto GNOME.
+ Muchas personas trabajan en software libre en su tiempo libre o
+ como un pasatiempo, así, si sus responsabilidades del «mundo
+ real» cambian, se verá reflejado en la cantidad de trabajo que
+ dedicarán a proyectos de software libre.
+ </para>
+
+ <para>
+ Se tarda mucho tiempo en escribir software y supone una
+ gran cantidad de trabajo. Es por esto que muchos
+ de los voluntarios de tiempo parcial no pueden comenzar
+ grandes proyectos por sí mismos; es mucho más fácil y
+ gratificante contribuir a proyectos existentes, puesto que
+ los resultados son inmediatamente visibles y usables.
+ </para>
+
+ <para>
+ Teniendo esto en cuenta y el hecho que los programadores de
+ software libre tiene recursos escasos, concluimos que
+ para los proyectos existentes es muy importante facilitar,
+ tanto como sea posible, que otras personas puedan contribuir.
+ Una forma de hacerlo es asegurándose de que los programas
+ sean fáciles de leer, entender y modificar.
+ </para>
+
+ <para>
+ El código desordenado es difícil de leer y las personas pueden
+ perder interés si no son capaces de descifrar lo que el código
+ intenta hacer. Además, es importante que los programadores sean
+ capaces de entender el código rápidamente, y así poder comenzar
+ a contribuir reparando fallos y extendiéndolo en un período breve
+ de tiempo. El código fuente es una forma de comunicación, y así
+ como a alguien podría no querer leer una novela con errores
+ ortográficos y mala puntuación, los programadores deben intentar
+ escribir buen código de tal forma que sea fácil de entender y
+ modificar por otros.
+ </para>
+
+ <para>
+ Existen algunas cualidades que son importantes en un buen
+ código y por qué son importantes para los desarrolladores
+ de software libre:
+
+ <variablelist>
+ <varlistentry>
+ <term>Limpieza</term>
+ <listitem>
+ <para>
+ Un código limpio es fácil de leer; permite a las
+ personas leerlo con un mínimo esfuerzo y así pueden
+ entenderlo más fácilmente.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Consistencia</term>
+ <listitem>
+ <para>
+ El código consistente permite más fácilmente que las
+ personas entiendan como funciona el programa; cuando se
+ lee código consistente, subconcientemente uno se forma
+ una número de supuestos y expectativas acerca del
+ funcionamiento del código, de esta forma es más fácil
+ y seguro realizarle modificaciones.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Extensibilidad</term>
+ <listitem>
+ <para>
+ El código de propósito general es más fácil de reutilizar
+ y modificar que el código demasiado específico con muchos
+ supuestos escritos directamente en el código (hardcoded).
+ Cuando alguien desea agregar una nueva características
+ a un programa, obviamente será más fácil hacerlo si el
+ código fue diseñado para ser extensible desde el inicio.
+ El código que no fue escrito de esta forma hará que las
+ personas deban implementar hacks muy feos para poder
+ añadir características.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Corrección</term>
+ <listitem>
+ <para>
+ Finalmente, el código diseñado debe ser correcto para
+ que las personas pierdan menos tiempo preocupándose de
+ los errores y se ocupen en extender las
+ características de un programa. Los usuarios también
+ apreciarán un código correcto, ya que a nadie le gusta
+ que un programa se caiga.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ En resumen, los programadores a menudo contribuyen en
+ su tiempo libre a proyectos de software libre, y aún quienes
+ contribuyen de forma regular pueden detenerse en cualquier
+ instante del tiempo, así que es muy importante que el código
+ sea bueno y les permita modificarlo facilmente. El resultado
+ final será un mejor software al que los programadores
+ querrán extender.
+ </para>
+ </sect1>
+
+ <!-- Coding Style -->
+
+ <sect1 id="code-style">
+ <title>Estilo de programación</title>
+
+ <para>
+ «El estilo de programación» se refiere a la forma en
+ que se da formato al código fuente. Para C, esto involucra
+ la forma en que se ubican las llaves, se indenta el código y
+ se utilizan los paréntesis. GNOME tiene una mezcla de estilos
+ de programación y no obligamos el uso de ninguno de ellos. Lo más
+ importante es que el código sea consistente dentro de un programa
+ o una biblioteca --- el código con un formato desordenado
+ no es aceptable debido a que es difícil de leer.
+ </para>
+
+ <para>
+ Cuando se escribe un nuevo programa o biblioteca, siga un
+ estilo consistente de ubicación de llaves y de indentación.
+ Si no tiene ninguna preferencia personal de estilo,
+ recomendamos el estilo de programación del núcleo de Linux o
+ el estilo de programación de GNU.
+ </para>
+
+ <para>
+ Lea el nodo de info <filename>(Standards)Writing C</filename>
+ en la documentación de GNU. Luego, obtenga el código fuente
+ de Linux y lea el archivo
+ <filename>linux/Documentation/CodingStyle</filename>, e
+ ignore los chistes de Linus. Estos dos documentos le darán
+ una buena idea de nuestras recomendaciones para el código de
+ GNOME.
+ </para>
+
+ <!-- Indentation Style -->
+
+ <sect2 id="indent">
+ <title>Estilo de indentación</title>
+
+ <para>
+ Para el código del núcleo de GNOME preferimos el estilo
+ de indentación del núcleo de Linux. Use tabuladores
+ de 8 espacios para la indentación.
+ </para>
+
+ <para>
+ Usar tabuladores de 8 espacios para indentación proporciona
+ un número de beneficios. Permite que el código sea más
+ fácil de leer, ya que la indentación se marca claramente.
+ También ayuda a mantener su código ordenado
+ forzando a dividir funciones en trozos más modulares y
+ bien definidos --- si la indentación va más allá del
+ margen derecho, significa que la función está mal
+ diseñada y que debiera dividirse para hacerla más modular
+ o bien, repensarla.
+ </para>
+
+ <para>
+ Los tabuladores de 8 espacios para indentación también
+ ayudan al diseño de funciones que encajen bien en la pantalla,
+ lo cual significa que las personas puedan entender el código
+ sin tener que desplazarse atrás y adelantes para entenderlo.
+ </para>
+
+ <para>
+ Si usa &Emacs;, entonces puedes seleccionar el estilo de
+ indentación del núcleo de Linux incluyendo en el
+ archivo <filename>.emacs</filename> lo siguiente:
+
+ <programlisting>
+(add-hook 'c-mode-common-hook
+ (lambda ()
+ (c-set-style "k&r")
+ (setq c-basic-offset 8)))
+ </programlisting>
+
+ En los nuevos Emacs o con el nuevo cc-mode, puedes ser capaz
+ de hacerlo más simple con:
+
+ <programlisting>
+(add-hook 'c-mode-common-hook
+ (lambda ()
+ (c-set-style "linux")))
+ </programlisting>
+ </para>
+
+ <para>
+ El estilo de indentación de GNU es el predeterminado para
+ &Emacs;, así que no es necesario agregar nada en el
+ archivo <filename>.emacs</filename> para habilitarlo.
+ Si desea seleccionarlo explícitamente, sustituya
+ «gnu» por «linux» en el ejemplo
+ anterior.
+ </para>
+
+ <para>
+ Si usa &Vim;, entonces puede seleccionar el estilo
+ de indentación del núcleo de Linux incluyendo el
+ siguiente fragmento en el
+ archivo <filename>.vimrc</filename>:
+
+ <programlisting>
+set ts=8
+if !exists("autocommands_loaded")
+ let autocommands_loaded = 1
+ augroup C
+ autocmd BufRead *.c set cindent
+ augroup END
+endif
+ </programlisting>
+ </para>
+
+ <para>
+ Como alternativa puede seleccionar el estilo de
+ indentación de GNU en &Vim; usando lo siguiente en
+ el archivo <filename>.vimrc</filename>:
+ <footnote>
+ <para>
+ Gracias a Tomas Ögren por proporcionar este código.
+ </para>
+ </footnote>:
+
+ <programlisting>
+augroup C
+ autocmd BufRead *.c set cinoptions={.5s,:.5s,+.5s,t0,g0,^-2,e-2,n-2,p2s,(0,=.5s formatoptions=croql cindent shiftwidth=4 tabstop=8
+augroup END
+ </programlisting>
+ </para>
+
+ <note>
+ <para>
+ Si sabe personalizar el estilo de indentación en otros
+ editores populares, por favor háganoslo saber y así podemos
+ expandir este documento.
+ </para>
+ </note>
+ </sect2>
+
+ <!-- Naming Conventions -->
+
+ <sect2 id="naming">
+ <title>Convenciones de nombres</title>
+
+ <para>
+ Es importante seguir una buena convención de nombres para
+ los símbolos de los programas. Es específicamente
+ importante para las bibliotecas, ya que no debería
+ ensuciarse el espacio de nombres global --- es muy
+ molesto cuando una biblioteca tiene símbolos nombrados
+ desordenadamente que chocan con nombres que pueda
+ querer usar en sus programas.
+ </para>
+
+ <para>
+ Los nombres de las funciones deberían ser de la forma
+ <function>modulo_submodulo_operacion</function>, por ejemplo,
+ <function>gnome_canvas_set_scroll_region</function> o
+ <function>gnome_mime_get_keys</function>. Esta convención
+ elimina las colisiones de nombres de símbolos entre módulos.
+ Es muy importante para las bibliotecas.
+ </para>
+
+ <para>
+ Los símbolos deben tener nombres descriptivos. Como Linus
+ dice, no use <function>cntusr()</function>, sino que use
+ <function>count_active_users()</function>. Esto permite
+ que el código sea más fácil de leer y casi se auto
+ documenta.
+ </para>
+
+ <para>
+ Intente usar las mismas convenciones de nombre que tienen
+ GTK+ y las bibliotecas de GNOME:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Los nombres de las funciones en minúsculas, con líneas
+ de subrayado para separar palabras, tal como:
+ <function>gnome_canvas_set_scroll_region()</function>,
+ <function>gnome_mime_get_keys()</function>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Las macros y las enumeraciones en mayúsculas, con líneas
+ de subrayado para separar palabras, tal como:
+ <symbol>GNOMEUIINFO_SUBTREE()</symbol> para una macro y
+ <symbol>GNOME_INTERACT_NONE</symbol> para un valor
+ enumerado.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Los nombres de tipos y estructuras usan una mezcla de
+ mayúsculas y minúsculas, tal como:
+ <symbol>GnomeCanvasItem</symbol>,
+ <symbol>GnomeIconList</symbol>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ Al utilizar líneas de subrayado para separar palabras el
+ código estará menos apretado y facilita la edición, ya
+ que puede usar las secuencias de teclas que permiten
+ navegar entre palabras más rápidamente en cualquier editor.
+ </para>
+
+ <para>
+ Si está escribiendo una biblioteca, entonces puede necesitar
+ exportar símbolos que serán usados sólo dentro de la
+ biblioteca. Por ejemplo, dos de los archivos objeto que
+ componen la biblioteca <filename>libfoo.so</filename> pueden
+ requerir acceder a símbolos ubicados en el otro archivo,
+ pero se tiene la intención que éstos símbolos sean
+ utilizados desde los programas de usuario. En este caso,
+ coloque una línea de subrayado antes del nombre de la
+ función y haga que la primera palabra siga la convención
+ estándar módulo/submódulo. Por ejemplo, podría tener
+ una función llamada
+ <function>_foo_internal_frobnicate()</function>.
+ </para>
+
+ <!-- Consistency in Naming -->
+
+ <sect3 id="consist">
+ <title>Consistencia entre nombres</title>
+
+ <para>
+ Es importante que las variables se nombren de manera
+ consistente. Por ejemplo, un módulo que manipula una
+ lista puede elegir nombrar las variables que mantienen
+ un puntero a la lista como «<symbol>l</symbol>»,
+ por elegancia y simplicidad. Sin embargo, es importante que
+ un módulo que manipula widgets y tamaños no use variables
+ llamadas «<symbol>w</symbol>» tanto para
+ widgets y anchos («width») (como en valores de ancho/alto =>
+ width/height); esto podría hacer que el código sea inconsistente
+ y difícil de leer.
+ </para>
+
+ <para>
+ Por supuesto, nombre muy cortos y elegantes solamente deberían
+ ser usados para variables locales de funciones.
+ Nunca llame una variable global «<symbol>x</symbol>»; use
+ un nombre más largo que indique lo que significa.
+ </para>
+ </sect3>
+ </sect2>
+
+ <!-- Cleanliness -->
+
+ <sect2 id="clean">
+ <title>Limpieza</title>
+
+ <para>
+ El código de GNOME debe ser tan limpio como sea posible.
+ Esto implica usar un estilo de indentación consistente
+ y una buena convención para nombrar símbolos, como se
+ ha indicado anteriormente. Esto también implica lo
+ siguiente.
+ </para>
+
+ <para>
+ Aprender el uso correcto de la palabra reservada
+ <symbol>static</symbol>.
+ <emphasis>No</emphasis> declarar todos los símbolos como
+ globales. Esto tiene la ventaja de que puede usar nombres
+ más cortos dentro de las funciones en un sólo archivo
+ fuente, ya que no son globalmente visibles y por
+ consiguiente no necesita emplear el prefijo
+ módulo/submódulo.
+ </para>
+
+ <para>
+ Aprenda el uso correcto de la palabra reservada
+ <symbol>const</symbol>. Úsela consistentemente,
+ así le permitirá al compilador que atrape muchos
+ errores estúpidos.
+ </para>
+
+ <para>
+ Si tiene una función que retorna un puntero a
+ un dato interno que se supone que el usuario
+ no debe liberar, debería usar el modificador
+ const. Este avisará al usuario si intenta
+ hacer alguna operación incorrecta, por ejemplo:
+
+ <programlisting>
+const char *gnome_mime_get_info (const char *info);
+ </programlisting>
+
+ El compilador avisará si el usuario intenta liberar
+ la cadena retornada. Esto puede atrapar muchos
+ errores.
+ </para>
+
+ <para>
+ Si tiene «valores mágicos» en el programa o
+ biblioteca, use macros que los definan en vez de usarlos
+ directamente en el código:
+
+ <programlisting>
+/* Amount of padding for GUI elements */
+#define GNOME_PAD 8
+#define GNOME_PAD_SMALL 4
+#define GNOME_PAD_BIG 12
+ </programlisting>
+ </para>
+
+ <para>
+ Si tiene una lista de valores posibles para una variable,
+ no use macros para ellas, use enum para darle
+ un nombre de tipo --- esto permite disponer de nombres
+ simbólicos en un depurador. Además, no use
+ «int» para almacenar un valor enumerado; use
+ el tipo enum. Esto le permite al compilador atrapar
+ los errores por usted, permitiéndole al depurador mostrar los
+ valores apropiados y hacer obvios los valores que una
+ variable puede tomar. A continuación un
+ ejemplo:
+
+ <programlisting>
+/* Shadow types */
+typedef enum {
+ GTK_SHADOW_NONE,
+ GTK_SHADOW_IN,
+ GTK_SHADOW_OUT,
+ GTK_SHADOW_ETCHED_IN,
+ GTK_SHADOW_ETCHED_OUT
+} GtkShadowType;
+
+void gtk_frame_set_shadow_type (GtkFrame *frame, GtkShadowType type);
+ </programlisting>
+ </para>
+
+ <para>
+ Si define un conjunto de valores para un campo de bits, haga
+ lo siguiente:
+
+ <programlisting>
+<![CDATA[
+/* Update flags for items */
+enum {
+ GNOME_CANVAS_UPDATE_REQUESTED = 1 << 0,
+ GNOME_CANVAS_UPDATE_AFFINE = 1 << 1,
+ GNOME_CANVAS_UPDATE_CLIP = 1 << 2,
+ GNOME_CANVAS_UPDATE_VISIBILITY = 1 << 3,
+ GNOME_CANVAS_UPDATE_IS_VISIBLE = 1 << 4
+};]]>
+ </programlisting>
+
+ Esto hace más fácil modificar la lista de valores y menos
+ propenso a error que especificando los valores a mano. También
+ permite usar estos valores como símbolos en un depurador.
+ </para>
+
+ <para>
+ No escriba código ofuscado, intente que sea espartano.
+ Para clarificar una expresión, no use más paréntesis que
+ los necesarios. Use espacios antes de los paréntesis y
+ después de las comas y también alrededor de los operadores
+ binarios.
+ </para>
+
+ <para>
+ No coloque hacks en el código. En vez de escribir un
+ hack feo, reescriba el código para que quede limpio,
+ extensible y mantenible.
+ </para>
+
+ <para>
+ Asegúrese de que el código compila absolutamente sin ningún
+ aviso del compilador. Esto le ayudará a atrapar errores
+ estúpidos. Use los prototipos de las funciones en los
+ archivos de encabezados de forma consistente.
+ </para>
+
+ <para>
+ Dentro de GNOME puede usar la macro de Autoconf
+ <symbol>GNOME_COMPILE_WARNINGS</symbol> en el archivo
+ <filename>configure.in</filename>. Esto permitirá contar
+ con un buen conjunto de avisos del compilador de una manera
+ portable.
+ </para>
+
+ <para>
+ Comente el código. Coloque comentarios antes de
+ cada función para decir que hace. No diga cómo lo hace
+ a menos que sea absolutamente necesario; debería ser
+ obvio al leer el código. Si no lo fuera, entonces
+ pueda desear reescribirla hasta que sea fácil de
+ entender.
+ </para>
+
+ <para>
+ Cuando documente las funciones de la API de una biblioteca,
+ siga las directrices indicadas en el archivo
+ <filename>gnome-libs/devel-docs/api-comment-style.txt</filename>.
+ Esto permite que el código fuente pueda proporcionar documentación
+ en línea, que posteriormente se extrae mediante el sistema
+ <application>gtk-doc</application> para crear un manual DocBook
+ de forma automática.
+ </para>
+
+ <!-- Portability considerations -->
+
+ <sect3 id="portability">
+ <title>Consideraciones de portabilidad</title>
+
+ <para>
+ Se construye GNOME en muchas plataformas diferentes.
+ Se puede asumir que serán plataformas más o menos tipo Unix;
+ hasta el momento GNOME no ha sido portado a sistema no-Unix,
+ así que se puede asumir que los servicios estándar de
+ Unix estarán disponibles.<footnote>
+ <para>
+ ¿Servicios estándar de Unix? Por supuesto que estamos
+ bromeando.
+ </para>
+ </footnote>
+ </para>
+
+ <para>
+ Recuerde que el mundo no es su propio equipo con GNU/Linux;
+ las gente realmente usa otros tipos de máquinas.
+ </para>
+
+ <para>
+ Intente no usar extensiones específicas de
+ <application>GCC</application> debido a que éstas no
+ funcionarán con otros compiladores. Si realmente debe
+ hacer uso de tal cosa, vea la forma en que se hace
+ en <application>Glib</application> con el conjunto de
+ macros G_GNUC; asegúrese también de incluir código
+ que funcione con compiladores ISO C. Si sólo tiene
+ disponible <application>GCC</application>, aprenda a usar
+ las opciones <option>-ansi -pedantic</option> que
+ permiten probar código sospechoso.
+ </para>
+
+ <para>
+ Recuerde que algunas plataformas no disponen de
+ <application>GCC</application> o que
+ <application>GDB</application> puede ser inusable en ellos,
+ y se querrán usar otros compiladores y
+ depuradores.
+ </para>
+ </sect3>
+
+ <!-- GTK+-related Issues -->
+
+ <sect3 id="gtk">
+ <title>Tópicos relacionados con GTK+</title>
+
+ <para>
+ GTK+ permite hacer mucha magia y ofuscación con manipuladores
+ de señas, pasar cerraduras y conjuntos de datos. Si se
+ encuentra hadiendo muchos
+ <symbol>gtk_object_set_data()</symbol> en un mismo lugar,
+ o pasado estados de forma extraña a través de manejadores de
+ señales, reescriba el código. Si necesita adjuntar muchos
+ datos a un objeto en particular, entonces es un buen candidato
+ para una nueva clase derivada, que no sólo hará al código
+ más limpio, sino que también lo hará más extensible.
+ </para>
+
+ <para>
+ Mucha de la heurística en manejadores de eventos complicadas
+ a menudo se pueden reemplazar limpiando el código a través
+ de una máquina de estados. Esto es útil cuando se quieren
+ implementar cosas truculentas como selección y comportamientos
+ de arrastrado, y hará al código más fácil de depurar y extender.
+ </para>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <!-- Correctness and Robustness -->
+
+ <sect1 id="robust">
+ <title>Corrección y robustez</title>
+
+ <para>
+ Es extremadamente importante que el código de GNOME sea
+ correcto y robusto. Esto significa que el código debería hacer
+ lo que se espera que haga, y debería manejar bien las condiciones
+ de excepción. Aunque esto pueda parecer obvio, esta sección
+ dará algunas ideas para asegurar la corrección de su código
+ de GNOME. Esto es muy importante, ya que los usuarios esperan
+ y merecen un software fiable que se ejecute correctamente
+ y que no se caiga.
+ </para>
+
+ <!-- Ensuring Consistency -->
+
+ <sect2 id="ensure">
+ <title>Cómo asegurar la consistencia</title>
+
+ <para>
+ <!-- FIXME: Buscar un mejor termino para "assertion" -->
+ Utilice las macros de aserción de Glib para asegurarse de
+ que el estado de un programa es consistente. Estas macros
+ ayudan a localizar errores muy rápidamente y se gastará
+ mucho menos tiempo en el depurado si se emplean de forma
+ generosa y consistente.
+ </para>
+
+ <para>
+ Inserte verificaciones de sanidad en el código en puntos
+ importantes como es el inicio de funciones públicas, al
+ final de código que realiza una búsqueda que siempre
+ debe ser exitosa y en cualquier lugar donde
+ el rango de valores calculados es importante.
+ </para>
+ </sect2>
+
+ <!-- Assertions and Preconditions -->
+
+ <sect2 id="assert">
+ <title>Aserciones y precondiciones</title>
+
+ <para>
+ Las aserciones y precondiciones ayudan a asegurar que
+ el estado de un programa es consistente. Glib proporciona
+ macros para colocar aserciones y precondiciones en el
+ código. Debería usarlas libremente; a cambio podrá
+ localizar errores muy rápidamente y ocupará menos tiempo
+ rastreando errores con el depurador.
+ </para>
+
+ <para>
+ Existen macros de Glib para precondiciones, las cuales
+ emiten un mensaje cuando una condición falla y retornan
+ de la función desde donde fueron llamadas. Debieran ser
+ usadas en el inicio de las funciones.
+
+ <variablelist>
+ <varlistentry>
+ <term><symbol>g_return_if_fail
+ (condición)</symbol></term>
+ <listitem>
+ <para>
+ Retorna desde la línea actual de la función si la
+ <symbol>condición</symbol> es falsa.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><symbol>g_return_val_if_fail (condición,
+ valor)</symbol></term>
+ <listitem>
+ <para>
+ Retorna el <symbol>valor</symbol> indicado desde
+ la función actual si la <symbol>condición</symbol>
+ es falsa.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ También existen macros para aserciones. Estas emitirán
+ un mensaje cuando una condición falle y llamará a la
+ función <function>abort(3)</function> para terminar el
+ programa. Debieran ser usadas para asegurarse la
+ consistencia para códigos internos.
+
+ <variablelist>
+ <varlistentry>
+ <term><symbol>g_assert (condición)</symbol></term>
+ <listitem>
+ <para>
+ Aborta el programa si la <symbol>condición</symbol>
+ es falsa.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><symbol>g_assert_not_reached ()</symbol></term>
+ <listitem>
+ <para>
+ Aborta el programa si se llama a la macro.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ Estas funciones debieran emplearse para imponer
+ precondiciones en el código y verificar su corrección
+ --- piense en ellas como verificaciones de sanidad
+ en los programas. Debiera usarlas libremente como
+ asistencia para atrapar los errores rápidamente; una
+ vez que el programa se encuentre completamente depurado,
+ puede compilarlo con estas macros deshabilitadas y así
+ evitar añadirle sobrecarga en el momento de ejecutarlos.
+ </para>
+
+ <para>
+ Las macros <symbol>g_return_*()</symbol> debieran
+ emplearse al inicio de las funciones públicas de las
+ bibliotecas, para asegurarse de que los argumentos que se pasan
+ a ellas sean correctos y tengan un rango válido. Si
+ una función no retorna valor (por ejemplo, retorna
+ <symbol>void</symbol>), debiera usar
+ <symbol>g_return_if_fail()</symbol>. En caso contrario,
+ debiera usar <symbol>g_return_val_if_fail()</symbol>
+ para retornar un valor «seguro». Cuando
+ se invoca una función de biblioteca que usa estas macros
+ con un argumento incorrecto , se producirá un
+ mensaje de error y continuará la ejecución. El
+ programa cliente podrá tener algún sobresalto, hacer
+ nada o caerse, pero al menos sabrá
+ <emphasis>dónde</emphasis> se le ha pasado un valor
+ incorrecto a la función.
+ </para>
+
+ <para>
+ La macro <symbol>g_assert()</symbol> debiera usarse para
+ asegurar la consistencia interna de una biblioteca o
+ programa. En vez de retornar de la función y continuar
+ la ejecución si la condición falla,
+ <symbol>g_assert()</symbol> producirá en mensaje de error
+ e inmediatamente abortará el programa. Esto es para
+ evitar que el programa continúe ejecutándose en un
+ estado inconsistente. Debiera usar esta macro para
+ asegurarse de que el programa o biblioteca está usando
+ valores internos sanos.
+ </para>
+
+ <para>
+ La macro <symbol>g_assert_not_reached()</symbol> se
+ usa para marcar el lugar en el código que nunca
+ debiera producirse. Por ejemplo, si tiene una
+ cláusula <symbol>switch</symbol> y piensa que maneja
+ todos los valores posibles en las etiquetas
+ <symbol>case</symbol>, entonces debiera colocar
+ <symbol>g_assert_not_reached()</symbol> en la
+ etiqueta <symbol>default</symbol> para asegurarse de que
+ el código nunca llegue allá (podría significar que
+ ha perdido algún valor o que el programa se encuentra
+ incorrecto).
+ </para>
+
+ <para>
+ Estas macros ayudan a encontrar errores más rápido
+ a través de avisos que se producen tan pronto como
+ el programa alcanza un estado incosistente. Úselos
+ frecuentemente y encontrará muchos errores más
+ fácilmente.
+ </para>
+ </sect2>
+
+ <!-- GTK+-related Issues -->
+
+ <sect2 id="assert-gtk">
+ <title>Tópicos relacionados con GTK+</title>
+
+ <para>
+ Sea cuidadoso cuando escriba manejadores de eventos
+ --- asegurése de que los eventos son manipuladas en
+ las situaciones apropiadas. Es necesario asegurarse de
+ que los manejadores de señales tengan los prototipos
+ correctos. Esto es muy importante. Recuerde que no
+ todos los prototipos de manejadores de señal se parecen
+ a lo siguiente:
+
+ <programlisting>
+static void my_handler (GtkWidget *widget, gpointer data);
+ </programlisting>
+
+ Por ejemplo, los manejadores de eventos tienen un parámetro
+ extra de evento y retornan <symbol>gint</symbol>. Vea los
+ archivos de encabezado de GTK+ cuando necesite verificarlo.
+ </para>
+
+ <para>
+ Asegúrese de que el programa trata de una forma apropiada
+ todas las acciones generadas por el usuario. Recuerde
+ que el usuario puede cerrar una ventana en cualquier
+ momento a través del administrador de ventanas; téngalo
+ presente y escriba el código necesario para manejar esta
+ situación.
+ </para>
+
+ <para>
+ Si verifica los modificadores de teclas con una máscara
+ de estado de eventos, por ejemplo,
+ <keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
+ haga esto:
+
+ <programlisting>
+ guint modifiers;
+
+ modifiers = gtk_accelerator_get_default_mod_mask ();
+
+ if (event->keysym == GDK_F10
+ && (event->state & modifiers) == GDK_CONTROL_MASK) {
+ do_something ();
+ }
+ </programlisting>
+
+ Esto es necesario; si en vez de lo anterior hace:
+
+ <programlisting>
+ if (event->keysym == GDK_F10 && event->state == GDK_CONTROL_MASK)
+ </programlisting>
+
+ entonces el programa no funcionará correctamente si el
+ usuario tiene, por ejemplo, activada la tecla
+ <keycap>NumLock</keycap> — <keycap>NumLock</keycap>
+ también es un modificador, y si está activado, entonces
+ la máscara de estado del evento no será como se espera
+ en el segundo ejemplo.
+ </para>
+
+ <!-- Visuals and Colormaps -->
+
+ <sect3 id="visuals">
+ <title>Vistas y mapas de color</title>
+
+ <para>
+ <!-- FIXME: Buscar un término adecuado para "Visual" en
+ vez de "vista" -->
+ Algunos usuarios utilizan tarjetas de vídeo avanzadas
+ (por ejemplo, SGIs y Suns) que soportan múltiples vistas
+ simúltaneamente. Una vista define la representación en memoria
+ que usa un dispositivo de hardware para almacenar los
+ contenidos de una imagen. Muchas tarjetas de vídeo de
+ PC soportan sólo una vista a la vez, pero el hardware
+ avanzado puede tener diferentes ventanas y pixmaps en
+ diferentes vistas simultáneamente.
+ </para>
+
+ <para>
+ Es importante entender las vistas y mapas de colores si
+ va a escribir código que crea ventanas y pixmaps por sus
+ propios medios, en vez de utilizar las funciones de alto
+ nivel como GnomeCanvas y GnomePixmap. Para mayor información,
+ lea el manual de programación de Xlib.
+ </para>
+
+ <para>
+ <!-- FIXME: traducir -->
+ In general, you just need to remember that the visual and
+ colormap for a drawable must match the ones of another
+ drawable if you want to copy an area from the first drawable
+ into the second one. If they are not the same, you will get
+ a BadMatch error from X and you application will most likely
+ abort.
+ </para>
+
+ <para>
+ If you create a graphics context (GC) and share it to paint
+ onto several drawables, make sure all of them have the same
+ visual and colormap for which the GC was defined. The same
+ applies if you want to copy an area from a pixmap to a
+ window; both must have the same visual and colormap
+ </para>
+
+ <para>
+ Si no está seguro de que su código lo hace correctamente, pregunte
+ educadamente en una de las listas de correo de desarrollo de
+ GNOME si alguien puede realizar una prueba con una tarjeta
+ de video que soporta esta característica. Dicha personas
+ sabrá como arreglar el problema y le dirá al respecto.
+ </para>
+ </sect3>
+ </sect2>
+
+ <!-- Unix-related Issues -->
+
+ <sect2 id="unix">
+ <title>Temas relacionados con Unix</title>
+
+ <para>
+ Verifique los valores de retorno de <emphasis>todas</emphasis>
+ las llamas al sistema que el programa realice. Recuerde
+ que muchas de las llamadas al sistema pueden ser
+ interrumpidas (por ejemplo, la llamada retornar -1 y
+ errno será definido a EINTR) y deben reiniciarse.
+ </para>
+
+ <para>
+ No asuma, por ejemplo, que la función
+ <function>write(2)</function> escribirá el buffer completo
+ de una vez; tiene que verificar el valor de retorno, el cual
+ indica el número de bytes escritos e intente nuevamente
+ hasta que sea cero. Si el valor de retorno es -1, recuerde
+ verificar el valor de errno y manejar el error
+ apropiadamente.
+ </para>
+
+ <para>
+ Si la aplicación llama a la función <function>fork(2)</function>
+ sin llamar a <function>execve(2)</function>, recuerde que
+ el proceso hijo no puede hacer llamadas X. Normalmente se
+ puede diagnosticar este problema a través de un oscuro
+ mensaje de error de Xlib.
+ </para>
+
+ <para>
+ Lea el libro «Advanced programming in the Unix
+ environment», de Stevens, para aprender acerca de
+ todos estos temas y asegúrese de que sus programas usan
+ la API de Unix de forma correcta. Si no desea asegurarse
+ del uso correcto de las llamadas Unix, pregunte en las
+ listas de correo.
+ </para>
+ </sect2>
+ </sect1>
+
+ <!-- Security Considerations -->
+
+ <sect1 id="security">
+ <title>Consideraciones de seguridad</title>
+
+ <para>
+ La seguridad es un tema complejo y en esta sección no se
+ puede explicar ni de lejos todo lo relacionado.
+ Intentaremos indicar las situaciones más comunes donde sus
+ programas deben interesarse por la seguridad.
+ </para>
+
+ <para>
+ Es muy fácil crear hoyos de seguridad a través de la creación
+ incorrecta de archivos temporales en <filename>/tmp</filename>.
+ Debe garantizar que los archivos que usará no existen al
+ momento de su creación. Usando un nombre de archivo «único»
+ e «impredecible» no es suficiente; debe garantizar que el archivo
+ con ese nombre no será creado por alguien más entre el tiempo
+ que determina el nombre y el tiempo en que es efectivamente
+ creado (básicamente los ataques involucran que un tercero
+ cree un enlace simbólico al archivo que ellos quieren
+ sobreescribir).
+ </para>
+
+ <para>
+ Afortunadamente, esto es fácil de hacer. Use el siguiente trozo
+ de código:
+
+ <programlisting>
+ char *filename;
+ int fd;
+
+ do {
+ filename = tempnam (NULL, "foo");
+ if (!filename) {
+ fprintf (stderr, "Could not create temporary file name\n");
+ exit (EXIT_FAILURE);
+ }
+
+ fd = open (filename, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600);
+ free (filename);
+ } while (fd == -1);
+ </programlisting>
+
+ Recuerde liberar <symbol>filename</symbol> usando la función
+ <function>free()</function> y llamar a las funciones
+ <function>close()</function> y <function>unlink()</function>
+ con el archivo respectivo cuando haya terminado; aquí
+ liberamos <symbol>filename</symbol> con <function>free()</function>
+ inmediatamente y así no causará una pérdida de memoria.
+ </para>
+
+ <para>
+ Si desea usar las biblioteca estándar de E/S, puede usar la
+ función <function>fdopen()</function> para transformar el
+ descriptor de archivo en <symbol>FILE *</symbol>, o puede
+ usar la <function>tmpfile()</function> para hacerlo en un
+ solo paso.
+ </para>
+
+ <para>
+ Intente no usar buffers de tamaño fijo. Los buffers de tamaño
+ fijo para cadenas constituyen los típicas fuentes de hoyos
+ explotables que pueden llegar a oscuros errores. Si definitivamente
+ debe usar buffers de tamaño fijo para cadenas, use la función
+ <function>g_snprintf()</function> para especificar el tamaño
+ máximo del buffer.
+ </para>
+
+ <para>
+ Glib proporciona la muy conveniente función
+ <function>g_strdup_printf()</function>, la cual funciona como
+ <function>sprintf()</function> pero automáticamente
+ localizará un buffer con el tamaño correcto. El valor de retorno
+ de esta función debiera ser liberada usando
+ <function>g_free()</function>. A menudo es más conveniente de
+ usar que <function>g_snprintf()</function>, ya que esta no
+ limita el tamaño de las cadenas que un programa puede manipular.
+ </para>
+
+ <para>
+ Si desea concatenar un grupo de cadenas, puede usar la función
+ <function>g_strconcat()</function>, la cual recibe una lista
+ variables de cadenas y un puntero a NULL como último argumento.
+ </para>
+
+ <para>
+ <emphasis>Bajo ninguna circunstancia</emphasis> cree un
+ programa GTK+ con setuid root. Las bibliotecas de GTK+ y
+ GNOME son grandes y complejas y no han tenido auditorías
+ de seguridad. En cualquier caso, no debiera querer que
+ una pieza tan grande código sea setuid root. Si definitivamente
+ requiere usar privilegios de root para algo, escriba un
+ programa que sea la interfaz de usuario como un proceso
+ normal, sin privilegios y cree un programa de ayuda que
+ tenga setuid y se encargue de realizar la operaciones
+ «peligrosas». Además, notifique a las listas
+ de correo de desarrollo de GNOME indicando que requiere
+ que alguien realice una auditoría de seguridad a su
+ programa de ayuda.
+ </para>
+
+ <para>
+ En general, si no está seguro si puede crear un riesgo de
+ seguridad, pregunte en la listas de correo de desarrollo
+ de GNOME.
+ </para>
+
+ <para>
+ Puede leer más sobre temas de seguridad que debiera encontrar
+ cuando programe una aplicación Unix en el documento
+ <ulink URL="http://www.fish.com/security/murphy.html">«Murphy's
+ Law and Computer Security»</ulink>, de Wietse Wenema.
+ Hay otros documentos de seguridad en <ulink
+ URL="http://www.fish.com/security">el sitio fish.com</ulink>
+ que podría encontrar interesante.
+ </para>
+
+ <para>
+ Puede encontrar muchas otras guías útiles para escribir programas
+ seguros en <ulink
+ url="http://www.dwheeler.com/secure-programs">«Secure
+ Programming for Linux and Unix HOWTO»</ulink>.
+ </para>
+ </sect1>
+
+ <!-- Performace -->
+
+ <sect1 id="performance">
+ <title>Rendimiento</title>
+
+ <para>
+ No lea esta sección hasta que esté seguro de que su programa está
+ correcto, por ejemplo, cuando esté seguro de que funciona
+ correctamente y no tiene errores. Es más importante que
+ el código sea correcto a que sea rápido. Un programa lento
+ pero correcto es mucho mejor a uno rápido pero con errores.
+ </para>
+
+ <para>
+ Si quiere optimizar su programa, el primer paso es determinar
+ un perfil al programa ejecutándolo con datos de la vida real
+ y recopilar puntos calientes que requieran optimización.
+ Esto ayudará a determinar los lugares que necesitan optimizarse.
+ Es importante que nunca adelante la optimización si no tiene
+ una idea clara sobre donde está el problema. Podría terminar
+ perdiendo el tiempo en agilizar una rutina que no es la causa
+ del cuello de boteLla y como resultado podría terminar ofuscando
+ dicha rutina. Esto podría reducir la legibilidad y mantenibilidad
+ del código sin ganancia visible en velocidad.
+ </para>
+
+ <para>
+ Un código sencillo es bueno porque es fácil de entender y
+ mantener. Si puede escribir código simple que además sea
+ potente y rápido, tanto mejor. Si tiene un trozo de código
+ inteligente pero que no es fácil de seguir, entonces documéntelo
+ para que las personas no lo estropeen accidentalmente.
+ </para>
+
+ <para>
+ No escriba código que sea difícil de leer y mantener por el
+ sólo hecho de hacerlo más rápido. En cambio prefiera un algoritmo
+ agradable y claro e impleméntelo claramente.
+ </para>
+
+ <para>
+ Hacer un buen trabajo en el caso general es a menudo mejor que
+ tener muchos casos especiales. Sólo provea casos especiales
+ cuando se han identificado puntos débiles en el programa.
+ </para>
+
+ <!-- List Management in Glib -->
+
+ <sect2 id="list">
+ <title>Administración de listas en Glib</title>
+ <para>
+ Evite emplear construcciones que terminen ralentizando
+ los algoritmos. Si usa
+ <function>g_list_insert_sorted()</function> o
+ <function>g_list_append()</function> sin ningún cuidado,
+ fácilmente puede tener un algoritmo que se ejecuta en
+ tiempo proporcional a O(n<superscript>2</superscript>).
+ Normalmente puede crear listas hacia atrás, usando
+ <function>g_list_prepend()</function>, e invirtiéndola
+ cuando haya terminado usando
+ <function>g_list_reverse()</function>. Esta es una
+ operación O(n). Y si necesita una lista ordenada, puede
+ crearla de la misma forma (hacia atrás) y una vez terminado,
+ usar <function>g_list_sort()</function>.
+ </para>
+
+ <para>
+ Si necesita una lista ordenada en todo momento, puede ser
+ mejor emplear un estructura de árbol o un híbrido
+ lista/árbol. Si necesita construir una lista añadiendo
+ nodos a ella, mantenga un puntero al final de la lista
+ y vaya cambiándola según sea apropiado; esto le permitira
+ insertar un nodo al inicio o al final en un tiempo constante.
+ </para>
+ </sect2>
+ </sect1>
+
+ <!-- Localization -->
+
+ <sect1 id="l10n">
+ <title>Localización</title>
+
+ <para>
+ Se pretende que GNOME pueda ejecutarse en distintas localidades
+ y lenguajes, y los programas debieran tener esto en cuenta. No
+ tiene que localizar los programas, sólo debe permitir que éstos
+ sean traducibles y localizables.
+ </para>
+
+ <para>
+ Debe recordar que los diferentes idiomas humanos tienen diferentes
+ gramáticas, así que no debiera suponer la forma de estructurar
+ cada frase. Esto es importante, por ejemplo, cuando se
+ construyen cadenas a partir de trozos separados.
+ </para>
+
+ <para>
+ La concatenación normalmente no es la forma correcta de construir
+ una cadena para que sea presentada al usuario. Normalmente terminan
+ en mensajes que no pueden ser traducidos correctamente en todos
+ los idiomas. En vez de concatenar, intente usar
+ <function>g_strdup_printf()</function>, por ejemplo:
+
+ <programlisting>
+ /* Una forma no muy buena */
+ char *message = g_strconcat (_("Hello, "),
+ name,
+ _(", would you like fries with that?"),
+ NULL);
+
+ /* Una mejor forma */
+ char *message = g_strdup_printf (_("Hello, %s, would you like fries with that?"),
+ name);
+ </programlisting>
+
+ Esto permitirá al traductor mover %s donde corresponda según
+ lo requiera la gramática del idioma en el cual trabaja.
+ </para>
+
+ <para>
+ Recuerdo que no todos los idiomas forman los plurales añadiendo
+ una «s» a las palabras. Además, las estructuras de
+ frases pueden cambiar con los plurales. Por ejemplo,
+
+ <programlisting>
+ /* Una forma no muy buena */
+ printf (_("%d happy monkey%s bouncing on the bed."),
+ num_monkeys,
+ (num_monkeys > 1) ? "s", "");
+
+ /* Una mejor forma */
+ printf ((num_monkeys > 1)
+ ? _("%d happy monkeys bouncing on the bed."),
+ : _("%d happy monkey bouncing on the bed."));
+ </programlisting>
+
+ Se requiere de esta forma ya que el plural se forma de
+ distintas maneras en distintos idiomas, y la estructura
+ completa de la frase puede cambiar.
+ </para>
+
+ <para>
+ Si el programa muestra fechas u horas, use la función
+ <function>strftime()</function> para darles formato como
+ cadenas. Esto se encargará de usar la representación
+ adecuada de fecha y hora de acuerdo a la definición local
+ del usuario. Además, si el programa debe generar una
+ representación visual de un calendario, recuerde que en
+ algunos países se considera como primer día de la semana
+ el domingo y no el lunes. El programa debiera permitir
+ ambas formas de calendarios.
+ </para>
+
+ <para>
+ Si el programa usa medidas, asegúrese de permitir tanto
+ el sistema métrico decimal como el sistema imperial (o anglosajón).
+ </para>
+ </sect1>
+
+ <!-- Binary Compatibility -->
+
+ <sect1 id="binary">
+ <title>Compatibilidad binaria en las bibliotecas</title>
+
+ <para>
+ Para bibliotecas estables y ya liberadas, es muy importante
+ intentar preservar la compatibilidad binaria en las revisiones
+ mayores del código. Los desarrolladores de bibliotecas deben
+ intentar no alienar a los usuarios realizando de forma frecuente
+ cambios que sean binariamente incompatibles en bibliotecas que
+ son de producción. Por supuesto, en aquellas bibliotecas que se
+ encuentran en desarrollo o están etiquetadas como no finalizadas
+ puede realizar tantos cambios como lo necesiten.
+ </para>
+
+ <para>
+ Una biblioteca típicamente exporta un número de interfaces. Estas
+ incluyen nombres de rutinas, las firmas o prototipos de estas
+ rutinas, variables globales, estructuras, campos de estructura
+ (tanto los tipos como su significado), el significado de los
+ valores enumerados y la semántica de los archivos que la
+ biblioteca crea. Mantener compatibilidad binaria significa que
+ estas interfaces no cambiarán. Puede añadir nuevas interfaces
+ sin romper la compatibilidad binaria, pero no puede cambiar
+ las ya existentes, ya que los programas antiguos no se ejecutarán
+ correctamente.
+ </para>
+
+ <para>
+ Esta sección incluye un número de ideas acerca de como lograr
+ que el código de una biblioteca sea compatible con sus
+ versiones anteriores.
+ </para>
+
+ <para>
+ Mantener la compatibilidad binaria significa que los programas
+ y archivos objetos que fueron compilados con una versión
+ previa del código continuarán funcionando sin recompilar aún
+ cuando la biblioteca sea reemplazada. Es posible encontrar
+ una descripción detallada en el nodo info
+ <filename>(libtool)Interfaces</filename> de la documentación
+ de GNU libtool.
+ </para>
+
+ <!-- Private Information in Structures -->
+
+ <sect2 id="private">
+ <title>Información privada en las estructuras</title>
+
+ <para>
+ En el sistema GNOME es una tarea muy común crear un
+ nuevo <structname>GtkObject</structname> para crear
+ una estructura cuyo primer miembro corresponde a la
+ clase de la cual hereda este objeto y posteriormente
+ un número de variables de instancia que se añaden
+ después del primer miembro.
+ </para>
+
+ <para>
+ Este esquema de diseño normalmente lleva a que el código
+ sea difícil de actualizar y cambiar: si se quiere
+ extender un objeto donde se necesita mantener su estado
+ interno, los programadores necesitan recurrir a varios
+ hacks para mantener el mismo tamaño de las estructuras.
+ Esto hace difícil agregar nuevos campos a las estructuras
+ públicas sin romper la compatibilidad binaria, ya que
+ los campos de la estructura pueden cambiar y el tamaño
+ de las estructuras pueden variar.
+ </para>
+
+ <para>
+ Por consiguiente, se sugiere una estrategia que puedan
+ adoptar los desarrolladores en el momento de crear nuevos
+ objetos. Esta estrategia asegurará la compatibilidad
+ binaria y al mismo tiempo mejorará la legibilidad y
+ mantenibilidad del código.
+ </para>
+
+ <para>
+ La idea es que, para un objeto dado, el programador
+ debiera crear tres archivos: el primero que contiene
+ el contrato entre la biblioteca y el usuario (esto
+ es el archivo de encabezado que se instala en el
+ sistema); el segundo contiene la implementación del
+ objeto; y el tercer archivo contiene la definición
+ de la estructura para los campos privados o internos
+ que no necesitan estar en la estructura pública.
+ </para>
+
+ <para>
+ La API pública de la estructura podría incluir un
+ puntero a un elemento privado, el cual podría
+ apuntar a los datos privado de la instancia. Las
+ rutinas de implementación podría dereferenciar
+ este punto para acceder a los datos privados; por
+ supuesto, el puntero apunta a la estructura que se
+ localiza privadamente.
+ </para>
+
+ <para>
+ Por ejemplo, imagine que se crea el objeto GnomeFrob.
+ La implementación del widget sera dividido en tres
+ archivos:
+
+ <table>
+ <title>Archivos que muestran el widget de ejemplo
+ GnomeFrob</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Archivo</entry>
+ <entry>Contenido</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><filename>gnome-frob.h</filename></entry>
+ <entry>API pública de GnomeFrob</entry>
+ </row>
+ <row>
+ <entry><filename>gnome-frob.c</filename></entry>
+ <entry>Implementación del objeto Gnomefrob</entry>
+ </row>
+ <row>
+ <entry><filename>gnome-frob-private.h</filename></entry>
+ <entry>Datos privados de la implementación de GnomeFrob.
+ Debiera querer usar esto si planea compartir los
+ datos privados a través de varios archivos C. Si
+ limita el uso de la información privada a sólo un
+ archivo, no necesita esto, ya que al definir la
+ estructura en el archivo de implementación logrará
+ el mismo efecto.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+
+ <para>
+ <example>
+ <title>Ejemplo de la API pública de <filename>gnome-frob.h</filename>
+ </title>
+ <programlisting>
+typedef struct _GnomeFrob GnomeFrob;
+typedef struct _GnomeFrobPrivate GnomeFrobPrivate;
+
+struct _GnomeFrob {
+ GtkObject parent_object;
+
+ int public_value;
+ GnomeFrobPrivate *priv;
+} GnomeFrob;
+
+GnomeFrob *gnome_frob_new (void);
+void gnome_frob_frobate (GnomeFrob *frob);
+ </programlisting>
+
+ </example>
+
+ <example>
+ <title>Ejemplo de
+ <filename>gnome-frob-private.h</filename></title>
+ <programlisting>
+typedef struct {
+ gboolean frobbed;
+} GnomeFrobPrivate;
+ </programlisting>
+ </example>
+
+ <example>
+ <title>Ejemplo de la implementación de
+ <filename>gnome-frob.c</filename>.</title>
+ <programlisting>
+void gnome_frob_frobate (GnomeFrob *frob)
+{
+ g_return_if_fail (frob != NULL);
+ g_return_if_fail (GNOME_IS_FROB (frob));
+
+ frob->priv->frobbed = TRUE;
+}
+ </programlisting>
+ </example>
+
+ Fíjese en el uso de prototipos de estructura: esto permite que
+ el compilador realice más verificaciones en tiempo de
+ compilación respecto a los tipos que estan siendo empleados.
+ </para>
+
+ <para>
+ Este esquema es útil en algunas situaciones, particularmente
+ en el caso en el cual vale la pena almacenar un puntero
+ extra para una instancia del objeto. Si esto no fuera
+ posible, el programador necesitaría recurrir a otros
+ artilugios para evitar este problema.
+ </para>
+
+ <para>
+ El propósito de tener un archivo de encabezado privado
+ extra para las estructuras privadas es permitir que las
+ clases derivadas usen esta información. Por supuesto,
+ una buena práctica de programación indicaría que debiera
+ proveerse de interfaces o métodos de acceso precisamente
+ para que el programador no tenga que lidiar con
+ estructuras privadas. Se debiera intentar alcanzar un
+ balance entre buena práctica y pragmatismo cuando se
+ crean estructuras privadas y métodos de acceso públicos.
+ </para>
+
+ <para>
+ Podrían aparecer algunos problemas, por ejemplo, cuando
+ se ha enviado un versión del código y que está siendo
+ ampliamente usado y se desea extenderlo. Hay dos
+ soluciones para esto.
+ </para>
+
+ <para>
+ La primera opción es encontrar un campo puntero en la
+ estructura pública que pueda hacerse privada y
+ reemplazar el puntero a la parte privada de la
+ estructura. Esto preserva el tamaño de la estructura
+ ya que, para los propósitos de GNOME, se puede
+ asumir que los punteros son todos del mismo tamaño.
+ Se puede hacer que este campo apunte a la parte privada
+ de la estructura que será ubicada por la función que
+ originalmente creaba la estructura pública. Es
+ importante que este campo sea llamado
+ <structfield>private</structfield>, se trata de
+ una palabra reservada de C++ y creará problemas cuando
+ el archivo de encabezado sea usado desde programas
+ fuentes C++ — mejor llámelo
+ <structfield>priv</structfield>. Por supuesto, este
+ tipo de cambios sólo funcionará si el antiguo campo
+ puntero solamente era usado para propósitos internos;
+ si los usuarios de la biblioteca habían tenido acceso
+ a dicho campo para cualquier propósito, será necesario
+ buscar otro campo o buscar una solución diferente.
+ </para>
+
+ <para>
+ Si la estructura original fue derivada de
+ <structname>GtkObject</structname> y no hay campos punteros
+ que puedan ser reemplazados, puede usar la facilidad
+ de datos de objetos de GTK+. Esto permite asociar punteros
+ a datos arbitrarios a objetos. Use la función
+ <function>gtk_object_set_data()</function> para adjuntar
+ valores o estructuras a un objeto y cuando requiera usarlos
+ la función <function>gtk_object_get_data()</function>
+ permitirá recuperar dichos valores. Esto puede ser empleado
+ para adjuntar una estructura privada a un objeto GTK+.
+ Esto no es tan eficiente como el enfoque anterior, pero podría
+ no importar para el dominio particular de la aplicación. Si
+ los datos serán accedidos frecuentemente, se pueden usar
+ quarks en vez de cadenas para agregar y obtenerlos a través
+ de las funciones
+ <function>gtk_object_set_data_by_id()</function> y
+ <function>gtk_object_get_data_by_id()</function>,
+ respectivamente.
+ </para>
+
+ </sect2>
+ </sect1>
+
+ <!-- Modifying Other People's Code -->
+
+ <sect1 id="modify">
+ <title>Cómo modificar el código de otros</title>
+
+ <para>
+ GNOME es un proyecto de equipo, así las contribuciones de
+ código a programas de otras personas siempre son apreciadas.
+ Siga los siguientes lineamientos cuando modifique el código
+ de otra persona.
+ </para>
+
+ <!-- General Etiquette -->
+
+ <sect2 id="etiquette">
+ <title>Etiqueta general</title>
+
+ <para>
+ Siga el mismo estilo de indentación usado en el código
+ original. El código original perdurará durante más tiempo
+ que el que le pueda dedicar, mantener las
+ contribuciones consistentes respecto a la indentación
+ es más importante que forzar su estilo de indentación
+ en el código.
+ </para>
+
+ <para>
+ Aunque sus parches pueden implementar una
+ funcionalidad muy llamativa, es muy molesto para el
+ autor tener que reindentar el código antes de aplicar
+ un parche al código principal. Así, si el código
+ original luce como
+
+ <programlisting>
+int
+sum_plus_square_of_indices (int *values, int nvalues)
+{
+ int i, total;
+
+ total = 0;
+
+ for (i = 0; i < nvalues; i++)
+ total += values[i] + i * i;
+
+ return total;
+}
+ </programlisting>
+
+ entonces no agregue una función que luce como
+
+ <programlisting>
+int sum_plus_cube_of_indices(int *values, int nvalues) {
+ int i,total;
+
+ total=0;
+
+ for (i=0;i<nvalues;i++)
+ total+=values[i]+i*i*i;
+
+ return total;
+}
+ </programlisting>
+
+ En el segundo ejemplo, la indentanción y ubicación de las
+ llaves no coincide con el código original, no hay espacios
+ alrededor de los operadores y el código no se parecerá
+ al original. Siga el estilo de programación del autor
+ original del programa y los parches que envíe tendrán una mejor
+ oportunidad de ser aceptados.
+ </para>
+
+ <para>
+ No repare errores con hacks rápidos o artilugios; repárelo
+ correctamente. Tampoco añada características como hacks o
+ con código que no sea extensible; es mejor rehacer el
+ código original para que sea extensible y luego agregue
+ la nueva característica, utilizando el código como
+ estructura.
+ </para>
+
+ <para>
+ La limpieza de código siempre es bienvenida; si encuentra
+ trozos de código feos y sucios en GNOME, será muy
+ apreciado si envía parches que hagan el código más
+ agradable y fácil de mantener.
+ </para>
+
+ <para>
+ Como siempre, asegúrese de que el código que contribuye compila
+ sin ningún tipo de aviso, que tenga los prototipos correctos
+ y que siga las directrices de este documento.
+ </para>
+ </sect2>
+
+ <!-- Documenting Your Changes -->
+
+ <sect2 id="document">
+ <title>Cómo documentar los cambios</title>
+
+ <para>
+ GNOME utiliza los archivos &ChangeLog; estándar de GNU para
+ documentar los cambios al código. Cada cambio que
+ efectúe a un programa <emphasis>debe</emphasis> ser
+ acompañado por una registro en el &ChangeLog;. Esto
+ permite a las personas leer la historia de cambios
+ del programa de una manera sencilla.
+ </para>
+
+ <para>
+ Si usa &Emacs;, puede agregar las líneas al
+ &ChangeLog; presionando «C-x 4 a».
+ </para>
+
+ <note>
+ <para>
+ Si conoce la forma de realizarlos para otros editores
+ populares, agradeceremos que nos lo haga saber para
+ expandir este documento.
+ </para>
+ </note>
+
+ <para>
+ Cada registro en el &ChangeLog; tiene un forma general:
+ <programlisting>
+1999-04-19 J. Random Hacker <jrandom@foo.org>
+
+ * foo.c (some_function): Changed the way MetaThingies are
+ frobnicated. We now use a hash table instead of a linked list to
+ look MetaThingies up.
+ (some_other_function): Support the MetaThingies hash table by
+ feeding it when necessary
+
+ * bar.c (another_function): Fixed bug where it would print "Take
+ me to your leader" instead of "Hello, World".
+
+1999-04-18 Johnny Grep <grep@foobar.com>
+
+ * baz.c (ugly_function): Beautified by using a helper function.
+ </programlisting>
+ </para>
+
+ <para>
+ Si agrega una nueva función a una biblioteca, escriba
+ la referencia necesaria y la documentación de programación.
+ Puede escribir una referencia a la documentacion
+ en línea usando el formato de comentarios descrito en
+ <filename>gnome-libs/devel-docs/api-comment-style.txt</filename>.
+ Si usa &Emacs;,
+ <filename>gnome-libs/tools/gnome-doc/gnome-doc.el</filename>
+ provee un acelerador que puede ser empleado para añadir
+ una plantilla de documentación al programa.
+ </para>
+ </sect2>
+
+ <!-- Changing Code on CVS -->
+
+ <sect2 id="change-cvs">
+ <title>Cómo actualizar en CVS</title>
+
+ <para>
+ Si tiene acceso de escritura en el repositorio CVS de GNOME,
+ debe seguir algunas políticas adicionales. Ya que está
+ trabajando en la copia maestra de los fuentes, debe tener
+ especial cuidado.
+ </para>
+
+ <para>
+ Si está reparando algo en un programa que está en el CVS
+ o si está añadiendo una funcionalidad allí, y si no ha
+ estado trabajando en dicho programa por un período largo
+ de tiempo, pregunte al autor original antes de aplicar
+ sus parches. Generalmente está bien formular estas
+ preguntas en la lista de correo
+ <filename>gnome-devel-list</filename>.
+ </para>
+
+ <para>
+ Una vez que el autor del programa lo indique como un
+ «contribuyente frecuente», puede comenzar
+ aplicar los parches sin previo consentimiento. Si
+ quiere aplicar un reorganización mayor del código,
+ debiera preguntar primero.
+ </para>
+
+ <para>
+ Algunos módulos en el CVS tienen rama estable y de
+ desarrollo. Normalmente el desarrollo debiera ir
+ en la rama HEAD en el CVS, y la rama estable debiera
+ mantenerse separadamente. Generalmente no se añaden
+ nuevas características a las rama estable; sólo
+ se reparan errores. Repare el error a la rama estable
+ y pregunte al autor principal sobre la política para
+ mezclar parches en la rama de desarrollo; algunos
+ autores prefieren hacerlo por lotes, mientras hay otros
+ que prefieren mezclarlos inmediatamente.
+ </para>
+
+ <para>
+ Si trabaja en una característica experimental que
+ podría estropear mucho código, cree una rama en el CVS
+ y realice los cambios allí. No los mezcle en la rama
+ principal de desarrollo hasta que se encuentre
+ razonablemente seguro que funcionará correctamente y que
+ se integrará bien dentro del resto del código. El uso de
+ una rama para trabajo en características experimentales
+ le permitirá evitar interrumpir el trabajo de otros
+ desarrolladores. Pregunte al autor principal antes de
+ mezclar su rama y traer sus cambios a la parte principal
+ del árbol.
+ </para>
+
+ <para>
+ Como siempre, agrege un registro en el &ChangeLog;
+ cuando realice un cambio. Algunos autores tienen la
+ política de rechazar, correctamente, los cambios que
+ no tienen tal registro.
+ </para>
+
+ <para>
+ Algunas veces existen diferentes políticas para los módulos,
+ verifique si el módulo contiene un archivo
+ <filename>README.CVS</filename>. Si es así, lea ese archivo
+ antes de realizar cambios.
+ </para>
+
+ <!-- Branches and Tags -->
+
+ <sect3 id="branches">
+ <title>Ramas y marcas</title>
+
+ <para>
+ Tenemos una convención para nombrar las ramas y marcas o
+ puntos de una rama en el repositorio de CVS de GNOME.
+ Las marcas deben ser definidas después que se libera cada
+ nueva version y deben ser de la forma
+ «MODULE_MAJOR_MINOR_MICRO», por ejemplo,
+ «GNOME_LIBS_1_0_53». Los puntos de una rama
+ deben ser de la forma «MODULE_BRANCH_ANCHOR»,
+ como en «GNOME_LIBS_1_0_ANCHOR». Finalmente,
+ una rama raíz en este punto debiera ser de la forma
+ «module-branch», por ejemplo,
+ «gnome-libs-1-0». Use esta convención cuando
+ cree marcas, puntos de una rama y ramas.
+ </para>
+ </sect3>
+
+ <!-- Additional CVS Policies -->
+
+ <sect3 id="cvs-policies">
+ <title>Políticas adicionales del CVS</title>
+
+ <para>
+ CVS no proporciona un manera preconstruida para renombrar archivos
+ o moverlos a otros directorios. Debiera planificar
+ cuidadosamente el árbol del repositorio de tal forma que evite
+ mover o renombrar archivos.
+ </para>
+
+ <para>
+ En el caso que deba mover o renombrar un archivo en el CVS,
+ <emphasis>NO EJECUTE</emphasis> «cvs remove»
+ y luego «cvs add». Si lo hace, los archivos
+ «nuevos» perderán la capacidad de seguir su
+ historia de cambios, ya que desde el punto de vista de CVS
+ serán archivos completamente nuevos en su revisión
+ inicial. Un objetivo del repositorio CVS de GNOME es
+ poder seguir la historia de los fuentes de manera
+ precisa desde el inicio.
+ </para>
+
+ <para>
+ <emphasis>Por favor</emphasis>, pregunte al mantenedor
+ del CVS, esto es, una persona conocida con acceso shell
+ a la máquina con CVS, para realizar la cirugía necesaria
+ para mover los archivos por usted. Esto requiere
+ conocimiento de la forma en que funciona CVS y debe ser
+ hecho muy cuidadosamente. La recuperación de un error de
+ «cvs add/remove» es una tarea muy desagradable;
+ <!-- FIXME -->
+ if you move files in this
+ erroneous way a CVS maintainer who has to go through this
+ job will summon a flaming bat of death from hell to bite
+ your head off. So please ask for someone to move the files
+ for you.
+ </para>
+ </sect3>
+ </sect2>
+
+ </sect1>
+
+ <!-- Maintaining a Package -->
+
+ <sect1 id="maintain">
+ <title>Cómo mantener un paquete</title>
+
+ <para>
+ Un mantenedor de paquete es una persona que se preocupa de
+ liberar versiones, integrar cambios de otras personas y,
+ en general, ser responsable de un paquete. Durante el
+ período de vida de un paquete, este puede cambiar de
+ mantenedores, por ejemplo, una persona que pierde interés
+ o que ya no puede dedicarle tiempo suficiente como mantenedor.
+ </para>
+
+ <para>
+ En conformidad con los Estándares de programación de GNU, GNOME
+ usa GNU Autoconf para manejar la portabilidad y GNU Automake
+ para crear makefiles. Automake hace especialmente fácil
+ construir paquetes correctos, así que si es un mantenedor
+ de paquetes, debiera aprender como usarlo. Autoconf y
+ Automake tienen muchas áreas truculentas, así que siéntase
+ libre de pedir ayuda en las listas de desarrollo de GNOME
+ si tiene preguntas sobre la forma correcta de makefiles
+ para su paquete.
+ </para>
+
+ <para>
+ Un número de personas regularmente contribuye con traducciones
+ localizadas de los catálogos de mensajes en los paquetes de
+ GNOME. Para mantener las traducciones actualizadas tanto como
+ sea posible, los mantenedores deben coordinarse con los
+ traductores para que estos últimos puedan actualizar las
+ traducciones a tiempo cuando se va a liberar una nueva
+ versión del paquete. Una buena forma de notificar a los
+ traductores consiste en enviar un mensaje a
+ <email>gnome-i18n@gnome.org</email> con suficientes
+ días de anticipación. Esto les permitirá actualizar sus
+ respectivas traducciones a tiempo para puedan ser incluidas
+ en la siguiente versión liberada.
+ </para>
+ </sect1>
+
+ <!-- Memory Leaks Agenda -->
+
+ <sect1 id="memory-leak">
+ <title>¿Por qué debería preocuparse por la pérdida de memoria?.</title>
+
+ <para>
+ Échele un vistazo a la lista de errores de Mozilla y una cosa es
+ clara: el nuevo código que entra a Mozilla no es (o no ha sido)
+ verificado suficientemente por pérdida de memoria y problemas
+ de acceso.
+ </para>
+
+ <para>
+ Las pérdidas de memoria son malas por varias razones:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Se comerá el área de intercambio lentamente. A la larga su
+ programa, o hasta su máquina sucumbirán.
+ </para>
+ <para>
+ Nadie quiere que su programa o biblioteca adquiera la
+ reputación de ser una porquería sólo porque uno ha sido
+ vago. Déjeselo a las personas en Redmond.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Ocultan el mal uso de la memoria. Si olvida liberar la
+ memoria, no hay forma de atrapar las lecturas y
+ escrituras a esos trozos de memoria. Si posteriormente
+ repara la pérdida, una parte completamente distinta
+ del programa podría fallar.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Cuando se usan verificadores automáticos de memoria,
+ nadie quiere ver 600 problemas, de los cuales 500
+ se encuentran en las bibliotecas de soporte. Lo que
+ desea ver es que las todo iba como una seda antes de
+ que empezara a toquetear y que, por lo tanto, le toca
+ arreglar los problemas.
+ </para>
+
+ <para>
+ Este es uno de los problemas de Mozilla actualmente:
+ gotea sin parar así qiu ¿cómo va a saber si ha contribuido al problema?
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <sect2 id="memory-advice">
+ <title>Algunos consejos en la lucha contra la pérdida de memoria.</title>
+
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Use «const» donde sea posible (para punteros obviamente).
+ </para>
+ <para>
+ Si un argumento es «const», entonces indudablemente la
+ función llamada no liberará la memoria por usted.
+ </para>
+ <para>
+ Si el tipo de resultado de una función es «const», entonces
+ claramente no es responsable por liberarlo.
+ *Probablemente* lo será para un resultado distinto de
+ «const» (que no sea un entero o algo similar).
+ </para>
+ <para>
+ Fíjese en que, desafortunadamente, esto no funciona muy bien
+ con los objetos que cuentan referencias. Funciona bien
+ con cadenas.
+ </para>
+ <para>
+ Dado que C usa llamadas por valor, no tiene sentido
+ aplicar «const» a tipos int, double y similares.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>Documente las responsabilidades.</emphasis>
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Si una función toma la propiedad de un objeto/referencia,
+ sea explícito acerca de ello.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Indique siempre si el que llama a la función debiera
+ liberar/desreferenciar los resultados.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Documenta *cómo* entregar la memoria: unref, free,
+ g_free, ...
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>Sea cuidadoso cuando use copiar-y-pegar.</emphasis>
+ </para>
+
+ <para>
+ El proceso de cortado y pegado no mejora el código, al
+ contrario de lo que creen muchos programadores. Primero
+ mire el código y si intenta producir muchas copias, quizás
+ necesite una función de ayuda. <!-- FIXME: mejor
+ traducción de helper -->
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>Libere todo antes de salir.</emphasis>
+ </para>
+ <para>
+ Esto lleva tiempo, así que quizás debiera hacerlo sólo dentro
+ de una condición.
+ </para>
+ <para>
+ El motivo de este consejo es que los verificadores de memoria
+ toman tiempo en determinar entre una pérdida que conoce y no
+ le preocupa y las otras pérdidas.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>No deje punteros sueltos en sus estructuras de
+ datos.</emphasis>
+ </para>
+
+ <para>
+ Asigne NULL o (void *)0xdeadbeef para los miembros liberados a
+ menos que vaya a liberar la estructura a la que pertenecen.
+ </para>
+
+ <para>
+ Los punteros sueltos tienen la mala tendencia de ocultar pérdidas
+ de memoria.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>Ejecute el nuevo código en un ciclo 1 millón de
+ veces.</emphasis>
+ </para>
+
+ <para>
+ Si pierde memoria, lo sabrá — sólo siga al proceso con
+ top en otra ventana. Podría querer especificar a top el PID
+ del proceso con la opción -p.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>Repárelo ahora, no después.</emphasis>
+ </para>
+
+ <para>
+ No escriba una porquería de código; más temprano que tarde le
+ pesará.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ </sect1>
+</article>