solid single responsibility principle principios ejemplos python dependency-injection

python - single - solid android



¿Hay un punto para el contenedor de inyección de dependencia en Python? (2)

no tiene un concepto utilizable de programación basada en interfaz (como en las interfaces C #)

El hecho de que el compilador no pueda comprobar que está utilizando la interfaz correctamente no significa que no haya "ningún concepto utilizable de interfaces". Se documenta una interfaz y se escriben pruebas unitarias.

En cuanto a los globales, no es como public static métodos public static y los campos en C # o las clases de Java son realmente diferentes. Considera cómo funciona java.lang.Math, por ejemplo. Ahora considera el hecho de que java.lang.Math no es un Singleton. Lo hicieron por una buena razón.

Con todos estos beneficios, ¿hay realmente algún punto para un contenedor de inyección de dependencia?

Lo dudo, pero entonces realmente nunca vi el punto de ellos en C # o Java, tampoco. La inyección de dependencia es una técnica de programación, en mi opinión. Y realmente no hay mucho de eso, tampoco.

Siempre he sospechado que la inyección de dependencia como patrón de diseño era un mal olor creado por todo, debe ser una clase de "pensamiento nazi".

No, no lo es. La inyección de dependencia es una buena idea la mayor parte del tiempo. Tampoco necesitas una clase para inyectar dependencias. Cada vez que pasa algo a una función libre como parámetro, en lugar de que la función llame a otra función para obtener la información, básicamente está haciendo lo mismo: inversión de control. Python también te permite tratar los módulos de forma similar a las clases de muchas maneras (ciertamente más formas que Java y C # do). Hay problemas que pueden resolverse pasando módulos como parámetros a funciones. :)

Hasta ahora creo que puedo cubrir fábricas, Singletons, objetos de varias instancias, solo con el uso de Globals.

Singletons son el mal olor, en todo caso. En casi todos los casos, en mi amplia experiencia, existen porque alguien pensó que sería malo (TM) en principio tener un global, sin realmente pensar en las opciones posibles, o por qué querían ese tipo de acceso a un solo objeto compartido , o incluso por qué los globales son "Bad (TM) en principio" en primer lugar.

Podrías hacer una función global en Python que actúe como una fábrica. Sin embargo, diría que es más Pythonic hacer lo siguiente:

a) primero, asegúrate de que realmente no puedes hacer lo que quieres con __init__ . Quiero decir, en un lenguaje de tipo dinámico, puedes hacer muchísimas cosas de esa manera.

b) Si __init__ no lo corta, intente usar __new__ para controlar el comportamiento.

En Python, las clases son objetos en sí mismos, que son invocables. Por defecto, llamarlos crea una instancia de la clase. Con __new__ , puedes conectarte a eso.

c) Usar un decorador aplicado a la clase. Aquí hay un ejemplo que hace un Singleton (solo porque):

def _singleton(cls): instance = cls() result = lambda: instance result.__doc__ = cls.__doc__ return result @_singleton class example(object): pass

Funciona de esta manera: cuando decora la clase, se llama a _singleton() se pasa la clase. Una instancia se construye y se almacena en caché, y _singleton() devuelve una función anónima que devolverá la instancia cuando se llame. Para completar la charada, la documentación de la clase se adjunta a la función anónima. Luego, Python vuelve a vincular el nombre de la clase en el ámbito global a la función anónima devuelta. Así que cuando lo llamas, obtienes la misma instancia de la clase, cada vez.

Ahora, esto todavía se puede solucionar, por supuesto (puedes hacer algo como example().__class__() para obtener otra instancia), pero es mucho más claro que estás haciendo algo mal que simplemente ignorando una función de fábrica Para poder utilizar el constructor normalmente. Además, significa que el código de llamada en realidad actúa como si estuviera llamando al constructor normalmente :)

El Duck Typing es lo que me está haciendo en este momento, por lo que estoy acostumbrado a definir interfaces y luego basar las clases en estas interfaces y dejar que las cosas estáticas cubran mi estupidez. Siento que sin tipografías estáticas, los contenedores son un poco inútiles.

Debe cambiar su forma de pensar: deje de preocuparse por lo que se le ha pasado y preocupándose de si puede hacer lo que quiere que haga . Así es como funciona la escritura de pato.

