Ver Mensaje Individual
  #10 (permalink)  
Antiguo 15/10/2008, 09:06
venkman
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Clase dentro de clase

Debo decir que de todas las posibilidades que me comentas, la de hacer clases internas es la que menos me gusta.

Uno de los aspectos más importantes de la orientación a objetos es el de la separación de preocupaciones (separation of concerns) y el desacoplamiento. La idea es que si diseñas un sistema orientado a objetos, las soluciones que debes buscar deben hacer que los objetos sean lo más atómicos posible.

En este caso un Astro (sea un sol o un planeta) es claramente una entidad independiente. Sí, su funcionamiento va a ocurrir dentro de un SistemaSolar, pero la clase Astro en sí debe estar encapsulada de forma independiente. En general el uso de clases internas no suele ser buena idea, pero desde luego no lo es cuando se trata de entidades que tienen una importancia tan grande en el sistema como es, en este caso, Astro.


Yo más bien tendería a la última opción, que SistemaSolar sea un "contenedor de astros". De este modo tendría una colección de planetas. Y claramente tendría una forma de añadir un astro, aunque yo no lo haría como dices, pasándole nombre, radio, masa, etc, sino pasándole un objeto Astro (no me refiero al mismo Astro que tú, luego comento más). Es decir, SistemaSolar no debe instanciar los astros, sólo debe recibirlos.

A nivel de aplicación sería donde haríamos el astro2 = Planeta(nombre, radio, masa...) y luego sistema.addAstro(astro2).

Ahora, ¿por qué digo estas cosas?
La razón principal es esta: Con las clases internas estás ligando mucho las clases de tipo Astro al SistemaSolar. SistemaSolar sólo debería funcionar como un contenedor de Astros, sin tener que ocuparse directamente de cómo es cada Astro. Usando clases internas tendríamos que cada vez que quisieras añadir un tipo de Astro nuevo tendrías que crear una nueva clase interna dentro de SistemaSolar y con toda seguridad hacer cambios en SistemaSolar.

Un nuevo tipo de Astro podría ser uno que tuviera una órbita diferente a la del resto, que girara en sentido contrario por ejemplo o que tuviera una órbita parabólica o hiperbólica (como un asteroide o un cometa quizá) en lugar de elíptica. Y crear algo así no debería afectar a SistemaSolar.

De hecho, lo que debería ser es que SistemaSolar sólo trata con una clase genérica Astro que no es el mismo Astro que tú sino la base de la que deben heredar todos los Astros:

Código python:
Ver original
  1. class Planeta(Astro):
  2.     #...
  3.  
  4. class Sol(Astro):
  5.     #...
  6.  
  7. class Cometa(Astro):
  8.     #...
  9.  
  10. class Sistema:
  11.     #...
  12.     def addAstro(self, astro):
  13.         #...

En caso de añadir ahora un Asteroide, no necesitamos cambiar SistemaSolar para nada, sólo añadir una clase Asteroide que herede de Astro (e implemente los métodos que tiene que implementar cualquier Astro, claro).



Las propiedades que comentas como color de fondo o nivel de zoom, realmente no son una preocupación directa de la que se deban ocupar los planetas. En realidad es algo que concierne únicamente a quien pinta el sistema completo (color de fondo) o a quien toma la decisión de qué planetas pintar. El zoom no le interesa realmente a los planetas. Sino que es el sistema solar el que determina en un momento dado qué planetas deben pintarse o no pintarse y en qué posición. Lo mismo ocurre con el paso del tiempo. Son propiedades que afectan a todo el sistema por igual, no independientemente a cada uno de los planetas y por tanto debe ser preocupación del sistema llamar "más rápido" o "más lento" a que se pinten los planetas (entendiendo por esto no llamarlos más rápido realmente sino contar más rápido el tiempo y calcular las posiciones de los planetas de acuerdo a esa velocidad).


Al final todo se reduce a lo mismo, tratar de separar las preocupaciones y que cada entidad se ocupe sólo de lo que se tiene que ocupar realmente.


Ahora tengo que salir, pero si quieres lo seguimos hablando. bye.