Ни. «Переместить весь мой код из одной функции в один класс» - это не ООП. Одним из фундаментальных правил ООП является то, что класс должен иметь одну зону ответственности .
Это не единственная ответственность, это около 15:
SolverPotential::solve(){
SolvePotential::interpolate()
SolverPotential::compute_flux()
SolverPotential::compute_energy()
// ...
// 10 other high-level function calls with NO parameter lists (just use private member variables)
}
Это также делает практически невозможным сохранение инварианта класса, не так ли? Когда можно вызывать compute_flux? Решать? Интерполяция? Что мешает мне сделать это в неправильном порядке? Будет ли класс в действительном состоянии, если я сделаю это? Получу ли я из него действительные данные?
Однако, почему это или-или? Почему нельзя сделать несколько классов и функций?
// This struct could be replaced with something like typedef boost::tuple<double,double,double> coord3d
struct coord3d {
double x, y, z;
};
coord3d interpolate(const coord3d& coord, const coord3d& interpolated, double potential); // Just return the potential, rather than using messy output parameters
double compute_flux(const coord3d coord&flux); // Return the flux instead of output params
double compute_energy(const coord3d& coord); // And return the energy directly as well
Конечно, эти функции не обязательно должны быть функциями. Если необходимо / удобно, каждый из них можно сделать классом или, что еще лучше, функтором, чтобы поддерживать необходимое состояние и, возможно, позволить вам эффективно передавать их в качестве аргументов другим функциям.
Если важна оптимальная производительность, вам, возможно, придется быть осторожным с прямым возвратом более крупных структур, а не с использованием выходных параметров, но я определенно сначала профилирую, чтобы увидеть, если это проблема, и даже если это так, вы возможно, можно избежать вывода параметров с помощью шаблонов выражений.
Если у вас есть концептуальный объект, над которым можно выполнить ряд независимых операций, вероятно, намек на то, что вам нужен некоторый ООП, что он должен быть смоделирован как класс с несколькими функциями-членами, каждая из которых, конечно, поддерживать инвариант класса независимо от того, как, когда и почему они называются.
Если вам нужно составить ряд функций, то, скорее всего, вам нужно склеить их, чтобы сформировать новые, более широкие функциональные возможности, функциональное программирование и функторы. Одна из общих причин (но определенно не единственная) желательности составных функций заключается в том, что вам нужно выполнять одну и ту же операцию над множеством различных наборов данных (возможно, даже с несколькими разными типами, каждый из которых реализует одну и ту же концепцию). Заставив функтор выполнять тяжелую работу, можно использовать его с std :: transform или std :: for_each.
Вы также можете использовать каррирование для постепенной сборки ваших функций (возможно, некоторые функции могут быть параметризованы набором фиксированных параметров, которые не меняются в зависимости от вызовов). Опять же, создайте функтор, который инициализируется с этими фиксированными параметрами, а затем предоставьте переменные данные в operator ().
И, наконец, если вам просто нужно выполнить последовательность операций с некоторыми изменяемыми данными, вам может подойти простое старое процедурное программирование.
Наконец, добавьте общее программирование, шаблонизируя необходимые классы и функции, чтобы они могли работать вместе, не перепрыгивая через обручи, такие как косвенное указание или наследование.
Не зацикливайтесь на ООП. Используйте инструменты в вашем распоряжении.
Я не знаю достаточно контекста вашего вопроса, чтобы сказать наверняка, но мне кажется, что вам действительно нужен не класс, это просто иерархия функций.
Ваш код пользователя звонит решить (). Внутренние вызовы solve (), скажем, (для примера, составлены), interpolate () и compute_energy (). compute_energy () внутренне вызывает compute_flux () и так далее. Каждая функция выполняет только пару вызовов для выполнения логических шагов, которые составляют ответственность функции. Так что нигде у вас нет огромного класса с дюжиной различных обязанностей или большой монолитной функцией, которая делает все последовательно.
В любом случае, в «очень длинных списках параметров» нет ничего плохого (обычно их можно сократить, сгруппировав некоторые из них вместе, но даже если вы не можете, нет ничего «un-OOP» в передаче много параметров. Напротив, это означает, что функция хорошо инкапсулирована из всего остального. Все, что ей нужно, передается в параметрах, поэтому она не привязана к остальной части приложения.