2010-10-25 4 views
8

En mi aplicación tengo un Controller que se inició con el método principal. El controlador inicializa ganchos, conexiones de bases de datos, la interfaz de usuario, otra conexión y otras cosas. Tiene la mayor parte del estado del programa (no, no es un Singleton). En otro ejemplo, hay un controlador para el bot que maneja la interpretación y el envío de comandos. Ambos son archivos bastante grandes.¿Cómo puedo escribir un controlador sin convertirlo en un objeto de Dios?

He leído sobre los objetos de Dios, pero realmente no conozco una manera de dividirlo. Si dividí el intérprete y el despachador en el bot, se creará una horrible cadena de llamadas (algo así como getBot().getParser().getOutput().sendMessage(recipient, message)). De manera similar, en el primer controlador, si dividía las cosas, solo tendría objetos de datos que contengan campos y algunos métodos de utilidad de alias. Dividirlos empeoraría las cosas. Y antes de asumir que es imposible de mantener, en realidad no lo es. Ni siquiera escribí el controlador Bot, pero todavía sé qué está pasando.

El problema es que la clase Bot tiene 2000 líneas de longitud (probablemente más corta si saqué los comentarios de Javadoc) y el Bot tiene aproximadamente 1000 líneas de longitud. Muchas líneas = objeto de Dios. Pero, ¿está bien para una o dos clases principales de un proyecto?

+0

Relacionado: [Diseñar una clase de tal manera que no se convierta en un "objeto de Dios"] (http://stackoverflow.com/questions/2589703/designing-a-class-in-such-a- way-that-it-doesnt-become-a-god-object) –

+0

@jleedev He visto eso, pero este es un problema un poco diferente. El OP que podría haber de subobjetos hechos funciona bien, ya que era todo interno. Mi caso, sin embargo, es un controlador de API de cara al público que necesita ser simple en el que no puedo hacer que ningún otro objeto haga el trabajo. – TheLQ

Respuesta

11

"Lotes de líneas" no significa que la clase sea un objeto divino en absoluto, ese es un terrible punto de referencia terrible para determinar si debes o no refacturar algo. Algunas cosas son muy complicadas y justifican un objeto complicado e inherentemente grande. La idea de un objeto de Dios es lo que la clase hace.

Por ejemplo si he hecho un objeto que podría

DoMyTaxes() 
GiveMeHugs() 
LogThisError() 
StartGameLoop() 

El objeto podría calificar como un objeto de dios, incluso si sólo puede ser de 100 líneas de código. La idea básica es que todo lo anterior no tiene ninguna relación (en el extremo lógico del negocio del espectro) entonces, ¿por qué en el mundo serían todos parte del mismo objeto? Si decidiera hacer que los abrazos duraran más, podría acabar arruinando mis impuestos. Ingrese el IRS.

Sin embargo, si está trabajando en un simulador de la física, digamos, y la clase Classical() tendría métodos/objetos tales como:

Space() 
Time() 
Velocity() 
Speed() 
Mass() 
Acceleration() 
Gravity() 
Force() 
Impulse() 
Torque() 
Momentum() 
AngularMomentum() 
Inertia() 
MomentOfInertia() 
ReferenceFrame() 
Energy() 
KineticEnergy() 
PotentialEnergy() 
MechanicalWork() 
VirtualWork() 
DAlembertsPrinciple() 

(cortesía de Wikipedia)

Este objeto no lo haría ser un objeto de diosEs un objeto complejo. Todo lo que trata con la física newtoniana lo atraviesa, pero no es un objeto de Dios ... simplemente es un objeto realmente grande. Lo anterior podría terminar siendo miles de líneas de código. El objeto Quantum() sería aún más complejo, no hace falta decirlo.

Para reiterar, la idea es sobre el comportamiento de un programa , no flujo de datos:

que no les importa si un solo objeto tiene una gran cantidad de datos de la aplicación, o si la mayoría de los flujos deben pasar por un único objeto. Lo que tiene más impacto en maintenability es cuando un solo Dios Clase (tm) tiene demasiado comportamiento (código comercial).

Si cree que hay un problema, usted podría tratar de poner en práctica diferentes formas de mediation, o patrones más desagradables tales como dependency injection.

+0

Buena respuesta. Siguiendo ese principio, supongo que mi objeto es simplemente complejo, ya que maneja el análisis sintáctico, la salida y los ganchos (aunque los ganchos se están moviendo). Gracias por la respuesta – TheLQ

+0

muy buena respuesta, +1 –

3

Si no se siente cómodo con el tamaño y la complejidad de una clase, suele ser un buen indicador de que se puede hacer un mejor diseño. Pero no mida solo el tamaño. Si una clase es fácil de entender y seguir, pero contiene mucho código, eso no significa necesariamente que sea un candidato para volver a factorizar. He visto gente que se deja llevar por esto y el desorden que crean en la búsqueda de hacer cosas pequeñas fue mucho peor que el código original. Por otro lado, he leído las clases de punta a punta varias veces y todavía no tenía idea de lo que hacen.

La pregunta que me haría es: si se lo dijera a otro desarrollador, ¿sería capaz de entenderlo y mantenerlo fácilmente?

Si la respuesta es sí, entonces las probabilidades indican que no necesita hacer nada. Si no, entonces un re-factoring está en orden.

Con referencia a objetos de dios, leyendo su publicación, parece que esta clase está haciendo demasiado. Me pregunto si primero podría volver a factorizar el estado en un conjunto de objetos modelo como punto de partida. Entonces su clase comienza a parecerse más a una fábrica de configuración de algún tipo.

2

Sugeriría que el motor de física/movimiento definitivamente debería estar separado del intérprete de idiomas; aunque el intérprete de idiomas necesitará acceder a algunos de los métodos y propiedades públicos del motor de física, no hay ninguna razón para que los dos aspectos del robot estén en la misma clase. El intérprete de idiomas en sí podría subdividirse en unas pocas clases, al igual que el motor de movimiento. Puede haber un objeto de control maestro, pero debe tener una cantidad relativamente pequeña de código. Es el motor de movimiento principal y el motor de lenguaje principal, todos deben delegar la mayor parte de su trabajo a los objetos que los componen.

0

Creo que el principio clave aquí es "cohesión".

DoMyTaxes() 
GiveMeHugs() 
LogThisError() 
StartGameLoop() 

..is no cohesivo.

Algo así como:

GiveMeHug() 
GiveMeKisses() 
GiveMeHugs(int noOfTimes) 
GiveMeHugs(int noOfTimes, Person person) 
GiveMeHugsAndKisses() 

..es cohesiva ya que todos los métodos son bastante similares. Podrías tener 1000 métodos cohesivos en una clase y todavía no sería un objeto de dios, ya que la responsabilidad de la clase sigue siendo limitada.

Cuestiones relacionadas