Если в методе требуется только одно поле объекта, что следует передать в качестве параметра - объект или значение поля? - PullRequest
7 голосов
/ 23 октября 2009

Допустим, есть метод, который ищет авторов книг по идентификатору книги. Что следует передать в качестве параметра этому методу - только book.id (int) или целый объект книги?

Или другой пример. В Java я должен сделать некоторую работу с текущим URL страницы. Что следует передать такому методу - только request.getRequestURL () или весь запрос?

Я вижу преимущества каждого метода, но не могу придумать хорошее правило, когда что использовать.

Спасибо.

Ответы [ 12 ]

10 голосов
/ 23 октября 2009

Я не уверен, есть ли «правило» для того, что лучше, но я чаще всего передаю в метод только те параметры, которые мне нужны. Таким образом, в вашем первом примере я передаю только book.id, а во втором - только request.getRequestURL ().

Я стараюсь не пропускать больше, чем мне нужно.

6 голосов
/ 23 октября 2009

Я собираюсь быть несогласным и спорить о передаче всего объекта Книги.

Причина 1: проверка типа. Если вы просто передадите целочисленный идентификатор, вы не сможете узнать, глядя на код, есть ли у вас правильный «вид» целочисленного идентификатора. Возможно, вы передавали целочисленную переменную, которая, по вашему мнению, является идентификатором книги, но на самом деле это идентификатор автора. Компилятор не поможет вам поймать эту ошибку, и результаты будут ошибочными.

Причина 2: проверка будущего. Некоторые утверждают, что если вы просто передадите идентификатор, вы сможете изменить структуру объекта Book позже, не нарушая метод doSomethingWithBook (int ID). И это правда. С другой стороны, если вы передадите весь объект Book, вы дадите себе возможность изменить внутренние компоненты doSomethingWithBook (Book book) (возможно, он захочет выполнить поиск на основе какого-либо другого поля в будущем), не нарушая ни одного из ( возможно, много) мест, которые вы назвали doSomethingWithBook. Я бы сказал, что последний помогает вам больше.

В случае запроса я бы дал другой ответ, поскольку я бы посчитал объект запроса тесно связанным с определенным типом интерфейса (веб) и поэтому хотел бы ограничить использование этого объекта. Один вопрос, который я хотел бы задать себе: если бы я хотел переключить это веб-приложение, скажем, на приложение командной строки, сколько классов нужно было бы изменить? Если я передам запрос, это «заразит» больше классов с помощью веб-логики.

3 голосов
/ 23 октября 2009

Это связано с Законом Деметры , который в основном гласит, что объекты и методы должны получать только то, что им нужно, а не проходить через другой объект, чтобы получить то, что им действительно нужно. Если вам нужно использовать несколько полей из Book в своем методе, лучше взять книгу. Но в целом у вас будет меньше связей в системе, если вы будете зависеть только от того, что вам нужно.

В обоих ваших примерах, вероятно, предпочтительнее использовать идентификатор или URL. В частности, в случае URL, где (если вы хотите протестировать метод) легко создать URL для тестирования, но сложнее (и совершенно не нужно) создать запрос для передачи методу, который затем будет использовать только URL тем не мение. Этот метод также становится более применимым к другим ситуациям, чем тот, в котором у вас есть объект запроса.

3 голосов
/ 23 октября 2009

Слабое подключение является предпочтительным, если нет особых причин. Когда идентификатор книги передается только методу поиска, вы можете изменять интерфейс книги, не беспокоясь о том, что это может повлиять на другие функции. В какой-то момент в будущем вы можете обнаружить, что вам нужно выполнять точно такую ​​же работу с некоторым URL-адресом вне обработчика запросов, поэтому избегать ненужной зависимости от запроса - это хорошо. Но учтите, что если вы часто звоните do_smth(request.getRequestURL()), это может стать довольно раздражающим.

2 голосов
/ 23 октября 2009

(Примечание: это особое мнение относительно принятого ответа.)

Что ж, в контексте моделирования предметной области существует неявное правило.Если получатель выполняет задачи независимо от модели предметной области, вы пропускаете поле.В противном случае вы должны передать объект, и действие, специфичное для модели, становится явным с помощью действия получателя, обращающегося к свойству id объекта 'Book'.Наиболее важно, если доступ к свойству когда-либо развивается после простого возврата ссылки на поле (например, определенные действия в методе доступа к свойству), тогда очевидно, что вы НЕ хотите преследовать все экземпляры в вашем коде, где вы разыменовали свойство, прежде чем передать его в различные методы.

Дальнейшие соображения - это последствия (если таковые имеются) доступа к полю до вызова, или внутри получателя.

2 голосов
/ 23 октября 2009

Звоните book.authors().

2 голосов
/ 23 октября 2009

Я бы дал каждому методу столько, сколько необходимо (поэтому для второго вопроса: просто дайте ему request.getRequestURL()).

Для первого я бы подумал об определении обоих методов (но предпочел бы один id, поскольку вы можете легко получить идентификатор, если у вас есть Книга, но не наоборот).

findAuthorsForBookId(int bookId)
findAuthorsForBook(Book b)
1 голос
/ 23 октября 2009

Подумайте о поддержании кода в долгосрочной перспективе. Любой метод, который вы выставляете, - это метод, который вы должны поддерживать для продвижения своих пользователей. Если bookId - это все, что нужно для обозримого будущего, я бы просто сказал: таким образом, любой, у кого есть bookId, может использовать ваш метод, и он становится более мощным.

Но если есть хороший шанс, что вам, возможно, понадобится рефакторинг поиска, чтобы использовать некоторые другие атрибуты Book, тогда перейдите в Book.

1 голос
/ 23 октября 2009

На самом деле нет никаких правил, вы должны быть откровенны с необходимой вам информацией, в этом случае book.id. Если вы подумаете о расширении / совместном использовании поиска в будущем, у вас может быть перегруженный метод для принятия объекта книги, чтобы вы могли осуществлять поиск по другим атрибутам объекта книги.

0 голосов
/ 23 октября 2009

Допустим, есть метод, который ищет авторов книг по идентификатору книги. Что следует передать в качестве параметра этому методу - только book.id (int) или целый объект книги?

Я делаю предположение, что "авторы книг" - это атрибут книги. Поэтому я представляю что-то вроде следующего класса:

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();
    }
    // ...
}

Учитывая экземпляр объекта Book (aBook), для определения списка авторов я мог бы ожидать, что я могу вызвать aBook.getAuthors(), который не требует параметров.

Я бы не одобрял создание частично созданных объектов домена. Другими словами, учитывая bookid и ища список авторов, я бы хотел, чтобы код клиента выглядел так:

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

и меньше так:

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

Первая версия уменьшает количество одноразовых объектов, которые создаются клиентским кодом. (В данном случае bookQuery, что не является настоящей книгой.)

Это также облегчает чтение кода и, следовательно, его поддержку. Это потому, что bookQuery не делает то, что ожидал бы программист по обслуживанию. Например, я ожидал бы, что две книги с одинаковым идентификатором будут иметь одинаковое название, авторов, ISBN и т. Д. Эти утверждения не сработают для bookQuery и aBook.

В-третьих, он сводит к минимуму вероятность того, что когда-нибудь вы передадите недопустимый (частично созданный) объект Book методу, который ожидает настоящую книгу. Это ошибка, при которой сбой (в методе) может произойти далеко от причины (частичное создание экземпляра).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...