Параметры конструктора - эмпирическое правило

Если я правильно понимаю вашу проблему, вы сначала фиксируете заказ клиента в приложении «Касса» и сохраняете его в базе данных 1 (TempPosOrderPayment), затем платеж подтверждается, и вы копируете этот заказ в приложении «Платеж» в другое база данных (PosOrderPayment).

Предполагая, что вы используете две отдельные базы данных, приведенный выше сценарий выглядит разумным, хотя и подвержен ошибкам - что если вы забудете удалить запись из TempPosOrderPayment после ее копирования в PosOrderPayment?

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

22
задан Mogsdad 27 September 2015 в 01:55
поделиться

9 ответов

При таком количестве параметров пришло время рассмотреть шаблон Builder . Создайте класс построителя, который содержит все эти методы получения и установки, с помощью метода build (), который возвращает объект класса, который вы действительно пытаетесь построить.

Пример:

public class ReallyComplicatedClass {
    private int int1;
    private int int2;
    private String str1;
    private String str2;
    // ... and so on
    // Note that the constructor is private
    private ReallyComplicatedClass(Builder builder) {
        // set all those variables from the builder
    }
    public static class Builder {
        private int int1;
        private int int2;
        private String str1;
        private String str2;
        // and so on 
        public Builder(/* required parameters here */) {
            // set required parameters
        }
        public Builder int1(int newInt) {
            int1 = newInt;
            return this;
        }
        // ... setters for all optional parameters, all returning 'this'
        public ReallyComplicatedClass build() {
            return new ReallyComplicatedClass(this);
        }
    }
}

И в своем клиентском коде:

ReallyComplicatedClass c = new ReallyComplicatedClass.Builder()
        .int1(myInt1)
        .str2(myStr2)
        .build();

См. Страницы 7-9 из Effective Java Reloaded [pdf], презентация Джоша Блоха на JavaOne 2007. (Это также пункт 2 в Effective Java 2nd Edition , но я не Я не могу его процитировать.)

37
ответ дан 29 November 2019 в 03:43
поделиться

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

12
ответ дан 29 November 2019 в 03:43
поделиться

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

2
ответ дан 29 November 2019 в 03:43
поделиться

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

Использование установщиков не решает проблему класса, имеющего много зависимостей / параметров. Он просто перемещает проблему в другое место и не заставляет вводить параметры.

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

Шаблон строителя, упомянутый mmyers, также является хорошим решением при строительстве сложных объектов, и нет способа сделать их менее сложными.

2
ответ дан 29 November 2019 в 03:43
поделиться

Обычно я бы сказал, что не более пяти, из правила 7 +/- 2 на короткий срок память и некоторый пессимизм в отношении внимания программистов. Примечание: я бы посчитал список varargs как одну сущность.

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

1
ответ дан 29 November 2019 в 03:43
поделиться

Code Complete 2 рекомендует довольно разумный предел семи параметров для любого метода.

Попробуйте установить разумные значения по умолчанию для некоторых членов. Это позволит вам использовать getter / setters, не беспокоясь о том, что характеристика неполна.

8
ответ дан 29 November 2019 в 03:43
поделиться

Не думаю, что вы можете сказать, что подходящим числом является «семь, не более» или «пять».

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

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

Пример плохого конструктора:

public NightWatchman(int currentFloor, int salary, int hapiness) {...}

Здесь NightWatchman создается с некоторыми значениями по умолчанию, которые почти наверняка изменятся за короткое время. Забавно, что объекту рассказывают об их значениях одним способом, и затем использует их другим способом (через их установщики) в будущем.

Пример лучшего конструктора:

public GateWatchman(Gate watchedGate, boolean shootOnSight) {...}

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

У меня может быть класс с именами ShootingGateWatchman и PoliceCallingGateWatchman - то есть параметр интерпретируется как часть идентификатора объектов.

5
ответ дан 29 November 2019 в 03:43
поделиться

Это зависит.

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

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

0
ответ дан 29 November 2019 в 03:43
поделиться

Как насчет передачи объекта Param => Value Map в конструктор? Если вызывающая сторона пропускает какие-либо критические параметры, пусть конструктор выбросит исключение.

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

-2
ответ дан 29 November 2019 в 03:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: