How to deal with the idea of "many small functions" for classes, without passing lots of parameters?
Asked Answered
Q

4

7

Over time I have come to appreciate the mindset of many small functions ,and I really do like it a lot, but I'm having a hard time losing my shyness to apply it to classes, especially ones with more than a handful of nonpublic member variables.

Every additional helper function clutters up the interface, since often the code is class specific and I can't just use some generic piece of code. (To my limited knowledge, anyway, still a beginner, don't know every library out there, etc.)

So in extreme cases, I usually create a helper class which becomes the friend of the class that needs to be operated on, so it has access to all the nonpublic guts.

An alternative are free functions that need parameters, but even though premature optimization is evil, and I haven't actually profiled or disassembled it... I still DREAD the mere thought of passing all the stuff I need sometimes, even just as reference, even though that should be a simple address per argument.

Is all this a matter of preference, or is there a widely used way of dealing with that kind of stuff?

I know that trying to force stuff into patterns is a kind of anti pattern, but I am concerned about code sharing and standards, and I want to get stuff at least fairly non painful for other people to read.

So, how do you guys deal with that?

Edit: Some examples that motivated me to ask this question:

About the free functions: DeadMG was confused about making free functions work...without arguments.

My issue with those functions is that unlike member functions, free functions only know about data, if you give it to them, unless global variables and the like are used.

Sometimes, however, I have a huge, complicated procedure I want to break down for readability and understandings sake, but there are so many different variables which get used all over the place that passing all the data to free functions, which are agnostic to every bit of member data, looks simply nightmarish. Click for an example

That is a snippet of a function that converts data into a format that my mesh class accepts. It would take all of those parameter to refactor this into a "finalizeMesh" function, for example. At this point it's a part of a huge computer mesh data function, and bits of dimension info and sizes and scaling info is used all over the place, interwoven.

That's what I mean with "free functions need too many parameters sometimes".

I think it shows bad style, and not necessarily a symptom of being irrational per se, I hope :P.

I'll try to clear things up more along the way, if necessary.

Quiff answered 12/5, 2011 at 10:18 Comment(2)
In your case, helper classes sound like a good idea. I do notk now what you mean with free functions? Global methods? They should be avoided. Private methods in the class don't "clutter" the interface though, as clients should not be able to see them.Klipspringer
Your example tries to do too much; I would break it up into one function for position, one for color, and one for texcoord. Too many parameters is often a sign that you're attempting to do too many different things at once.Louanneloucks
H
4

Every additional helper function clutters up the interface

A private helper function doesn't.

I usually create a helper class which becomes the friend of the class that needs to be operated on

Don't do this unless it's absolutely unavoidable. You might want to break up your class's data into smaller nested classes (or plain old structs), then pass those around between methods.

I still DREAD the mere thought of passing all the stuff I need sometimes, even just as reference

That's not premature optimization, that's a perfectly acceptable way of preventing/reducing cognitive load. You don't want functions taking more than three parameters. If there are more then three, consider packaging your data in a struct or class.

Hoatzin answered 12/5, 2011 at 10:25 Comment(3)
Just to make sure. Is the essence of your post the following: "The many small functions, in the case of a class, should be many small classes which do the logic on small components of data." ? Like a composition of functor like things?Quiff
@Erius, yes: break up your classes into manageable units with few data members, then write methods that handle those units. Often, a large class can be factored into many small structs and the complicated methods may become methods on those structs.Hoatzin
I see, thank you for clarifying, and I'll definitely go that direction for these problems, thanks.Quiff
Y
1

I sometimes have the same problems as you have described: increasingly large classes that need too many helper functions to be accessed in a civilized manner.

When this occurs I try to seperate the class in multiple smaller classes if that is possible and convenient.

Scott Meyers states in Effective C++ that friend classes or functions is mostly not the best option, since the client code might do anything with the object.

Maybe you can try nested classes, that deal with the internals of your object. Another option are helper functions that use the public interface of your class and put the into a namespace related to your class.

Yoohoo answered 12/5, 2011 at 10:28 Comment(1)
Hm, that seems to be the trend so far, creating (nested) classes, and indeed, for example, in a GUI manager, I transferred the Z ordering stuff due to mouse clicks to a Z level manager and that made me feel slightly more professional, but in some cases it makes me worry about the actual identity of something. Like a Window Skinning class, I extracted all sorts of functionality into logical units, and that turned the original 'solid' feeling class into a mere container that just told it's elements what to do. That's probably really good, but it looks so drab, guess emotion coding is bad.Quiff
N
0

Another way to keep your classes free of cruft is to use the pimpl idiom. Hide your private implementation behind a pointer to a class that actually implements whatever it is that you're doing, and then expose a limited subset of features to whoever is the consumer of your class.

// Your public API in foo.h (note: only foo.cpp should #include foo_impl.h)
class Foo {
  public:
    bool func(int i) { return impl_->func(i); }
  private:
    FooImpl* impl_; 
};

There are many ways to implement this. The Boost pimpl template in the Vault is pretty good. Using smart pointers is another useful way of handling this, too.

http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/sp_techniques.html#pimpl

Nibble answered 12/5, 2011 at 15:46 Comment(0)
C
-1

An alternative are free functions that need parameters, but even though premature optimization is evil, and I haven't actually profiled or disassembled it... I still DREAD the mere thought of passing all the stuff I need sometimes, even just as reference, even though that should be a simple address per argument.

So, let me get this entirely straight. You haven't profiled or disassembled. But somehow, you intend on ... making functions work ... without arguments? How, exactly, do you propose to program without using function arguments? Member functions are no more or less efficient than free functions.

More importantly, you come up with lots of logical reasons why you know you're wrong. I think the problem here is in your head, which possibly stems from you being completely irrational, and nothing that any answer from any of us can help you with.

Generic algorithms that take parameters are the basis of modern object orientated programming- that's the entire point of both templates and inheritance.

Condescension answered 12/5, 2011 at 10:37 Comment(1)
I do think I have some irrational things along the lines of coding by emotion or something, and those things drag me down from time to time, but this is different, at least I think so. I'm going to edit my question to include an example. Could very well be a mind thing, in the end, but I don't think it is, let me elaborate up there cause I might just suck at explaining.Quiff

© 2022 - 2024 — McMap. All rights reserved.