2009-10-23 18 views
7

Digamos que hay un método que busca autores de libros por ID de libro. ¿Qué se debe pasar como parámetro para dicho método, solo book.id (int) u objeto de libro completo?Si solo se requiere un campo de objeto en un método, ¿qué se debe pasar como parámetro, un objeto o un valor de campo?

u otro ejemplo. En Java necesito hacer algo de trabajo con la URL actual de la página. ¿Qué se debe pasar a dicho método, solo request.getRequestURL() o solicitud completa?

I tipo de ver los beneficios de cada método, pero no se puede encontrar una buena regla cuando usar qué.

Gracias.

Respuesta

10

No estoy seguro de si hay una "regla" para lo que es mejor, pero a menudo paso solo los parámetros que necesito en el método. Por lo tanto, en su primer ejemplo solo pasaría el book.id y en su segundo ejemplo solo pasaría el request.getRequestURL().

Intento evitar pasar más de lo necesario.

+0

He eliminado mi propia publicación y la recomiendo porque veo que el título de la pregunta hace que mi respuesta anterior sea incorrecta. – David

+0

No creo que esto sea correcto. Ciertamente hay varias reglas que se aplican aquí. (Consulte la respuesta tardía para más detalles.) – alphazero

2

Me gustaría dar a cada método tanto como sea necesario (por lo que para la segunda pregunta: simplemente dale request.getRequestURL()).

Para la primera, pensaría en definir ambos métodos (pero prefiero id -uno, ya que puede obtener fácilmente la ID si tiene un Libro, pero no al revés).

findAuthorsForBookId(int bookId) 
findAuthorsForBook(Book b) 
1

No existe una regla en realidad, debe ser directo con la información que necesita, en ese caso el book.id. Si considera ampliar/compartir su búsqueda en el futuro, puede tener un método sobrecargado para aceptar un objeto libro para que pueda buscar por otros atributos del objeto libro.

0

Si está escribiendo un tipo de DAO, debería considerar tener un BookSelector que se puede compilar como: new BookSelector().byId(id).bySomethingElse(somethingElse) y pasar este selector en lugar de tener una proliferación de métodos findByXYZ.

3

Conectividad más débil es preferible a menos que haya razones específicas. Cuando pase la identificación del libro solo al método de búsqueda, puede cambiar la interfaz del libro sin preocuparse de que pueda afectar otras funciones. En algún momento en el futuro, puede descubrir que necesita hacer exactamente el mismo trabajo con alguna URL fuera del controlador de solicitudes, por lo que es bueno evitar la dependencia innecesaria a petición. Pero tenga en cuenta que si llama con frecuencia al do_smth(request.getRequestURL()) puede ser bastante molesto.

3

Esto está relacionado con el Law of Demeter, que básicamente establece que los objetos y métodos solo deberían recibir exactamente lo que necesitan, en lugar de pasar por otro objeto para obtener lo que realmente necesitan. Si necesita utilizar varios campos de Book en su método, podría ser mejor simplemente tomar un libro. Pero, en general, tendrá menos acoplamiento en un sistema si solo depende de lo que necesita exactamente.

En ambos ejemplos, solo sería preferible utilizar el ID o la URL. Particularmente en el caso de la URL, donde (si desea probar el método) es fácil crear una URL para probar pero más difícil (y completamente innecesario) para crear una solicitud para pasar al método que solo usará la URL. de todas formas. El método también se aplica de manera más general a otras situaciones distintas a las que tiene un objeto de solicitud.

+0

Bueno, si un Libro es un parámetro del método M, M puede invocar métodos en sus parámetros (como Book.getId()) sin violar la Ley de Demeter. Eso es solo un punto – TrueWill

+1

Hay 0 puntos si solo toma la identificación ... admitir que no es tan malo con un punto, pero creo que en el caso de la URL es particularmente obvio que está pasando algo completamente innecesario si proporciona la solicitud. – ColinD

+1

Supongo que diré que está relacionado con la Ley de Demeter ... Creo que la intención se aplica aquí. – ColinD

0

Acepto los carteles anteriores. Quería agregar que si se encuentran necesitando múltiples propiedades del objeto (id, título, autor), entonces sugeriría pasar el objeto (o una interfaz al objeto).Las listas cortas de parámetros son generalmente preferibles.

1

Piense en mantener el código a la larga. Cualquier método que expongas es un método que tendrás que respaldar para tus usuarios en el futuro. Si bookId es todo lo que se necesita para el futuro previsible, entonces me limitaré a pasar eso: de esa manera, cualquiera que tenga un bookDi puede usar su método, y se vuelve más poderoso.

Pero si hay una buena posibilidad de que necesite refactorizar la búsqueda para usar otros atributos de Book, pase el libro.

2

Llame book.authors().

2

. (Nota: esta es una opinión discrepante con respecto a la respuesta aceptada)

