Как мне разработать метод, который допускает необязательные операции? - PullRequest
2 голосов
/ 28 июня 2010

Например, предположим, что это:

class Gundam00 extends Gundam implements MobileSuit {
    ...

    public void fight(final List<MobileSuit> mobiruSuitso, final List<Gundam> theOtherDudes, final List<Person> casualities) {
        ....
    }
}

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

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

Есть предложения?

Ответы [ 4 ]

3 голосов
/ 28 июня 2010

Я считаю, что последние 2-3 аргумента, способность помнить, что все аргументы функции страдают. И понятность вместе с этим.

Передача именованных аргументов может помочь. Языки с удобным хеш-подобным буквальным синтаксисом делают это действительно простым. Возьми JavaScript:

g = new Gundam00();
g.fight({opponent: enemy, casualties: 'numerous'});

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

g.fight('opponent',enemy,'casualties', 'numerous');

И некоторые языки фактически поддерживают именованные аргументы напрямую (см .: http://en.wikipedia.org/wiki/Named_parameter#Use_in_programming_languages).

Наконец, вы можете рассмотреть возможность добавления для этого других методов, используя то, что некоторые называют Fluent Interface (http://en.wikipedia.org/wiki/Fluent_interface). По сути, у вас есть вызов метода, который возвращает сам объект, поэтому вы можете объединять вызовы вместе:

g.opponent(enemy).casualties('numerous').fight();

Это может быть самый простой вариант, если вы работаете на явно / статически типизированном языке, ориентированном на классы.

Обновление

Отвечая на комментарий Сецуны ... в этом последнем примере, если у вас есть роскошь, вы можете создавать такие методы, как opponent и casualties простые сеттеры, которые не влияют ни на какое внутреннее состояние или вычисления в любом другом путь, чем установка параметра, для которого они названы. Они просто устанавливают внутренние свойства, и тогда вся настоящая работа происходит внутри методов действия, таких как fight.

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

n = new NArgs();  
g.fight(n.arg('opponent',enemy).arg('casualties','numerous').arg('motion','slow'));

Немного более громоздко, но оно отделяет проблему именованных аргументов и позволяет сохранять ваши методы более атомарными, и NArgs, вероятно, можно легко реализовать, просто заключив некоторые методы в один тип Collection (HashTable?) или другой, доступный на вашем языке.

2 голосов
/ 28 июня 2010

Добавьте методы. Методы перегрузки - это, как правило, антипаттерн и возможность рефакторинга для кого-то другого.

http://www.codinghorror.com/blog/2007/03/curlys-law-do-one-thing.html

0 голосов
/ 28 июня 2010

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

public void setOtherDudes(final List<Gundam> theOtherDudes) {} // for input arguments
public List<Person> getCasualities() {} // for output arguments

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

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

0 голосов
/ 28 июня 2010

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

Или ... вы могли бы просто проверить, являются ли они нулевыми.

if(theOtherDudes == null)
    ...
...