6

Design Question

Recently, I've been doing more and more FP in C++, mostly in the form of function templates and lambdas, and heavy overloading of a single function name. I really like FP for some well-defined operations, but I've also noticed that as with OOP, one could easily fall into anti-patterns of spaghetti-code if one isn't careful (eg circular dependencies, which is a bigger issue for state-based code).

My question is, when thinking about adding new functionality, how do you decide between using a FP-paradigm or a OOP-paradigm?

I'm sensing it may have to do with identifying the invariants in the problem or in the design, but I'm not sure.

For example, without an OOP model/simplification of the real world, it may not be immediately obvious what a Dog or a Cat class is (what are its states? what are its methods?). Otoh, from a FP POV, a Eat() function simply allows an Animal to turn Food into Poop and Energy. It's harder to imagine Eat() being anything else (for me, at least).

I'm looking more for C++ answers, but this question could apply to any sub-module in any language that can handle multiple paradigms.

  • I've always gone the route that stateful data is encapsulated in a Class (Potentially a functor) if it's stateless and independent, just make it a function. – jozefg Dec 24 '12 at 11:48
3

I think that OOP lends itself best to when you have state that you can't destroy and re-create on a whim, or where that's a bad model- for example, if you consider 3D rendering, then the state of the renderer is not trivially destroyed and recreated, and it would be suicide for your performance to do so each frame.

In C++, then you need to add the fact that it doesn't have garbage collection and many FP techniques depend upon that for remotely acceptable performance.

Otoh, from a FP POV, a Eat() function simply allows an Animal to turn Food into Poop and Energy. It's harder to imagine Eat() being anything else (for me, at least).

That's completely equivalent to the OOP variant. There's no meaningful difference between

struct Animal { ... };
std::tuple<Poop, Energy> Eat(Animal*, Food);

and

class Animal {
public:
    std::tuple<Poop, Energy> Eat(Food);
};

A functional variation would return a new Animal which has eaten.

Typically, I recursively divide my program to obtain modules/submodules/classes/functions and member functions, then I often attempt to implement those functions or member functions functionally if possible.

  • It is not true. You animal in OO version is stateless therefor it is not OO. Each time you eat some food you change your state. At least you become heaver for some period of time. So this + encapsulation is the biggest difference between OOP and FP. – Alex Theodoridis Jun 11 '13 at 7:54
  • You don't have GC, but you have RAII, if you stick to simple data structures that can be copied on the stack, you will not worry about performance nor memory. If you keep passing a struct as a value type from function to function, it keeps gets copied on the stack, and you don't need to remove them from memory. Also objects that owns objects on heap (like a vector for example), you don't worry about its removal from memory, because when they are removed from stack RAII automatically calls destructor, which removes the object from heap. – user9335240 Feb 19 '18 at 8:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.