Вопрос о дизайне: передайте поля, Вы используете или передаете объект?

Если вы хотите глубокое копирование без переопределения при сохранении той же obj ссылки

obj = _.assign(obj, _.merge(obj, [source]))

12
задан Kyle Kaitan 7 July 2009 в 14:21
поделиться

12 ответов

Честно говоря, это зависит от рассматриваемого метода.

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

Если метод полагается на объект, тогда достаточно честно передать объект.

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

6
ответ дан 2 December 2019 в 21:04
поделиться

Это зависит от цели вашего метода.

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

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

3
ответ дан 2 December 2019 в 21:04
поделиться

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

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

ОБНОВЛЕНИЕ

Если налоговая форма не является формой пользовательского интерфейса, все немного меняется. В этом случае я предлагаю раскрыть значение с помощью метода экземпляра GetOwedTaxes () или свойства экземпляра OwedTaxes класса TaxForm , но я бы не использовал статический метод . Если вычисление может быть повторно использовано в другом месте, можно по-прежнему создать статический вспомогательный метод, использующий значения, а не форму, и вызвать этот вспомогательный метод из метода или свойства экземпляра.

2
ответ дан 2 December 2019 в 21:04
поделиться

Одним из преимуществ первой формы является

  1. Абстракция - программирование интерфейса, а не реализация. Это упрощает обслуживание вашего кода в долгосрочной перспективе, так как вы можете изменить реализацию TaxForm, не затрагивая клиентский код, пока интерфейс TaxForm не меняется.
0
ответ дан 2 December 2019 в 21:04
поделиться

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

Тем не менее, , когда вы получаете шесть, семь или более полей, пришло время рассмотреть возможность передачи всего объекта или подмножества полей в класс «полезной нагрузки» (или структуру / словарь, в зависимости от стиля языка). Длинные сигнатуры методов обычно сбивают с толку.

Другой вариант - сделать его методом класса, так что вам не нужно ничего передавать. Менее удобно тестировать,

1
ответ дан 2 December 2019 в 21:04
поделиться

I don't think it really matters. You open yourself to side effects if you pass in the Object as it might be mutated. This might however be what you want. To mitigate this (and to aid testing) you are probably better passing the interface rather than the concrete type. The benefit is that you don't need to change the method signature if you want to access another field of the Object.

Passing all the parameters makes it clearer what the type needs, and might make it easier to test (though if you use the interface this is less of a benefit). But you will have more refactoring.

Judge each situation on its merits and pick the least painful.

1
ответ дан 2 December 2019 в 21:04
поделиться

Я понимаю, что это в значительной степени артефакт используемого примера, и поэтому он может не применяться во многих реальных случаях, но , если функция так сильно привязана к определенному классу, то не должно быть:

double payment = f.calculateTaxesOwed;

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

1
ответ дан 2 December 2019 в 21:04
поделиться

Это то же самое, что и «Введение объекта параметра» из книги Мартина Фаулера по рефакторингу. Фаулер предлагает выполнить этот рефакторинг, если есть группа параметров, которые обычно передаются вместе.

0
ответ дан 2 December 2019 в 21:04
поделиться

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

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

Лично я, вероятно, использовал бы и то, и другое, чтобы сделать код более читабельным:

double calculateTaxesOwed(TaxForm f) 
{
    return calculateTaxesOwed(f.getTaxRate(), f.getIncome());
}

double calculateTaxesOwed(double taxRate, double income) { ... }

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

0
ответ дан 2 December 2019 в 21:04
поделиться

Лично я выберу №2, так как он гораздо более ясен в том, что именно нужно методу. Передача TaxForm (если это то, что я думаю, например Windows Form) воняет и заставляет меня немного съеживаться (> _ <).

Я бы использовал первый вариант, только если вы передаете DTO, специфичный для расчета, например объект IncomeTaxCalculationInfo, который будет содержать TaxRate и Income и все остальное, что необходимо для расчета окончательного результата в методе, но никогда не будет что-то вроде Windows / Web Form.

0
ответ дан 2 December 2019 в 21:04
поделиться

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

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


Общее обсуждение на примере:

Рассмотрим функцию для создания растрового изображения для визитной карточки. Назначение функции

(1) // Форматирует заголовок визитной карточки из имени и фамилии

ИЛИ

(2) // Форматирует заголовок бизнес-карты из Человек запись

Первый вариант более общий, с более слабым сцеплением, что обычно предпочтительнее. Однако во многих случаях менее устойчивы к запросам на изменение - например, рассмотрим «случай 2017: добавление лиц, начальных на визитную карточку».

Изменение реализации (добавление person.Initial) обычно проще и быстрее, чем изменение интерфейса.

В конечном итоге выбор заключается в том, какие изменения вы ожидаете: более вероятно, что больше информации от Person требуется запись, или более вероятно, что вы хотите создать заголовки визитных карточек для других структур данных, чем Person ?

Если это «не определено», и вы не можете использовать это специально (1) или (2) Я бы предпочел (2) для синтаксической чистоты.

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

If это «не определился», и вы не можете использовать opf для цели (1) или (2), я бы предпочел (2) для синтаксической чистоты.

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

If это «не определился», и вы не можете использовать opf для цели (1) или (2), я бы предпочел (2) для синтаксической чистоты.

0
ответ дан 2 December 2019 в 21:04
поделиться

If you believe in the Law of Demeter, then you would favor passing exactly what is needed:

http://en.wikipedia.org/wiki/Law_of_Demeter

http://www.c2.com/cgi/wiki?LawOfDemeter

0
ответ дан 2 December 2019 в 21:04
поделиться