0

Assume that you are developing a functionality and are 90% sure that the implementation class will stay alone. If I was in this position in Java I would probably not use the interface right now to keep the things simple. In Java it is easy to refactor the code and extract the interface later.

In C++ the refactoring is not always so easy. It may require replacing values with smart pointers (because of the introduction of polymorphism) and other non-trivial tasks.

On the other hand I don't much like the idea of introducing virtual calls when I am 90% sure they won't be needed. After all speed is one of the reasons to prefer C++ over simpler languages.

2
  • Templates provide another way to swap out the implementation. I'd use auto and if needed switch to templates, much simpler change. Jul 3, 2013 at 12:57
  • "speed is one of the reasons to prefer..." - this has been a dubious claim at best for nearly a decade.
    – Telastyn
    Jul 3, 2013 at 13:07

2 Answers 2

2

I would like to point out a thing 1st then share some of my experience. Please be careful with saying Abstract Base Classes and Interfaces so freely alongside. ABCs are language concept and Interface is a design concept. Of course ABCs are very handy in implementing interfaces in c++, however I do not think it is said anywhere (high credible source) that they are meant specifically for it. There are other ways to do it! Please take a read http://accu.org/index.php/journals/471.

That being said, to answer your question. In my experience as the rule of thumb you should always write code that you feel is designed well. If you think virtuals will cripple your performance, seriously do not bother unless you can prove it is more than 10% if you plan on managing your code. If it is one-shot, squeeze it all, code design does not matter.

Sadly one needs to learn how to analyze and profile applications, at a level that I would consider quite high, to properly re-design code. You should be able to tell if you need to reorganize branches, eliminate virtuals or memory management or find bottlenecks. I believe nowadays they are much more often hardware related. If you look through some SO c++ performance questions you will see that bottle necks lied in very strange places and only people who profiled code for cache misses or branch predictions were able to find causes.

I must say that, I had fallen victim to pre-mature optimizations, as well as under- and over- design. I tried to implement (heck, i did implement) clever things where they were not needed, and only complicated code and interface system to a point where it was not fun to extend my own programs. For the sake of like 5% speed-up I effectively encumbered process of testing to the point I had to spend a day to implement tests or test it manually after adding some new feature. I also went down to such thing as get_x(){ return x;}; was virtual because it shared interface with something that had different memory management.

To sum up, for now my advice would be:

  1. Write code that is well designed for current needs (and maybe immediate future). Do not try to over complicate it beforehand. It's just as bad as premature opitmizations. Personal experience.

  2. When it is appropriate, then refactor and introduce templates.

  3. Don't care about performance, unless you are sure you need. Learn to high-quality analyze your code. Then work on bottle necks.

Of course its probably twice as much work as getting everything right in the 1st place. In my case the problem is I miss the right way 2 out of 3 times if not more :). I believe over time a good programmer is able to choose good approach beforehand more often.

On the templates vs ABCs for interfaces.

I think ABCs are more-programmer friendly and readable, however I would got for template polymorphism if I ran into something like:

...
virtual get_x() {return coords[0];};
virtual get_y() {return coords[1];};
virtual get_z() {return coords[2];};
...

void some_fancy_algorithm_that_work_on_coords(){
  // for example calculate distances between every pair of instances
  // that can provide `ICoords` interface
}

I template base polymorphism a half-decent compiler can eliminate implicit object casts and use referenced methods and properties directly. It is good to avoid virtuals and intermediate access, even though everything is wrapped in the code design.

2

Interfaces are a design decision, so they are much more important to get right than implementation or convenience. Your design should drive the other concerns, not the other way around. Get the design right, decide whether to introduce interfaces, then worry about what that means in your language, C++ or otherwise.

[refactoring] may require replacing values with smart pointers

Smart pointers should be a drop-in replacement; even if this is not possible and you have to use raw pointers, you should be using idiomatic C++ where your object lifetimes are well-managed, i.e. it's obvious where you need to put deletes.

On the other hand I don't much like the idea of introducing virtual calls when I am 90% sure they won't be needed.

Are you sure you need to worry about virtual call overhead? Have you profiled your code? Is the virtual call on your hot path? Are you sure you've exhausted other options for improving speed (that are much more effective), such as algorithms, data structures, cache-friendliness, fitting things into L1?

2
  • I am asking just hypothetically so I can not respond to the last paragraph. Of course, you are right and I expected someone will play the premature optimization card against me :) Jul 3, 2013 at 13:34
  • @HonzaBrabec I'm not saying you are wrong to worry about the speed impact of virtual calls. However, in my experience it's been so far down the list of things to worry that in the end, the decision to not worry about it happens by itself. Jul 3, 2013 at 23:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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