oop - programming - Pregunta de diseño: ¿marca el teléfono PhoneNumber, o PhoneNumber se marca solo en el teléfono?
programación orientada a objetos (13)
Esto se vuelve a publicar desde algo que publiqué en DDD Yahoo! grupo.
En igualdad de condiciones, ¿escribe phone.dial (phoneNumber) o phoneNumber.dialOn (teléfono)? Tenga en cuenta posibles requisitos futuros (números de cuenta además de números de teléfono, calculadoras además de teléfonos).
La elección tiende a ilustrar cómo las expresiones idiomáticas de Information Expert, Single Responsibility Principle y Tell Do not Ask están en desacuerdo entre sí.
phoneNumber.dialOn (teléfono) favorece a Information Expert y Tell Do not Ask, mientras que phone.dial (phoneNumber) favorece el principio de responsabilidad única.
Si está familiarizado con el trabajo de Ken Pugh en prefabricación, este es el acertijo de hoja de cálculo ; ¿agregas filas o columnas?
Claramente, la interfaz PhoneUserInterface, que puede obtener una implementación del método PhoneUserFactory.CreatePhoneUser (), tiene un dial de método (Teléfono, Número) que puede usar para marcar el teléfono.
EDIT: respondiendo el comentario. Ninguno. El teléfono debe tener un buttonPressed () o algo así. El usuario ingresa los dígitos / caracteres del número de teléfono a través de esa interfaz.
Claramente, phone.Dial (número)
Meh - User.Dial (número). El teléfono no tiene sentido en el contexto dado. SOL (hablar en voz alta) es una buena manera de pensar sobre esto (aparte de modismos y principios):
Los teléfonos tienen un dial. No pueden marcar por sí mismos. Los números de teléfono son dígitos Los usuarios marcan PhoneNumbers en un dial de teléfono.
Ninguno. El usuario marca un número de teléfono en un teléfono.
No debe ser el negativo aquí, pero este tipo de preguntas son muy académicas. Depende completamente de la aplicación. Puedo pensar en muy buenas razones para hacerlo de cualquier manera, y he visto demasiados buenos programadores empantanarse en este tipo de detalles de diseño discutible.
No estoy seguro de cómo se relaciona eso con el enigma de la hoja de cálculo. ¿Espera, en el futuro, usar teléfonos para marcar números de cuenta? Para usar números de teléfono en las calculadoras? Su ejemplo de "preparación futura de requisitos" no es muy bueno ...
Además, usas el verbo "marcar". Claro, podría imaginarme "marcando" un número de cuenta en un teléfono. (Es un gran tramo, sin embargo). Pero si este número de teléfono se va a usar en una calculadora, ¿llamaría a la acción "marcar"? Si el nombre de la función cambia según el tipo de parámetro que se pasa, tiene un error de diseño.
En un diseño OO típico, los objetos se envían a los mensajes que transportan datos, y no al revés.
No tendría ningún número de teléfono como clase, ya que no tiene ningún comportamiento, solo es un elemento de datos.
Si escribe OO, entonces comienza con el objeto básico, que no es el número, el número va al teléfono, por lo que phone.dial () de esa manera también puede phone.withwer () phone.disconnect () phone.powerOFF , ect.
Otra forma de verlo es si el teléfono marca el número o si el número marca el teléfono.
phone.dial () +1.
¿Cuál es la variante de estado o comportamiento de un PhoneNumber? Lo único que se le viene a la mente son las "reglas de marcado" (marque el código de país si está afuera, marque "9" para obtener una línea externa, etc.). Ese contexto parece muy adecuado para el teléfono.
Si su modelo de objeto no requiere varianza, un número es solo una secuencia de dígitos, "marcar" es solo poro (dígito en número de teléfono) {presionar (dígito); } Estoy con Rob Conery: meh.
phone.dial()
, porque es el teléfono el que marca.
Actor.Verbo (entradas) -> salidas.
A: phone.dial (phone_number)
PhoneNumber es tonto y solo es un conjunto de datos. Cuando ocurre la "marcación", ¿debería saber el objeto PhoneNumber cómo marcar? Hay muchos estados para realizar un seguimiento, como:
- ¿El teléfono ya está en otra llamada? (Si es sí / no, ¿qué hacer?)
- ¿Qué sucede si cambia el método de marcación? (roaming global, diferentes operadores, etc.)
- Además, ¿qué pasa con el alcance? Cuando se realiza una llamada, el número de teléfono debe agregarse a la lista de llamadas salientes recientes.
Si su objeto PhoneNumber necesita saber todo esto, no es DRY y su código será menos portátil y más propenso a fallar.
Diría que Steven A. Lowe lo tiene mal. Esto debe hacerse con un objeto de tipo Controlador para manejar los diferentes estados, etc. Mantenga su objeto PhoneNumber en blanco y dele la inteligencia al intermediario que necesita preocuparse por mantener el teléfono funcionando.
Elegir si se asignan los objetos de columna o los objetos de fila al método de marcación no cambia la forma en que se escalará el programa.
El método de marcado simplemente será una secuencia de métodos de fila y columna. Tienes que preguntar de qué dependen esos métodos.
Si la secuencia de los métodos de fila no depende de saber exactamente qué objeto de columna está involucrado (pero depende de qué objeto de fila particular está involucrado) y viceversa para la secuencia de métodos de columna, entonces el problema se escalará como m + n (m = num. filas, n = num. cols). Cuando crea una nueva fila, en realidad no le ahorra ningún trabajo si se le hubiera asignado al método de columna el método ''marcar''. ¡Todavía tiene que especificar una secuencia única de métodos de filas para usar en ''marcar'' en alguna parte!
Sin embargo, si la secuencia de métodos de columna dentro de ''marcar'' no depende de qué objeto de columna está involucrado (usan una secuencia ''genérica'' de métodos de columna), entonces el problema simplemente se escala como m. En realidad, no importa si ha asignado el método ''marcar'' a los objetos de la columna, el programa todavía se escala como m; esencialmente, no se requiere ningún trabajo para crear un nuevo método de marcado al agregar 1 objeto de columna más y es evidente que tiene la opción de abstraer todos esos métodos de marcado en un solo método de marcado genérico.
la pregunta asume el contexto de la respuesta y, por lo tanto, crea un falso dilema
el "enigma de la hoja de cálculo" es una dicotomía falsa en este ejemplo: las filas y las columnas son la capa de presentación, no necesariamente la capa de datos. Los comentarios a continuación me dicen que malinterpreté la analogía, pero no lo creo, decir "si esto es una fila o una columna, cuál es más probable que cambie" está forzando una elección innecesaria en el espacio problemático, ambos son igualmente probable que cambie Y en este ejemplo específico, esto lleva a elegir el paradigma equivocado [sí correcto ] para la solución. Marcar un teléfono es cómo los dispositivos mecánicos antiguos iniciaron una conexión a otro dispositivo mecánico antiguo; esto no es una analogía adecuada para la telefonía moderna. Y suponiendo que haya un "usuario" para iniciar la llamada, simplemente mueve el problema, aunque lo mueve en la dirección correcta, es decir, lejos del modelo de teléfono rotatorio ;-)
Si nos fijamos en cómo funciona el protocolo TAPI [lo siento sobre el error tipográfico anterior, es TAPI no ATAPI!], Existe un controlador de llamadas, equivalente al "usuario", supongo, en cierto sentido, que gestiona las conexiones entre dispositivos. Un dispositivo no llama a otro, el controlador de llamadas conecta dispositivos. Entonces, el siguiente ejemplo sigue siendo esencialmente correcto. Podría ser más correcto usar un objeto CallController en lugar de una conexión genérica, pero la analogía debería ser lo suficientemente clara como es.
En este ejemplo, un teléfono es un dispositivo con una dirección conocida como ''número de teléfono''. El operador ''marcar'' establece una conexión entre los dos dispositivos. Entonces la respuesta es:
Phone p1 = new Phone(phoneNumber1);
Phone p2 = new Phone(phoneNumber2);
Connection conn = new Connection(p1,p2);
conn.Open();
//...talk
conn.Close();
esto también admitirá llamadas multipartitas, al sobrecargar Connection para incluir una lista de dispositivos u otras conexiones, por ej.
Connection confCall = new Connection(p1,p2,p3,p4,p5,p6);
confCall.Open();
Connection joinCall = new Connection(confCall,p7,p8,conn);
joinCall.Open();
mira el protocolo TAPI para más ejemplos