2012-02-28 8 views
9

Algo fuera de necesidad, desarrollo software con mi configuración regional en "C" o "en_US". Es difícil utilizar una configuración regional diferente porque solo hablo un idioma con algo que se acerca a la fluidez.¿Qué estrategias existen para garantizar que todas las operaciones basadas en la configuración regional se manejen correctamente en todas las configuraciones regionales?

Como resultado, a menudo pasan por alto las diferencias de comportamiento que pueden introducirse al tener diferentes configuraciones de configuración regional. Sorprendentemente, pasar por alto esas diferencias a veces dará lugar a errores que solo descubrirá un usuario desafortunado que use una configuración regional diferente. En casos particularmente malos, ese usuario puede que ni siquiera comparta un idioma conmigo, por lo que el proceso de informe de errores es difícil. Y, importante, gran parte de mi software está en forma de bibliotecas; mientras que casi nada establece la configuración regional, puede combinarse con otra biblioteca, o usarse en una aplicación que establece establecer el comportamiento de generación regional que nunca experimento yo mismo.

Para ser un poco más específico, los tipos de errores que tengo en mente no faltan localizaciones de texto o errores en el código para usar esas localizaciones. En cambio, me refiero a errores donde una configuración regional cambia el resultado de alguna API localizable (por ejemplo, toupper(3)) cuando el código que utiliza esa API no anticipaba la posibilidad de dicho cambio (por ejemplo, en la configuración regional turca, toupper no cambia "i" a "I" - potencialmente un problema para un servidor de red que intenta hablar un protocolo de red particular a otro host).

Algunos ejemplos de este tipo de errores en el software que mantienen:

En el pasado, uno de los enfoques que he tomado para hacer frente a esta es escribir pruebas de regresión que cambien explícitamente la configuración regional a una donde se sabe que el código no funciona, ejercite el código, verifique el comportamiento correcto y el n restaurar la configuración regional original. Esto funciona bastante bien, pero solo después de que alguien haya informado un error, y solo cubre un área pequeña de una base de código.

Otro enfoque que parece posible es tener un sistema de integración continua (CIS) configurado para ejecutar un conjunto completo de pruebas en un entorno con un conjunto de configuración regional diferente. Esto mejora la situación de alguna manera, al brindar tanta cobertura en esa ubicación alternativa como la suite de pruebas normalmente ofrece. Otro inconveniente es que hay muchos, muchos, muchos lugares, y cada uno puede posiblemente causar problemas diferentes. En la práctica, probablemente haya una docena o más de formas diferentes en que una configuración regional puede interrumpir un programa, pero tener docenas de configuraciones de prueba adicionales es una carga para los recursos (particularmente para un proyecto que ya extiende sus límites de recursos probando en diferentes plataformas, contra diferentes bibliotecas versiones, etc.).

Otro enfoque que se me ocurrió es utilizar (posiblemente primero creando) una nueva configuración regional que es radicalmente diferente de la configuración regional "C" en todos los sentidos: tener una asignación de casos diferente, usar un separador de miles diferente, fechas de formato de manera diferente, etc. Esta configuración regional se podría utilizar con una configuración CIS adicional y se espera que capture cualquier error en el código que pueda desencadenarse en cualquier configuración regional.

¿Ya existe una localidad de prueba? ¿Hay fallas en esta idea para probar la compatibilidad con la configuración regional?

¿Qué otros enfoques para las pruebas de localidad han tomado las personas?

Me interesan principalmente las configuraciones regionales POSIX, ya que esas son las que conozco. Sin embargo, sé que Windows también tiene algunas características similares, por lo que la información adicional (tal vez con más información de fondo sobre cómo funcionan esas características), también podría ser útil.

+2