He estado jugando con python, como de costumbre, hace que mi rígido y estático mundo orientado a objetos orientado a objetos se convierta en un poco desordenado. Python admite la escritura de pato, no tiene un concepto utilizable de programación basada en interfaz (como en las interfaces C #) y permite variables globales. Con todos estos beneficios, ¿hay realmente algún punto para un contenedor de inyección de dependencia o el tiempo de ejecución de Python se convierte en el contenedor?

Entiendo el punto de estos contenedores en lenguajes OO de tipo estático, como Java y C #, pero ¿dónde encajaría tal cosa en el mundo chiflado de python (me encanta)?

Siempre he sospechado que la inyección de dependencia como patrón de diseño era un mal olor creado por todo, debe ser una clase de "pensamiento nazi" que es c # y Java, ¿sería correcto o hay algo que me falta?

Hasta ahora creo que puedo cubrir fábricas, Singletons, objetos de varias instancias, solo con el uso de Globals. También sospecho que las cosas de Aspect están cubiertas también, aunque todavía estoy pensando en esto.

El Duck Typing es lo que me está haciendo en este momento, por lo que estoy acostumbrado a definir interfaces y luego basar las clases en estas interfaces y dejar que las cosas estáticas cubran mi estupidez. Siento que sin tipografías estáticas, los contenedores son un poco inútiles.

editar

Creo que no usaré los marcos / contenedores del inyector de dependencia cuando use python. Realmente no hay ningún punto. Después de pensar y leer las respuestas hasta el momento, se deja claro el argumento de que sin las definiciones de tipo estático, las promesas hechas son tan vagas que el motivo es una molestia. La tipificación del pato es lo que es, y la única promesa puede hacerse a través de la documentación. Siempre que la referencia entre en la Clase Método / función a través de un parámetro de firma, y ​​no llegue al éter del entorno de programación, creo que estaré a salvo.

Sin embargo, alarmante es el hecho de que no puedo imponer mi voluntad a los demás a través de mis prácticas de diseño de cojinete, como lo he hecho en Java y C #. Me importa ...... nah :)


La conclusión

(La siguiente es la parte más relevante de la publicación original. Admito que me enceré un poco poéticamente, así que pensé que simplemente debería incluir las oraciones más importantes en su propia sección. Dicho esto, creo que la depilación poética es importante basta con que no lo haya borrado.)

La inyección de dependencia todavía se utiliza. Siempre habrá la necesidad de que los objetos se comuniquen con los objetos ya instanciados. Habrá una necesidad de objetos "padres" (o contenedores, o lo que sea) para configurar el estado de sus "hijos". Estos deberán ser transmitidos a través de algún método o establecidos a través de alguna asignación, pero en el sentido abstracto, es lo mismo.

La respuesta original:

Sistemas tipo

Python es, de muchas maneras, el segundo lenguaje más matemáticamente puro que he encontrado, solo sigue a Scheme (aunque nunca he usado Haskell, entiendo que estar allí también).

Python admite cierres de forma nativa, tiene continuaciones (sintaxis de rendimiento), herencia múltiple y una sintaxis de comprensión de bucle que es en gran medida sin paralelo. Todo esto lo acerca mucho más a la visión original de Alonzo Church en Lambda Calculus (las ideas originales de McCarthy detrás de Lisp). Python 3 lo hace aún más puro con la comprensión de conjuntos (lo que hace que mi corazón se agite solo de pensar en su belleza inherente).

Constante y continuamente existe la idea de que los datos almacenados en las variables de Python tienen más en común con sus contrapartes en Matemáticas, tanto que la interfaz de un objeto puede reducirse para ser simplemente ", los adjetivos o conjunto de adjetivos que describen el objeto". Básicamente, la interfaz de un objeto está total y completamente contenida en su __dict__ y se muestra con dir .

Considerando todo esto, empieza a preguntarse si la forma "tradicional" de ver las cosas ("tradicional" con citas porque Python es tan antiguo como Java) realmente puede funcionar en ese lenguaje. Cuando incluso las listas de argumentos en Python tienen un sentimiento de POO (kwargs, ¿alguien?) Realmente da la vuelta al mundo.

La inyección de dependencia todavía se utiliza. Siempre habrá la necesidad de que los objetos se comuniquen con los objetos ya instanciados. Habrá una necesidad de objetos "padres" (o contenedores, o lo que sea) para configurar el estado de sus "hijos". Estos deberán ser transmitidos a través de algún método o establecidos a través de alguna asignación, pero en el sentido abstracto, es lo mismo. Pero existe una confianza implícita en que el contenido del __dict__ del objeto pasado contendrá una descripción apropiada. Debido a esto, se vuelve mucho menos, "una vez que haya creado una instancia de este objeto, le otorgaré las mismas cosas que se necesitan para la vida", y mucho más, "Bueno, sí, un objeto necesita un estado, así que dandole uno ".

Y esto expone un aspecto oculto de la escritura estática. Para que algo que espera que un IFoo funcione, debe tener un conocimiento completo de lo que significa ser un IFoo , incluso si nunca necesitará el 90% de esa definición. Mientras tanto, la escritura de pato hace que el objeto dependiente sepa solo que las propiedades X, Y y Z deberían estar allí en tiempo de ejecución.

Globales

En cuanto a los globales. Evítalos a menos que no tengas otra opción. Es mejor que utilice un Singleton solo porque Singleton le permite iniciar sesión cuando cambia el valor. Esto no es cierto para los globales.

Hay una regla de programación: cuanto más expuesta y complicada sea su interfaz, más difícil será mantenerla. Si algo se coloca en una variable global, cualquier cosa en ese módulo, y posiblemente cualquier cosa en CUALQUIER módulo puede modificar el valor. El código casi puede volverse no determinista. Te lo aseguro, la tristeza sigue.