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

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

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

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

спасибо.

12 ответов


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

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


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

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

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

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


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


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

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


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

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

findAuthorsForBookId(int bookId)
findAuthorsForBook(Book b)

вызов book.authors().


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

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

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


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


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

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


Если вы пишете своего рода DAO, вы должны рассмотреть возможность наличия BookSelector который может быть построен как:new BookSelector().byId(id).bySomethingElse(somethingElse) и передайте этот селектор вместо распространения методов findByXYZ.


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


допустим, есть метод, который ищет авторов книг по идентификатору книги. Что следует передать в качестве параметра в такой метод-только книга.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();
    }
    // ...
}

учитывая экземпляр объекта книги (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 не делает то, что ожидал бы программист по обслуживанию. Например,я ожидал бы, что две книги с одинаковым идентификатором будут иметь одинаковый tite, authors, ISBN и т. д. Эти утверждения не для bookQuery и aBook.

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