[C++]Some quick and naive class design questions

Started by
4 comments, last by Ariste 13 years, 11 months ago
Hi :) As the title suggests, I got a few questions about class design. What I'm wondering is: Is it okay to increase the overall amount of functions in a class if it improves readability? (I keep the functions in question very short, but still, imho, practical enough.) I'm asking because I wonder if the number of functions somehow impacts performance, like during copy operations. I doubt that though, since I read that the functions are only kept in memory once, only data is shoved around. (Not 100% sure though since I'm self taught.) My main concern is code bloat and thus cache thrashing? The functions in question aren't called all over the place, on the contrary. Most of them only describe a small process, so the bigger functions don't look too obfuscated. And Is it practical to split a system into multiple classes, for modularity sake, even if both could be fused into one, with no apparent ill effect, besides rigidity? I'm guessing: Yes, but I don't wanna guess too much in the future :P. I am working on a reusable input-processing module. So far, I have split it into two classes. The job of the first is strictly to interpret/translate incoming input events and puts them into a generic structure. Like, keyboard keys, mouse buttons (including the wheel) and game-pad buttons are all treated as buttons, mouse-, and analogue movement are x-y pairs. The second class acts a bit like a binding manager, where any function, member or general can subscribe to either 'commands' (have to be registered, according to the need of the project) or directly to a button-value. The manager then, upon receiving an input packet, pushes an event into the subscriber according to what the subscriber requested. So yeah, I could eliminate the need of that input 'carrier' class they both use for communication if I'd fuse them, but that would just rearrange stuff. Still, I'm concerned about performance, including cache stuff, and the like, but I got only little knowledge about that, hence my questions. From reading through similar threads, overhead seems to be the better choice if it improves legibility, and the like, but yeah... Well, cheers. :)
Advertisement
To your first question:

It's absolutely okay, as long as it actually improves readability. In general, worry about readability and correctness first. Let the compiler worry about micro-optimization. If you find the compiler isn't doing an adequate job, then benchmark and fix the bottlenecks. But don't just assume that these bottlenecks are going to exist, because most of the time they won't, and if they do, they won't be where you expect them. The number of functions in a class, for example, will have zero impact on the performance of the class AFAIK (unless they're virtual, which is another matter entirely).

To your second question:

It's not only practical, but also highly recommended. See the Single Responsibility Principle. You want your classes (and functions) to be small. Each should take care of a discrete, well-defined, and limited chunk of functionality. Your example is a great demonstration of this: raw input and input translation are two different tasks, and so should be handled by two different objects.
For more on the SRP, see the third link in my sig. The huge understandability of following it and similar principles are well worth the hypothetical, negligible performance cost.
Alright. Thank you for your replies :).
Very interesting, gonna read myself into that and similar approaches.

I am still wondering about the amount of functions I should declare/keep, though.
But that really is mostly a cosmetic issue, as in, another user, or me, will obviously see all those functions, they're private, of course, but they'll still be visible, which feels unnecessary to me.

Would an interface be viable? Even though there will only be one version of the class?

But yeah...
I blame it on the STL container iterators, which are ugly, imho, and make code blocks look more complicated than they really are, so I extracted them into functions called process_<something>, inline.

Shouldn't be too bad, though it's hard to get away from those nagging thoughts of OMG WHAT IF IT'S ACTUALLY CALLED INSTEAD OF BEING INLINED? THERE WILL BE CALLS! CALLS ARE CYCLES!
Etc.

Ah well, thanks again and

Cheers!
Quote:Original post by Erius
I am still wondering about the amount of functions I should declare/keep, though.
But that really is mostly a cosmetic issue, as in, another user, or me, will obviously see all those functions, they're private, of course, but they'll still be visible, which feels unnecessary to me.

It's not merely cosmetic - more functions indicate a more complex object, perhaps an object that takes on too much responsibility. A giant class with hundreds of functions will be very hard to maintain.

As for private functions, those aren't part of the public interface of a class. I wouldn't create a separate interface for cosmetic reasons only. C++ just isn't a very beautiful language. ;)

Quote:I blame it on the STL container iterators, which are ugly, imho, and make code blocks look more complicated than they really are, so I extracted them into functions called process_<something>, inline.

They are ugly indeed. Typedefs may help to ease the pain here and there, but yeah.

Quote:Shouldn't be too bad, though it's hard to get away from those nagging thoughts of OMG WHAT IF IT'S ACTUALLY CALLED INSTEAD OF BEING INLINED? THERE WILL BE CALLS! CALLS ARE CYCLES!

Unless you're writing performance-critical code, that really shouldn't be on your mind while programming. And you're probably not writing performance-critical code most of the time. ;)
Create-ivity - a game development blog Mouseover for more information.
Quote:Original post by Erius
I am still wondering about the amount of functions I should declare/keep, though.
But that really is mostly a cosmetic issue, as in, another user, or me, will obviously see all those functions, they're private, of course, but they'll still be visible, which feels unnecessary to me.

Would an interface be viable? Even though there will only be one version of the class?

If you're really worried about it, look into the PIMPL idiom. But really, as long as you're following SRP, the number of private functions in a class isn't something to lose sleep over.

Quote:But yeah...
I blame it on the STL container iterators, which are ugly, imho, and make code blocks look more complicated than they really are, so I extracted them into functions called process_<something>, inline.

Captain P already mentioned typedefs, so I'll throw out another option: if you're using Visual Studio 2010, you can use the auto keyword to replace the type specifier before an identifier. Basically, it reduces

std::vector<std::list<SomeLongClassName> >::reverse_iterator iter = registry.rbegin()

to

auto iter = registry.rbegin()

Quote:Shouldn't be too bad, though it's hard to get away from those nagging thoughts of OMG WHAT IF IT'S ACTUALLY CALLED INSTEAD OF BEING INLINED? THERE WILL BE CALLS! CALLS ARE CYCLES!

This just isn't something to worry about, at least until you have performance issues and it shows up in a profiler report, which will probably never happen. Keep in mind the 80-20 rule, and don't micro-optimize code until you've proven that it's in the 20%.

This topic is closed to new replies.

Advertisement