Bueno, no hay una regla implícita establecido en el contexto de modelado de dominio. Si el receptor realiza tareas independientes del modelo de dominio, entonces pasa el campo. De lo contrario, debe pasar el objeto y la acción específica del modelo se hace explícita por el hecho de que el receptor acceda a la propiedad id del objeto 'Libro'. Lo que es más importante, si el acceso a la propiedad evoluciona más allá de simplemente devolver la referencia de un campo (por ejemplo, ciertas acciones en el acceso a la propiedad), entonces NO querrá perseguir todas las instancias en su código donde haya desreferenciado la propiedad antes de pasarla a varios métodos .

Otras consideraciones son las consecuencias (si las hubiera) de acceder al campo antes de la cita de llamada, o dentro del receptor.

6

Voy a ser un disidente y argumentar a favor de pasar todo el objeto Libro.

Motivo 1: comprobación del tipo. Si solo pasa una ID entera, no hay manera de saber, mirando el código, si tiene el "tipo" correcto de ID entero. Tal vez ha estado pasando una variable entera que cree que es la ID del libro, pero en realidad es la ID del autor. El compilador no lo ayudará a detectar este error, y los resultados serán impredecibles de forma inesperada.

Motivo 2: pruebas futuras. Algunos han argumentado que si solo pasa la identificación, se da la opción de cambiar la estructura del objeto Libro más adelante, sin romper el método doSomethingWithBook (int ID). Y eso es verdad Por otro lado, si pasa todo el objeto Book, se da la opción de cambiar las partes internas de doSomethingWithBook (Book book) (tal vez querrá buscar basado en algún otro campo en el futuro) sin romper ninguna de las (posiblemente numerosos) lugares a los que ha llamado doSomethingWithBook. Yo diría que este último te ayuda más.

En el caso de la Solicitud, daría una respuesta diferente, ya que consideraría un objeto Request estrechamente vinculado a cierto tipo de interfaz (web) y, por lo tanto, querría limitar el uso de ese objeto. Una pregunta que me gustaría hacerme a mí mismo: si quisiera cambiar esta aplicación web para que sea, por ejemplo, una aplicación de línea de comandos, ¿cuántas clases tendrían que cambiar? Si estoy pasando la solicitud, eso va a "infectar" más clases con lógica específica de la web.

+0

Creo que esto tiene sentido en el caso del Libro, aunque diría que si estuvieras en algún momento tomando una identificación y haciendo un Libro solo para envolverlo para pasar al método, estarías haciendo algo mal. En el caso de URL, dado que la solicitud no es un objeto de dominio, diría que nunca sería correcto pasar la solicitud. – ColinD

+0

El envío de objetos completos me parece una mejor opción también por esos motivos. No hubo puntos de vista alternativos en las respuestas, así que tuve que elegir el más popular. Ahora que hay algunos, probablemente "dejaré de aceptar" la respuesta y veamos cuántos seguidores podría obtener este enfoque. – serg

0

Digamos que hay un método que busca autores de libros por ID de libro. ¿Qué se debe pasar como parámetro para dicho método, solo book.id (int) u objeto de libro completo?

Estoy asumiendo que "autores de libros" es un atributo de un libro.Por lo tanto, me imagino algo parecido a la siguiente clase:

class Book { 
    private int id; 
    private List<Author> authors; 
    // ... maybe some other book information 
    public int getID() { 
     return this.id 
    } 
    public void setID(int value) { 
     this.id = value 
    } 
    public List<Author> getAuthors() { 
     return this.authors.clone(); 
    } 
    // ... 
} 

Dado un objeto instanciado libro (aBook), para determinar la lista de autores, yo esperaría que puedo llamar aBook.getAuthors(), que no requiere ningún parámetro.

No recomendaría la creación de objetos de dominio parcialmente instanciados. En otras palabras, dado un bookid, y en busca de una lista de autores, me gustaría que el código de cliente para buscar la misma familia:

Book aBook = library.findBook(bookid); 
List<Author> authors = aBook.getAuthors(); 

y menos como esto:

Book bookQuery = new Book().setID(bookid); // partially instantiated Book 
Book aBook = library.findBook(bookQuery); 
List<Author> aBook = book.getAuthors(); 

La primera versión reduce la cantidad de objetos desechables creados por el código del cliente. (En este caso, bookQuery, que no es un libro real.)

También hace que el código sea más fácil de leer y, por lo tanto, de mantener. Esto se debe a que bookQuery no está haciendo lo que el programador de mantenimiento esperaría. Por ejemplo, esperaría que dos libros con el mismo ID tengan el mismo título, autores, ISBN, etc. Estas afirmaciones fallarían en bookQuery y aBook.

En tercer lugar, minimiza la posibilidad de que algún día pase un objeto de libro no válido (parcialmente instanciado) a un método que está esperando un libro real. Este es un error donde la falla (en el método) puede ocurrir lejos de la causa (la instanciación parcial).

Cuestiones relacionadas