¿Debe la lista de parámetros de un método contener objetos o identificadores de objeto?

10

Nuestros equipos están teniendo la siguiente discusión:

Digamos que tenemos los siguientes dos métodos:

public Response Withdraw(int clubId, int terminalId,int cardId, string invoice, decimal amount);

public Response Withdraw(Club club, Terminal terminal,Card card, string invoice, decimal amount);

lo que se envía por cable son solo los identificadores.

un lado dice que el primer método es correcto, porque solo tenemos los identificadores de terminal y club, y debe quedar claro que no tenemos nada más, este es mi enfoque.

el otro lado dice que el segundo método es correcto porque es más flexible.

Estamos familiarizados con la idea del parámetro del objeto, el otro lado también piensa que el parámetro del objeto debe tener los objetos como propiedades.

¿Cuál es el enfoque correcto?

Tal vez hay un tercer enfoque aún mejor?

Mithir
fuente
¿Qué? ...........
James
1
¿Contexto? ¿Servicio web? WCF?
CodesInChaos
1
@ James - lo siento, escribí esta pregunta un poco rápido, ¿puedes decirme qué no se entiende para que pueda editarlo?
Mithir
@CodesInChaos los métodos son métodos BL en realidad
Mithir

Respuestas:

10

La respuesta depende del contexto.

Si se espera que el cliente tenga todos esos objetos ya disponibles , usaría los parámetros del objeto. De lo contrario, su código se verá más complicado de lo que debe ser. (Por ejemplo, tendrán llamadas como club.getId(), por ejemplo).

Si el cliente solo tendrá los identificadores disponibles fácilmente, entonces quizás el segundo enfoque sea mejor, ya que es posible que no desee que el cliente tenga que ensamblar / cargar todos esos objetos si realmente solo necesita los identificadores.

Una opción es proporcionar ambos métodos , para que el cliente pueda elegir cuál usar (dado que esto no satura su API)

En general, los parámetros del objeto son más extensibles, ya que si en el futuro necesita otro dato para hacer el trabajo, no necesita introducir otro método que tome esa información adicional.

Por último, las firmas de su método no deben ser dictadas por los detalles de lo que hace el método (en su caso, qué pasa exactamente por el cable). La API debería tener un sentido abstracto, por lo que si la implementación cambia, no estás jodido.

c_maker
fuente
3
+1 Solo agregaría un punto más: para los métodos llamados de forma remota (¿"a través del cable"?), Pasar objetos puede implicar la serialización profunda de un extenso árbol de objetos. Las ID son excelentes sustitutos de los objetos cuando le preocupa el tamaño de una carga de llamadas remotas.
Ross Patterson
1
En este caso, parece que estás acoplado a un conjunto de abstracciones, por lo que pasar Id no te dará más flexibilidad y probablemente aumentará la probabilidad de que reviertas los parámetros. La pregunta es ¿qué tan estrictamente está el código en el método junto con las abstracciones que estoy pasando? Por ejemplo, un método como "validateCreditCard (tarjeta de cadena, cadena cvi)" probablemente debería permanecer con primitivas para evitar estar estrechamente vinculado con algún tipo de objeto CreditCard.
ipaul
Me reuniría en el medio y usaría una interfaz en la lista de parámetros. Entonces su club puede ser un club, pero también una sauna en el futuro.
Pieter B
13

El primer enfoque es indicativo de la obsesión primitiva . Debido a que está pasando entradas y cadenas, es muy fácil para el programador cometer un error (por ejemplo, pasar un clubId al parámetro terminalId). Esto resultará en errores difíciles de encontrar.

En el segundo ejemplo, es imposible pasar un palo cuando se espera una terminal; esto le daría un error de tiempo de compilación.

Aun así, todavía lo miraría string invoice. ¿Es una factura realmente una cadena? Que amountsignifica Es más probable que sea un valor monetario.

Usted mencionó en su pregunta "lo que se envía por cable son solo los identificadores". Esto es correcto, pero no permita que este requisito enturbie su dominio.

La mejor explicación que he visto a favor de este enfoque fue en la regla 3 de Object Calisthenics :

Un int por sí solo es solo un escalar, por lo que no tiene sentido. Cuando un método toma un int como parámetro, el nombre del método debe hacer todo el trabajo de expresar la intención. Si el mismo método toma una Hora como parámetro, es mucho más fácil ver qué está pasando. Los objetos pequeños como este pueden hacer que los programas sean más fáciles de mantener, ya que no es posible pasar un año a un método que tome un parámetro de hora. Con una variable primitiva, el compilador no puede ayudarlo a escribir programas semánticamente correctos. Con un objeto, incluso uno pequeño, le está dando al compilador y al programador información adicional sobre cuál es el valor y por qué se está utilizando.

MattDavey
fuente
Entonces, ¿se prefiere el segundo enfoque? incluso si hay un objeto club con solo la propiedad id llena?
Mithir
Esto parece ser un blog al azar. No hay evidencia para decir lo que se prefiere. ¿A quién le importa realmente lo que se prefiere? Haga lo que funcione para usted
James
@ James No hay una respuesta definitiva a esta pregunta, especialmente porque el OP no nos ha dado mucho contexto. Cualquiera que afirme categóricamente que un enfoque es preferible al otro está perjudicando a la OP. No es tan blanco y negro.
MattDavey
1
@James Simplemente señalé que el primer enfoque hace que sea muy fácil introducir errores difíciles de encontrar. No digo que los tipos primitivos sean malos, pero el propósito de los tipos primitivos es construir tipos de dominio significativos. Usarlos fuera de este contexto es la definición misma del olor del código de obsesión primitivo.
MattDavey
55
@ James: Lo que MattDavey dijo es un hecho bien establecido. No está diciendo que los tipos nativos son malos, lo que está diciendo es que esto: someMethod (int, int, int, string, decimal) es mucho más difícil de entender y usar por un cliente que someMethod (Club, Terminal, Card, String , decimal)
c_maker
2

No hay una respuesta correcta para esta. Cualquiera de las opciones podría ser adecuada para el trabajo. Bueno, casi de cualquier manera, el argumento de la factura me hizo fruncir el ceño, no tengo idea de qué es eso al leer el código.

Si envía una identificación, ambos sistemas deben estar estrechamente acoplados a lo que eso representa. ClubID es clave en la tabla de clubes. Más aún, tanto la persona que llama como la persona que llama deben acordar cómo se llama la tabla Clubs y en qué base de datos se encuentra. Si no quiere o no puede imponer esa restricción, entonces pasaría el objeto usando una descripción común, nativo, serializado, xml, nombre = valor lo que sea, un archivo ini :)

Eso, como lo identificó, le costará "por cable". Evitar eso simplemente enviando el identificador le cuesta a otro lado. Entonces, cuál te duele menos, ahora (o puede ser más tarde ...) es el indicador de lo bueno frente a lo malo.

Tony Hopkinson
fuente