6

In the section on "Good Encapsulation" in Code Complete, it is recommended to hide private implementation details. An example is given in C++. The idea is basically to completely separate the interface from the implementation, even in the class level.

class Employee {
public:
    ...
    Employee( ... );
    ...

    FullName GetName() const;
    String GetAddress() const;

private:
    EmployeeImplementation *m_implementation;
};

Is this really a good use of time? Not only does this seem inefficient (what kind of performance penalties would this give?), but the whole motto of Code Complete ("managing complexity") seems to have been reversed- does this not add complexity?

fredoverflow
  • 237,063
  • 85
  • 359
  • 638
voithos
  • 60,391
  • 10
  • 90
  • 110
  • It depends. Having a raw (i.e. non-smart) pointer to a `EmployeeImplementation` as a member variable is quite possibly a bad idea, though, depending on what it points to and who owns the pointed-to object. – James McNellis Jun 12 '11 at 04:16
  • 3
    It's called the pimpl idiom (or compiler firewall idiom). Some people like it, and some don't. – Kevin Jun 12 '11 at 04:20
  • 1
    @James McNellis: Why not just have private member variables instead of encapsulating all the member variables in a separate class? – Alok Save Jun 12 '11 at 04:40
  • 1
    @Als: The pimpl idiom is useful if you want to hide implementation details. For example, consider a cross-platform thread library; the implementations of the thread class may rely on platform-specific headers and types, the details of which you don't want to leak to users of the cross-platform class. If one is going to use pimpl though, a smart pointer should be used. However, with @Kevin's comment, I am now unsure as to whether the OP is questioning the utility of pimpl itself or the utility of using public accessors and mutators for private state. – James McNellis Jun 12 '11 at 04:43
  • @James: Indeed, I am wondering about the pimpl idiom itself (now that I know what it's called - thanks @Kevin). – voithos Jun 12 '11 at 05:03

5 Answers5

3

Another advantage of the PIMPL idiom may be in maintaining the ABI. See The Pimpl Idiom in practice.

The size of the class remains constant. This means that you may change the internal implementation, while keeping the interface intact.

If the implementation is distributed in compiled form (lib, dll, so, etc.), then, under some conditions, you may be able to just replace the library without having to recompile the code that uses the class. Thus, you decouple the code as a completely stand-alone module, so long as the public interface doesn't change.

As others have stated, it also reduces compilation time, which can be reason enough in some cases.

Community
  • 1
  • 1
Gilad Naor
  • 18,017
  • 14
  • 44
  • 52
2

Well, it does increase encapsulation since your header file now contains only public members and a single pointer to a private implementation.

It also (slightly?) lowers performance due to the extra level of indirection.

The "reduces compilation time" is the key issue here.

If you (your company) are the only users of the class then I don't think you have any reason to use this idiom. You get lower performance and you should have daily (or periodic) rebuilds of your source code anyway (which should be aware of dependencies between the classes).

This means that compilation time should be largely irrelevant if you are the only consumer of the class.

If you are distributing the library then the story is completely different. Changes in headers mean any clients you have will need to rebuild their applications to use your new version, even if what you did was change the private parts of the class. Using the pimpl idiom here would mean the change is invisible to the users of your dynamic library.

Andrei
  • 4,592
  • 22
  • 28
1

An extra level of indirection through pointer can cause extra cache misses and slow down your program. AFAIK, this idiom (PIMPL) is most often suggested to reduce compilation time. Say you have an employee.h header having with all fields in the class, instead of just one pointer. Now, whenever you change employee details (e.g. add or remove field), EVERY file including employee.h has to be recompiled. If all you have is a single pointer to an implementation class defined in employee.cpp, then ONLY employee.cpp has to be recompiled when you change EmployeeImplementation.

Now, is the reduced compilation time worth the extra cost? Only you can decide that.

zvrba
  • 23,242
  • 3
  • 52
  • 65
  • Is compile time the only incentive to using this method? What about the proposed increase of encapsulation- is it valid? – voithos Jun 12 '11 at 06:22
  • You cannot measure encapsulation, so talking about "increased encapsulation" is a bit meaningless. – zvrba Jun 12 '11 at 12:09
1

I think that the main advantage (or at least on of them) of the pimpl idiom is not saving compilation time, but allowing loose-coupling, i.e. breaking dependencies, between components.

Suppose you provide an infrastructure library that many other components use. Then, as @zvrba indicated, every time you change your private implementation details all your clients must recompile. It could be not a big deal, but in large and complex projects an integration between components may be a complex task. With pimpl, if your library is dynamic (dll, .so) then no action is required by your clients.

davka
  • 12,407
  • 11
  • 56
  • 78
1

This idiom is used for abstracting over poor headers, and not much else. Only use it if the types required to define the class involve including headers which leak macros, take a long time to compile, etc. Apart from that, it's generally not considered the correct thing to do. Since your implementation requires dynamic allocation and reference semantics anyway, you may as well just make it an interface and offer a CreateForMyPlatform() method that has a definition in a cpp file. At least you can use smart pointers for that scenario.

Puppy
  • 138,897
  • 33
  • 232
  • 446