[Python-es] Pregunta sobre diseño de una biblioteca

Juan Luis Cano juanlu001 en gmail.com
Mie Feb 13 17:12:03 CET 2013


No suelo preguntar nada en esta lista, pero hoy me gustaría plantearos 
una cuestión un poco abierta a la que llevo dando vueltas algunos meses. 
No tengo una formación reglada en programación así que me gustaría 
recabar algunas ideas sobre cómo llevar a cabo este diseño 
DeLaManeraCorrecta™. Os cuento (aviso de que es un email largo, un poco 
denso, posiblemente incomprensible y con algún tecnicismo):

Estoy escribiendo una biblioteca llamada scikit-aero para cálculos 
comunes en ingeniería aeronáutica con Python.

https://github.com/Pybonacci/scikit-aero

Uno de los módulos es de dinámica de gases. Y uno de los «objetos» que 
he definido es `IsentropicFlow`, que representa un flujo con unas 
determinadas características. Tiene varias propiedades, que se pueden 
obtener con expresiones matemáticas definidas en los métodos:

https://github.com/Pybonacci/scikit-aero/blob/master/skaero/gasdynamics/isentropic.py#L65

Al definir un `IsentropicFlow` especifico todas las variables que lo 
determinan *unívocamente*, y de ahí obtengo las propiedades.

Me surgen dos preguntas:

1. (Menos importante) Cada vez que quiero una propiedad de uno de estos 
objetos la calculo con la fórmula matemática y la devuelvo. Por ejemplo, 
defino un `IsentropicFlow` y puedo obtener de él ciertas propiedades en 
función de otro argumento `M`, el número de Mach incidente.

Pero aquí tengo otro ejemplo, los objetos `NormalShock`, que representan 
ondas de choque:

https://github.com/Pybonacci/scikit-aero/blob/master/skaero/gasdynamics/shocks.py#L22

donde las propiedades vienen determinadas por las variables que definen 
el `NormalShock`, nada más.

*Pregunta*: Si no dependen de argumentos extra, ¿tal vez sería mejor 
calcularlas en `__init__`, almacenarlas y simplemente devolver los 
valores cuando se pidan? Si es así, ¿hasta qué punto tiene sentido 
definir una clase, cuando prácticamente podría conseguir lo mismo 
utilizando un diccionario, o un `namedtuple`?

2. (Más importante) Digamos que otro tipo de objetos, `ObliqueShock` 
(ondas de choque oblicuas) vienen caracterizados por dos variables: `M` 
(número de Mach incidente) y `beta` (ángulo de la onda de choque). 
Definido un `ObliqueShock`, puedo obtener su ángulo de deflexión 
correspondiente, `theta`, a través de una relación matemática. Sin 
embargo si conozco `M` y `theta`, esa relación se tiene que resolver 
iterativamente para hallar `beta`, y además hay dos valores posibles 
entre los que tengo que discriminar.

Como me interesa, por motivos prácticos, disponer de una manera de 
instanciar `ObliqueShock` dados `M` y `theta`, mi aproximación al 
problema ha sido crear una función que:

* Recibe como argumentos `M`, `theta` y un argumento booleano que 
discrimina entre las dos soluciones posibles.
* Comienza un proceso iterativo: construye un `ObliqueShock` con `M` 
dado y `beta` cualquiera; si el `theta` resultante es el dado, devuelvo 
ese `ObliqueShock`, en caso contrario sigo iterando.

Una idea parecida está recogida en la función `mach_from_area_ratio`:

https://github.com/Pybonacci/scikit-aero/blob/master/skaero/gasdynamics/isentropic.py#L25

que itera sobre un `IsentropicFlow`.

*Pregunta*: ¿esto va bien? Supongo que sería una idea tipo «factoría» de 
clases. La razón del embrollo es no escribir la misma ecuación «fuera» y 
«dentro» de la clase, teniendo así que repetir código.

Estoy muy interesado en los principios SOLID y en intentar escribir 
código POO de buena calidad pero no parece haber mucho material 
disponible en la red y por otro lado sin una orientación a objetos 
«purista» no me resulta tan sencillo. Cuando programaba en ActionScript 
3 hacía y deshacía con interfaces, encapsulación, herencia... ahora 
Python y su «duck typing» me despistan un poco en este sentido.

Espero no haber aburrido a nadie más de la cuenta, si hacen falta más 
aclaraciones sobre lo anterior las daré gustoso y si alguien tiene 
comentarios sobre esto o sobre otros aspectos del código de scikit-aero 
estaría enormemente agradecido de recibirlos.

Un saludo,

Juan Luis Cano


Más información sobre la lista de distribución Python-es