2016-10-20 8 views
0

Наше приложение построено несколько вокруг Context класса со многими примитивными полями и булевы Контекст пропускают вокруг почти весь поток, и решения принимаются на основе логических флагов. Теперь, чтобы реализовать новую функциональность, в контекст добавлено новое логическое значение, и его нужно проверить в 10 разных местах. Общий поток имеет структуру, подобную этому примеру.Refactor булево на основе потока

public void handle(context) { 
    if (context.isBig()) 
    drawBigThing(context) 
    else 
    drawSmallThing(context) 
    //more code 
    ...... handleColor(context) //somewhere deeper in the flow/stack 

} 

private void handleColor(context) { 
    if (context.isBig()) 
    takeMoreColor(context.getColor()) 
    else 
    takeLessColor(context.getColor()) 
} 

Как вы видите в разных частях кода, мы оглядываемся на один и тот же флаг, но принимаем различные решения на его основе. Теперь, если я добавлю context.isVeryBig(), вы можете увидеть, как это может взорваться.

Каковы некоторые идеи (по инструментам java 8) для рефакторинга булевского флага, который запрашивается из методов/классов с разными обязанностями, но все еще интересуется одним и тем же флагом?

Одна из идей заключалась бы в том, чтобы сделать контекст более умным, а не содержать логические флаги, но государство/стратегию для каждой из обязанностей, но это устраняет обязанности в контексте (может быть, каким-то образом они могут быть отделены?), Я все равно имеют IFs, но по крайней мере они будут сгруппированы в одном месте и до начала потока

+1

А) да , вам лучше избавиться от такого подхода. У вас в основном много глобального состояния, и прямой доступ к полям не делает его лучше. B) State и Statemachine, а полиморфизм - это «общие» ответы в OO здесь. – GhostCat

+0

См. Https://sourcemaking.com/refactoring/smells/switch-statements, который относится к вашему делу IMO. – JnRouvignac

ответ

0

Это концептуальный вопрос. Так что, возможно, я не отвечаю полностью.

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

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

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

я все равно будет иметь МСФ, но по крайней мере они будут сгруппированы в одном месте и до того, как поток начинает

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

Предлагаю вам два способа решения темы.

1) Гибкая обработка с полной реализацией манипулирования конкретных обработчиками

Интерфейс:

public interface FlowHandler{ 

    void handle(Context context); 
} 

и в реализации по мере необходимости (в соответствии с вашим booleaans, которые делают поведение из поток для изменения):

public class BigFlowHandler implements FlowHandler { 

    public void handle(Context context){ 
      drawBigThing(context); 
      takeMoreColor(context.getColor()) 
    } 
} 

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

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

2) Предустановленный процесс, ограничения шагов для обработки и Факторизуют обработку шагов

Вы можете сделать это, объявив конкретный метод (handle(Context context) в конкретном классе (FlowHandler), которые цепи необходимы операции для любого выполненный поток. Вызываемые операции основываются на заводских методах, реализуемых стратегиями.
Конкретного класс (FlowHandler) отвечает на вопрос, что (этапы, процесс и их порядок), вторые ответы на ХАУ (период осуществления стадий процесса)

public interface HandlerOperations{ 
drawThing(Context context); 
takeColor(Context context); 
} 

public class FlowHandler{ 

    public FlowHandler(HandlerOperations handlerOperations){ 
      this.handlerOperations = handlerOperations; 
    } 

    public void handle(Context context){ 
      handlerOperations.drawThing(context); 
      handlerOperations.takeColor(context); 
    } 
}