¡Buena pregunta! No creo que haya una buena respuesta; en particular, Python explícitamente [no admite] (http://docs.python.org/library/locale.html#background-details-hints-tips-and-caveats) locale-invariant string manipulations. Sospecho que la solución es hacer una lista de todas las API que usan configuración de configuración local y, bueno, no usarlas. – katrielalex

+0

Estoy tan contento de que hablo alemán (lengua materna) y una fracción de japonés además del inglés para estas cosas.Aún así, es una muy buena pregunta, porque incluso conocer más de un idioma no facilita mucho la tarea (vale, puede leer los errores, eso es una buena ventaja, pero encontrar la línea problemática funciona aunque no sepas lo que dice el mensaje) – Voo

Respuesta

3

Me limitaré a auditar su código para usos incorrectos de funciones como toupper. En el modelo de configuración regional C, se debería considerar que dichas funciones funcionan solo con texto en lenguaje natural en el idioma de la configuración regional. Para cualquier aplicación que trate textos potencialmente multilingües, esto significa que funciones como tolowerno deben usarse en absoluto.

Si su objetivo es POSIX, tiene un poco más de flexibilidad debido a la función uselocale que permite anular temporalmente la configuración regional en un solo hilo (es decir, sin estropear el estado global de su programa). Luego puede mantener la configuración regional C globalmente y usar tolower etc. para texto ASCII/orientado a máquina (como archivos de configuración y similares) y solo uselocale a la configuración regional seleccionada del usuario cuando trabaje con texto en lenguaje natural desde dicha configuración regional.

De lo contrario (y tal vez incluso si necesita más avanzado), creo que la mejor solución es descartar completamente funciones como tolower y escribir sus propias versiones ASCII para texto de configuración y similares, y usar un poderoso Unicode- biblioteca consciente para texto en lenguaje natural.

Una pegajosa cuestión que aún no he mencionado es el separador decimal en relación con funciones como snprintf y strtod. Tenerlo cambiado a , en lugar de . en algunas configuraciones regionales puede arruinar su capacidad para analizar archivos con la biblioteca C. Mi solución preferida es simplemente nunca configurar la configuración regional LC_NUMERIC en absoluto. (Y soy matemático, así que tiendo a creer que los números deben ser universales, no sujetos a convenciones culturales). Dependiendo de su aplicación, las únicas categorías locales realmente necesarias pueden ser LC_CTYPE, LC_COLLATE y LC_MESSAGES. También suelen ser útiles LC_MONETARY y LC_TIME.

+0

'tolower/upper' también tienen el problema adicional de que generalmente se usan para comparar cosas que no distinguen entre mayúsculas y minúsculas, lo que simplemente no funciona con unicode. Un montón de razones para mantenerse alejado de unicdoe como sea posible (es decir, utilizar una biblioteca de alto nivel, no "simplemente asumir ascii") - tantos errores sutiles esperando allí, ugh. – Voo

+0

Gracias. "Auditar y eliminar" es ciertamente una estrategia; Me interesan especialmente las técnicas para verificar, especialmente de forma automatizada, que la estrategia haya tenido éxito y para proteger contra futuras regresiones. –

+0

Mi herramienta favorita para esto sería una almádena, es decir, eliminar todos los usos de las funciones de clase/carácter que pudieran ser problemáticos y todos los usos de 'setlocale' con' LC_NUMERIC'. Eso hace que sea bastante fácil verificar la corrección. –

2

Tiene dos problemas diferentes que resolver para responder a su pregunta: probar su código y resolver problemas con el código de otras personas.

Probando su propio código - He resuelto esto usando 2 o 3 configuraciones regionales basadas en inglés en un entorno de CI: en_GB (colación), en_ZW (casi todo cambia pero aún puede leer los errores) y luego en_AU (fecha, el cotejo)

Si desea asegurarse de que el código funciona con nombres de archivo de varios bytes, entonces también necesita probar con ja_JP

Tratar con código de otros pueblos es en muchos aspectos el más duro y mi solución para lo que vale para almacenar los valores de fecha (casi siempre son fechas :) en su valor de fecha/hora sin procesar y siempre mantenerlos como GMT. Luego, cuando cruzas el límite de tu aplicación, conviertes al formato apropiado.

PyTZ y PyICU son muy útiles para hacer lo anterior.

Cuestiones relacionadas