Плохо ли иметь магические переменные?

#java #oop

#java #ооп

Вопрос:

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

Плохо ли это делать в тестовом классе:

 chef.makeFood();
waiter.deliverFood(chef.getFood())
  

На той же ноте, должен ли я вместо этого сделать это:

 chef.makeFood();
Food f = chef.getFood();
waiter.deliverFood(f);
  

Комментарии:

1. Никакой разницы. Я бы не назвал это «магической переменной». Любой из них достаточно читаем. Это критерий, которому я бы следовал.

2. Я голосую за номер 1, поскольку он кажется менее неуклюжим, но, возможно, это только я. Что было бы проще для вашего будущего «я» дебютировать через 2 месяца или через 2 года?

3. второй пример не является «магической переменной», имхо, это просто локальная переменная

4. Что такое «магическая переменная»? Меня больше беспокоит то, что внутреннее состояние шеф-повара, похоже, сохраняет еду — это волшебство, и ИМО противоречит интуиции.

5. @DaveNewton: chef.makeFood(order); Food f = chef.getFood(); waiter.deliverFood(f) .

Ответ №1:

Плохо ли иметь магические переменные?

Это зависит от того, что вы подразумеваете под «магией». Если «магия» означает для вас «делает что-то, что трудно понять или объяснить», то это плохо.

Плохо ли это делать в тестовом классе:

   chef.makeFood();
  waiter.deliverFood(chef.getFood())
  

Я не вижу ничего плохого в этом коде как таковом, даже если это не так, как классы используются в обычном (не тестовом) коде. (Но в дизайне / коде есть проблема, которую вы нам не показываете …)

На той же ноте, должен ли я вместо этого сделать это:

   chef.makeFood();
  Food f = chef.getFood();
  waiter.deliverFood(f);
  

Это нормально делать или не делать этого. Это зависит от того, считаете ли вы, что это делает код более читаемым. (Лично я бы не стал беспокоиться о локальной переменной там, но это только мое мнение.)


С другой стороны, я согласен с комментарием @DaveNewton об объекте «chef», содержащем еду в «makeFood». Это, безусловно, нелогично и немного «волшебно»… если бы это был преднамеренный выбор дизайна.

Более простой и лучший дизайн был бы таким:

 Food f = chef.makeFood();
waiter.deliverFood(f);
  

и полностью удалите getFood() метод и связанную с ним переменную состояния из Chef класса.

Существует ряд причин, по которым это плохой дизайн / плохое моделирование:

  • В интуитивном смысле это означает, что объект chef должен «стоять, держа тарелку», пока официант не заберет ее.

  • С точки зрения моделирования классов у вас есть переменная состояния, которая не является необходимой для реализации поведения шеф-повара.

  • С практической точки зрения программирования это означает, что:

    • код будет сложно (er) понять, когда вы посмотрите на него через 12 месяцев, и

    • API Chef будет сложно использовать в многопоточном моделировании кухни.

(Если это то, что вы имели в виду под «магической переменной», то это плохо … см. Выше.)

Комментарии:

1. Или шеф держит в одной руке стопку еды в формате FIFO, а другой готовит еще больше еды.

Ответ №2:

Ну, это не магическая переменная или что-то в этом роде, вместо этого здесь:

 chef.makeFood();
waiter.deliverFood(chef.getFood())
  

Первый требует меньше строк и, возможно, может быть лучше, если вам не нужна ссылка на вновь созданный объект Food, однако многие могут возразить, что даже если вам не нужна ссылка, приведенный ниже код более читабелен и понятен:

 chef.makeFood();
Food f = chef.getFood();
waiter.deliverFood(f);
  

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

Ответ №3:

Трудно обобщить этот пример.

В этом простом примере, вероятно, у chef нет причин сохранять ссылку на `makeFood ()’, поэтому ее следует возвращать напрямую. (И тогда getFood() можно удалить)

Но есть много других сценариев, в которых правильно сохранять внутреннее состояние, например, StringBuilder — или более сложный «builder» , а затем возвращать результат, когда все в порядке.

Локальная переменная обычно оказывается там при отладке…. На самом деле это не имеет значения.