сокращение списка параметров, приводящее к дублированию кода

Оператор (+) указывает внешнее соединение. Это означает, что Oracle по-прежнему будет возвращать записи с другой стороны соединения, даже если нет совпадения. Например, если a и b являются emp и dept, и у вас могут быть сотрудники, не назначенные для отдела, тогда следующий оператор будет возвращать сведения о всех сотрудниках независимо от того, назначен ли они отделу.

select * from emp, dept where emp.dept_id=dept.dept_id(+)

Короче говоря, удаление (+) может иметь разницу в значении, но вы можете не заметить какое-то время в зависимости от ваших данных!

0
задан Jonathan 31 March 2019 в 00:07
поделиться

2 ответа

BillBundle в качестве объекта параметра представляет собой масштабируемый подход для сокращения списка параметров методов. Как и любая реализация шаблона проектирования объекта параметра , подразумевает также перемещение по коду, обрабатывающему параметры. Опция, позволяющая избежать дублирования кода при получении счетов и передачи их таким методам, как depositCash, может быть совмещена между шаблоном дизайна посетителя для получения счетов и шаблоном разработки метода шаблона обрабатывать их

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

interface BillEmitter {

    int getFives();

    int getTens();

    int getTwenties();

    int getFifties();

    default void accept(Visitor v) {
        v.visit(this);
    }
}

// add BillEmitter implementations as needed

public class SomeBillEmitter implements BillEmitter {

    private Atm atm;

    public SomeBillEmitter(Atm atm) {
        this.atm = atm;
    }

    public int getFives() {
        int theFivesBill = 0;
        // compute the fives bill with the information from ATM
        return theFivesBill;
    }

    public int getTens() {
        int theTensBill = 0;
        // compute the tens bill with the information from ATM
        return theTensBill;
    }

    public int getTwenties() {
        int theTwentiesBill = 0;
        // compute the twenties bill with the information from ATM
        return theTwentiesBill;
    }

    public int getFifties() {
        int theFiftiesBill = 0;
        // compute the fifties bill with the information from ATM
        return theFiftiesBill;
    }
}

Посетители

interface Visitor {

    default void visit(BillEmitter billEmitter) {

        // template method which gets the bills from the billEmitter
        // and pass them to the bill processor

        Billbundle billBundle = new BillBundle();
        billBundle.setFives(billEmitter.getFives());
        billBundle.setTens(billEmitter.getTens());
        billBundle.setTwenties(billEmitter.getTwenties());
        billBundle.setFifties(billEmitter.getFifties());

        processBills(billBundle);
    }

    void processBills(BillBundle billBundle);
}

// add Visitor implementations as needed

public class DepositCashVisitor implements Visitor {

    public void processBills(BillBundle billBundle) {
        // deposit the cash
        ...
    }
}

Использование

public class Atm {
    // add methods which returns information used to emit bills
}

public class Test {

    public static void main(String[] args) {

        Visitor depositCashVisitor = new DepositCashVisitor();

        Atm atm = new Atm();
        BillEmitter billEmitter = new SomeBillEmitter(atm);
        billEmitter.accept(depositCashVisitor);

        // add more bill emitters and visit them with depositCashVisitor
        // or add more visitors and visit billEmitter with them
    }
}
0
ответ дан Valentin Carnu 31 March 2019 в 00:07
поделиться

Ваша BillBundle идея выглядит хорошо для меня. Вы говорите, что вам приходилось многократно писать код:

Billbundle billBundle = new BillBundle();
billBundle.setFives(fives);
billBundle.setTens(tens);
billBundle.setTwenties(twenties);
billBundle.setFifties(fifties);
depositCash(billBundle);

Но действительно ли вы действительно или просто думаете, что можете?

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

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

Это гораздо лучше, чем обойти 4 параметра повсеместно по двум причинам:

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

  2. Гораздо меньше кода на самом деле зависит от типов счетов, которые вы поддерживаете. Допустим, ваша страна переключается на монету в 5 долларов, или вы просто не хотите, чтобы они были в машинах больше ... сколько кода нужно изменить, чтобы избавиться от пятерок? Вам нужно будет изменить код, который подсчитывает счета, и все остальные вещи, которые на самом деле заботятся о суммах каждого счета, но вам не нужно менять код, который просто пропускает эти счета. Они могут просто обойти оригинал BillBundle и не беспокоиться об этом.

Одно изменение, которое я бы предложил, - сделать ваш BillBundle неизменным. Тогда вам не нужно беспокоиться о том, чтобы кто-нибудь изменил его, когда вы передаете его.

Что-то вроде:

class BillBundle
{
    public final int fives;
    public final int tens;
    public final int twenties;
    public final int fifties;

    public BillBundle(int fives, int tens, int twenties, int fifties)
    {
       this.fives = fives;
       this.tens = tens;
       this.twenties = twenties;
       this.fifties = fifties;
    }
}

Я предупрежу вас, что большинство Java-программистов предпочитают методы getter вместо открытых полей final, но для этого нет веских причин.

0
ответ дан Matt Timmermans 31 March 2019 в 00:07
поделиться
Другие вопросы по тегам:

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