Я недавно столкнулся со следующей ситуацией.
class A{
public:
void calculate(T inputs);
}
Во-первых, A
представляет объект в физическом мире, что является веским аргументом для того, чтобы не разделять класс. Теперь calculate()
оказывается довольно долгая и сложная функция. Я воспринимаю три возможных структуры для этого:
- напишите это как стену текста - преимущества - вся информация в одном месте
- писать
private
служебные функции в классе и использовать их вcalculate
теле - недостатки - остальная часть класса не знает / не заботится / не понимает об этих методах напишите
calculate
следующим образом:void A::calculate(T inputs){ auto lambda1 = () [] {}; auto lambda2 = () [] {}; auto lambda3 = () [] {}; lambda1(inputs.first_logical_chunk); lambda2(inputs.second_logical_chunk); lambda3(inputs.third_logical_chunk); }
Можно ли это считать хорошей или плохой практикой? Выявляет ли этот подход какие-либо проблемы? В общем, должен ли я считать это хорошим подходом, когда я снова сталкиваюсь с той же ситуацией?
РЕДАКТИРОВАТЬ:
class A{
...
public:
// Reconfiguration of the algorithm.
void set_colour(double colour);
void set_density(double density);
void set_predelay(unsigned long microseconds);
void set_reverb_time(double reverb_time, double room_size);
void set_drywet(double left, double right);
void set_room_size(double value);;
private:
// Sub-model objects.
...
}
Все эти методы:
- получить значение
- вычислить некоторые другие значения без использования состояния
- вызвать некоторые из «объектов подмодели», чтобы изменить их состояние.
Оказывается, что за исключением set_room_size()
этих методов просто передают запрошенное значение подобъектам. set_room_size()
с другой стороны, выполняет пару экранов неясных формул, а затем (2) выполняет половину экрана вызова установщиков подобъектов, чтобы применить различные полученные результаты. Поэтому я разделил функцию на две лямбды и вызываю их в конце функции. Если бы мне удалось разбить его на более логичные куски, я бы выделил больше лямбд.
Независимо от того, цель текущего вопроса состоит в том, чтобы определить, должен ли такой образ мышления сохраняться, или это в лучшем случае не добавляет ценности (удобочитаемость, ремонтопригодность, способность к отладке и т. Д.).
Firstly, A represents an object in the physical world, which is a strong argument for not splitting the class up.
Конечно,A
представляет данные об объекте, который может существовать в физическом мире. Вы можете иметь экземплярA
без реального объекта и реальный объект без экземпляраA
, поэтому рассматривать их как одно и то же бессмысленно.calculate()
будет знать об этих подфункциях .A
, это доводит их до крайности.A
представляет объект в физическом мире, что является веским аргументом для того, чтобы не разделять класс». Мне, к сожалению, сказали об этом, когда я начал программировать. Мне потребовались годы, чтобы понять, что это хоккей с лошадью. Это ужасная причина для группировки вещей. Я не могу сформулировать, что является вескими причинами для группировки вещей (по крайней мере, к моему удовлетворению), но это та, которую вы должны отказаться прямо сейчас. В конечном итоге, будь весь «хороший код», это то, что он работает правильно, относительно прост для понимания и относительно легко изменить (то есть изменения не имеют странных побочных эффектов).Ответы:
Нет, это не очень хорошая модель
То, что вы делаете, разбиваете функцию на более мелкие функции, используя лямбду. Однако есть гораздо лучший инструмент для разделения функций: функции.
Как вы уже видели, лямбды работают, но они значат намного больше, чем просто разбиение функции на локальные биты. Лямбды делают:
В тот момент, когда вы добавляете лямбда-выражения в смесь, следующий разработчик, который должен взглянуть на код, должен немедленно мысленно загрузить все эти правила, чтобы увидеть, как работает ваш код. Они не знают, что вы не собираетесь использовать всю эту функциональность. Это очень дорого по сравнению с альтернативами.
Это все равно, что использовать ботинок для садоводства. Вы знаете, что вы используете его только для рытья маленьких ям для цветов этого года, но соседи будут нервничать.
Учтите, что все, что вы делаете - визуально группируете свой исходный код. Компилятору на самом деле все равно, что вы каррилируете с лямбдами. На самом деле, я ожидаю, что оптимизатор немедленно отменит все, что вы только что сделали, когда он компилируется. Вы просто угощаете следующего читателя (спасибо за это, даже если мы не согласны с методологией! Код читается гораздо чаще, чем пишется!). Все, что вы делаете, это группируете функциональность.
// ------------------
между каждой частью.РЕДАКТИРОВАТЬ: После просмотра вашего редактирования с примером кода, я склоняюсь к тому, что примечание комментариев является наиболее чистым, с скобками, чтобы обеспечить границы, предлагаемые комментариями. Однако, если какие-либо функции можно использовать в других функциях, я бы рекомендовал использовать функции вместо
источник
count++
)calculate()
на{}
блоки и объявления общих данных в областиcalculate()
видимости. Я думал, что, увидев, что лямбды не захватывают, читатель не будет обременен силой лямбд.lambda
несправедливым, или вы грубо заставляете людей следовать строгому обозначению, ответить не так просто. На самом деле, это может быть совершенно приемлемо для вас, чтобы использоватьlambda
этот способ в вашей компании, и совершенно неприемлемо для моей компании, и ни один из них на самом деле не должен ошибаться!lambda
, таких какfor_each
функция. Соответственно, когда я вижу,lambda
что не подходит ни к одному из тех легко обнаруживаемых случаев проблем, первое, к чему я прихожу, - это то, что он, вероятно, будет использоваться для функционального программирования, потому что в противном случае он не был необходим. Для многих разработчиков функциональное программирование - это совершенно другое мышление, чем процедурное или ОО-программирование.Я думаю, что вы сделали неверное предположение:
Я не согласен с этим. Например, если бы у меня был класс, представляющий автомобиль, я бы определенно хотел разделить его, потому что, конечно, я хочу, чтобы меньший класс представлял шины.
Вы должны разделить эту функцию на более мелкие частные функции. Если это действительно кажется отделенным от другой части класса, то это может быть признаком того, что класс должен быть отделен. Конечно, трудно сказать без явного примера.
Я действительно не вижу преимущества использования лямбда-функций в этом случае, потому что это на самом деле не делает код чище. Они были созданы, чтобы помочь программированию функционального стиля, но это не так.
То, что вы написали, немного напоминает объекты вложенных функций в стиле Javascript. Что снова является признаком того, что они тесно связаны друг с другом. Вы уверены, что вы не должны делать отдельный класс для них?
Подводя итог, я не думаю, что это хороший шаблон.
ОБНОВИТЬ
Если вы не видите способа инкапсулировать эту функциональность в значимом классе, вы можете создать вспомогательные функции с областями действия файлов, которые не являются членами вашего класса. В конце концов, это C ++, дизайн OO не обязателен.
источник
A
(может быть, даже функтор со всеми другими методами private)? Класс объявлен и определен внутриcalculate()
(это очень похоже на мой лямбда-пример). Как пояснение,calculate()
это один из семейства методов (calculate_1(), calculate_2()
и т. Д.), Все из которых просты, только этот - 2 экрана формул.calculate()
это намного дольше, чем все другие методы?