"Скажи, не спрашивай", когда один класс делает и сохраняет вычисления с данными из другого

Пожалуйста, скажите мне, если я применяю принцип Tell, не спрашивайте правильно в этом примере.

У меня есть два класса, CalculationResults имеет функцию calculateMe(), который использует Data сделать некоторые расчеты. Важно, что он хранит результаты.

class Data {
private:
  int dataForCalculations;
public:
  void calculate(CalculationResults& calculationResults) {
    calculationResults.calculateMe(dataForCalculations);
  }
};

class CalculationResults {
private:
  int calculatedData;
public:
  void calculateMe(int dataForCalculations) {
    calculatedData = someCalculations(dataForCalculations);
  }
};

// somewhere else:
Data data;
CalculationResults calculationResults;
data.calculate(calculationResults);

Первая версия этого кода (до применения Tell, not ask) не использовалась Data::calculate функция, но у нее есть getter за dataForCalculationsтак что где-то я звонил calculationResults.calculateMe(data.getDataForCalculations()),

Новая версия лучше?

1 ответ

Новая версия лучше?

Это зависит от того, кого вы спрашиваете. Но чтобы быть уверенным, новая версия на 100% говорит, не спрашивайте. Это легко сказать, потому что ваши методы возвращают void.

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

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

В качестве другого примера. Если бы я писал программу, которая смоделировала вызов кому-то, у меня могло бы быть Phone, а также PhoneNumberи Person объект. Теперь, согласно сказанию, не спрашивайте, вы должны попросить объект с данными выполнить определенное действие. Итак, в этом случае PhoneNumber может иметь метод dial(): phoneNumber.dial(), Но имеет ли это смысл, концептуально? Действительно, Person набирает PhoneNumber в Phone,

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

Во-вторых, часто неясно, какой объект следует вызывать первым, когда двум объектам необходимо совместно использовать данные. Возьмите Book и Pen например. Вы говорите book.writeWith(pen) или же pen.writeOn(book)? Возможно, с этим примером можно поспорить, но часто вы обнаружите, что разница произвольна, и я ненавижу это.

В-третьих, если вы говорите, не спрашивайте, объект будет постепенно создавать все больше и больше обязанностей. Вы говорите объект, чтобы сохранить себя? Вы говорите это для отображения себя? Что делать, если у вас есть несколько технологий просмотра? Что если вам нужно отобразить ваш объект в разных форматах? Вы спрашиваете свой объект по электронной почте сам? Наличие объекта со многими обязанностями не обязательно плохо. Менее гибко изменить, но обеспечивает более легкую работу с API. Однако большинство людей предпочитают гибкость, и наличие объекта с небольшим количеством обязанностей является частью кода SOLID.

В-четвертых, в чем разница между тем, чтобы ваш объект передавался частным образом другим объектам с помощью команды Tell, не спрашивать (когда вам нужно обмениваться данными), и иметь геттер? Не очень, если вы спросите меня.

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

calculationResults.calculate(data);

В любом случае, только мои 2 цента.

Другие вопросы по тегам