I am extremely contrarian on this issue.

While the possibility of someone making your "internal" state inconsistent is a near certainty, it is by no means your problem, nor should it be. Because otherwise you're making a bet that your code is perfect and won't ever NEED having its internals changed by someone other than you.

I've dealt with way too many buggy libraries to believe that any such thing as simple as design patterns and coding principles and abstractions and whatever other religions we're teaching in software engineering schools these days made better software. We've had 50 years of software engineering research and we're not making better software. Because it's not the tools' fault. Good workmen will create good results no matter the lack of quality of their tools; bad workmen will create bad results no matter the quality of their tools. I'm done believing the lie that we can hire just anyone for a job, as long as we give them the right tools, the right direction, the right restrictions, the right control. The person behind the tool is far, far more important.

The likelihood that the library code is perfect for all purposes is slim-to-none. The implementing developer will thus NEED access to your internals to make use of the library, or else move on to another library. That's basically what Open Source software is all about: dealing with hidden internals through the vendor is too tedious, expensive, and time consuming, so give the implementing developer full access to the source code, the ultimate of "internals".

As for the notion that it greatly expands your public interface, again, that is a certainty, and as well extremely not your problem. I guess since I don't use antique programming tools like C in basic, bare text editors, this probably isn't an issue I can completely understand, but if someone changes the interface in a future version, then I... either stick to the old version or change my code to suit. Bug fixes in the new version that didn't get back-ported to the old version? Again, if I just had access to those damn internals, I could do the back-porting myself and it wouldn't be a problem. Or I would learn there is a fundamental failing of the original library that prevents the bug from being fixed. And then appreciate better why the API had to change.

Code isn't that hard to change, especially if you stop expecting it to be hard to change. Hell, it's not even a problem for me to use two different versions of the same library so I don't lose functionality over time while I migrate. I like good code, and I like a well designed system, and I used to get really bent out of shape about such things, but I also like living and getting on with my life. Screw it, hack it. It's really not that big of a deal. If it works, it works, and you're done with it until it no longer works. That's the case no matter the scenario, for all N works over time T.

That's basically what Test Driven Development is all about: do what is necessary and sufficient, no more, no less, until it's no longer sufficient or necessary. If you're not doing only what is necessary, if you're writing unnecessary code, then you're wasting time that could be spent creating a real work of art that means something to someone, or exercising, or washing your butt. More importantly, you're spending my money on a mental masturbation trip to write code that was never asked for.

So yeah, don't hide your internals. You're more likely to drive people away.