2010-05-05 5 views
6

La mayoría de los programas que escribo son procesos relativamente organigramatibles, con un inicio definido y un final esperado. Los problemas en sí mismos pueden ser complejos, pero no se inclinan fácilmente hacia el uso central de objetos y la programación dirigida por eventos. A menudo, simplemente estoy agitando grandes lotes de datos de texto para producir diferentes datos de texto. Solo ocasionalmente necesito crear una clase: como ejemplo, para rastrear advertencias, errores y mensajes de depuración, creé una clase (Problemas) con una instanciación (myErr), que creo que es un ejemplo del patrón de diseño de Singleton . Como un factor adicional, mis colegas son más de la vieja escuela (de procedimiento) que yo y no están familiarizados con la programación orientada a objetos, por lo que soy reacio a crear cosas que no pudieron descifrar.Describa sus luchas con la minimización del uso de variables globales

Y sin embargo, oigo, una y otra vez, cómo incluso el patrón de diseño de Singleton es realmente un antipatrón y debe evitarse porque las variables globales son malas.

Las funciones secundarias necesitan pocos argumentos y no tienen necesidad de conocer la configuración (sin cambios) o el estado del programa (cambio) - Estoy de acuerdo. Sin embargo, las funciones en el medio de la cadena, que controlan principalmente el flujo del programa, necesitan un gran número de variables de configuración y algunas variables de estado del programa. Creo que pasar una docena o más de argumentos junto con una función es una "solución", pero difícilmente atractiva. Podría, por supuesto, meter variables en una sola matriz hash/dict/asociativa, pero parece una trampa.

Por ejemplo, al conectarme al Directorio Activo para crear una nueva cuenta, necesito variables de configuración como un nombre de usuario administrativo, contraseña, una unidad organizativa objetivo, algunos grupos predeterminados, un dominio, etc. Tendría que pasar esos argumentos a través de una variedad de funciones que ni siquiera las usarían, simplemente las baraja a través de una cadena que eventualmente conduciría a la función que realmente las necesita.

que habría al menos declaran las variables de configuración para que sea constante, para protegerlos, pero mi idioma de su elección en estos días (Python) no proporciona ninguna manera simple de hacer esto, sin embargo existen recetas como soluciones temporales.

Numerosas preguntas de desbordamiento de pila han llegado al por qué? de la maldad y el requisito de rehuir, pero no suelen mencionar consejos sobre cómo vivir con esta restricción casi religiosa. ¿Cómo resolvió, o al menos hizo las paces con, la cuestión de las variables globales y el estado del programa? ¿Dónde has hecho compromisos? ¿Cuáles han sido tus trucos, aparte de empujar una bandada de argumentos a las funciones?

+0

Buena pregunta: ¿está categorizando las variables de nivel de clase (miembro) como variables globales? –

Respuesta

5

Creo que hay un momento y un lugar para el patrón singleton, o situaciones similares. El punto clave para recordar es que una y otra vez, muchas personas han experimentado un horror específico cuando se trata de la opción "incorrecta" para usar variables globales/compartidas/estáticas, así como el patrón singleton.

En su caso, está hablando de configuración específicamente. No veo ningún daño al usar un patrón de estilo único para acceder a esos elementos de configuración. Cada aplicación tiene configuración, DEBE estar en una ubicación a la que pueda llamar, no hay necesidad de simplemente pasarla, eso complica más de lo que ayuda.

La clave aquí es para asegurarse de que REALMENTE necesita que la información exista solo una vez, la configuración es, con mucho, uno de los mejores motivos que he encontrado para utilizar este tipo de patrón.

3

Los datos globales que son invariables o están bien definidos y abarcan todo el proceso (p. Ej., El registro), generalmente son correctos para usarlos como datos globales. Los datos de configuración, especialmente si viven en un archivo local, caen dentro de la misma categoría (solo hay un archivo para todo el proceso/aplicación, similar al registro).

En general, si encuentra que tiene que pasar argumentos adicionales solo para pasarlos a otra función, debe jalar esa función "hacia arriba" y tener otra que medie. Otro enfoque más práctico que lo ilustra es el desarrollo basado en pruebas porque te obliga a pasar dependencias.

Otra forma de pensar es: si esa función no puede conocer fácilmente todos los detalles para llamar a una subfunción, tire de la subfunción hacia arriba y forzar una capa más alta y con más conocimiento para adquirir la necesaria información. Encontré esta técnica altamente conductiva para codificar la calidad, ya que construye piezas compartimentadas, en lugar de bestias monolíticas.

En su ejemplo de directorio activo, en lugar de pasar alrededor de los argumentos a la ad_connect, pasar alrededor de un objeto que se encarga de la lógica necesaria, y luego tener una función que media la interacción entre el objeto y la función de usarlo

def create_user(name, ad_user, ad_pass, ad_ou, ...): 
    conn = ad_connect(ad_user, ad_pass, ...) 
    conn.CreateRecord(ad_user) 

def create_user_mediator(name, ad_controller): 
    ad_controller.CreateRecord("cn=%s" % name) 

Eso es solo una forma de hacerlo, y, por supuesto, tiene sus pros y sus contras. Es simplemente un ejemplo de cómo create_user puede evitar tener que usar variables globales.