2

I understand the principles behind opaque data types, encapsulation, information hiding, etc. in theory: preventing alteration to parts of a program can prevent people from accidentally messing it up, and hiding the information is basically just to make it more readable. The thing that I just can't seem to wrap my brain around is how this wouldn't cause massive problems.

Having a programmer use a black box while completely ignorant to how it works seems really dangerous to me. Yes, I don't need to know what a bowl is made of or how a microwave works to use either of them, but if I do stick a bowl in the microwave and it's made of the wrong material, the bowl could shatter.

Say for example, I have a function, int black_box(int x, int y), that takes two numbers as inputs and performs some sort of calculation on them. It's known what the calculation does and how to use it, but the actual implementation is considered irrelevant. Now, I try black_box(5,3); but part of the calculation, which I don't know about, involves var = y / (x-5);. If the people who wrote up the documentation missed this and didn't write, "don't use 5 for x," I'd be stuck with an error telling me I can't divide by 0, and I would have no idea where I went wrong.

This was just a simplistic example where the oversight would be obvious, but in more complex programs, I can see this becoming a serious problem. I feel like I'm missing something vital here because I can't seem to view keeping other programmers blind to what they are using as a good thing.

4
  • Well - the var = y / (x-5) is clearly a BUG if not explicitly documented as a special case. But, more important thing, how does it come that you are testing third party library without source code in the first place?
    – Dusan
    May 4, 2019 at 22:16
  • Encapsulation isn't synonymous with black box, so when errors happen, the debug output or stack trace should contain sufficient info to find the location where something went wrong. And even if you don't look at the implementation of a data type, there should be a contract specifying what you can and can't do with it. Part of this contract is which inputs are valid, so it could state "x must be between 0 and 100, but not equal to 5". May 4, 2019 at 22:22
  • We hide information from ourselves. We do have the authority, though, to switch hats and look inside, especially if something is unclear, or there's a problem.
    – Erik Eidt
    May 4, 2019 at 22:53
  • You got some good answers, but I am not sure if the answerers really understand your issue. I guess the answer you are really after is Joel's Law of Leaky abstractions. In essence, it says any non-trivial abstraction always has the risk of showing unexpected or undocumented behaviour which you can only understand when looking into the black-box. And yes, this can sometimes lead to serious problem, or hard-to-fix bugs.
    – Doc Brown
    May 5, 2019 at 12:26

4 Answers 4

3

This isn’t a concern for encapsulation, it’s a concern of using proprietary software. Because what you describe is clearly a bug. It’s either a bug in the published API or it’s a bug in the implementation.

If the black box is internal to your company or the source code is otherwise available to you, you might be able to dig deeper and uncover the problem and fix it, but that has nothing to do with information hiding.

What does have something to do with encapsulation and information hiding, is that you should never have a black box, in that you don’t know what it does. You should always know precisely what it does, what you don’t need to know is how it does what it does. If it’s relevant for you to know about it, then it should tell you.

Appropriate information sharing is a required element of information hiding. Your example is a bug in that it is either a failure to disclose the appropriate information, or something that shouldn’t happen.

Your presumed proposed fix, that the developer be aware of the internals so that an inappropriate value is never passed is ineffective and makes the code less useful. It can only be used by someone that not only knows about the problem, but keeps it in mind whenever using it. But assuming that is a 32 bit integer, there are billions of inputs that don’t cause a problem, and obviously passing 5 will be rare — if it was common the code would be useless. Put in xml comments or something that says “doesn’t work if the input is 5”, and be done with it.

1
  • "or it’s open source" should be "or the source code is available to you". It doesn't have to be open source.
    – gnasher729
    May 5, 2019 at 21:22
1

You got already some good answers, but I am not sure if the answerers really understand your issue.

I guess what you are really after is Joel's Law of Leaky Abstractions. In essence, it says, any non-trivial abstraction always has the risk of showing unexpected or undocumented behaviour. This behaviour can only be understood in full by looking inside the "black-box".

And yes, this can sometimes lead to serious problems, like hard-to-fix bugs by unexpected behaviour, or maybe to performance problems. That is why the quality requirements for reusable black-box components are usually a lot higher than for "debuggable" components. For instance, such components should follow the principle of least astonishment (and your example of a function where x=5 leads to problem is an example how to violate this principle). Other requirements are things like

  • useful documentation (or being self-explanatory)

  • some robustness (which means, for example, some internal validation, so trying to use a component in a wrong manner gives a sensible error message)

One should also not overstate the implications of encountering a bug in some black-box component. Software always has bugs, with or without encapsulation, and any professional programmer should be aware of that fact and know how to deal with it.

The most important technique to find those bugs is called "testing", and it has to be done for any program, if it uses black-box components, or not. The techniques to deal with a bug are also well known: debugging and fixing it, or avoiding it by using the components differently. Even if there is a bug in a closed-source component, the vendor can usually be asked for fixing the problem. So using "black box" components is not inherently more "dangerous" than using one's own components.

Note the "LoLA" does not mean we should not use abstractions - it just means we should not rely on them 100% and trust them blindly.

0

If you don't have the source code of a library, then the behaviour should be documented precisely. And it better be (fairly) bug-free. If not, you are in a bad position - use a different library.

If you have the source code, information hiding is no problem. That's because the information is hidden from code that shouldn't need to worry about it. It isn't hidden from the debugger software, and it isn't hidden from the human debugger (software developer). The only problems that you have are the usual problems that you have when you are not the original author of the software.

-1

A poorly implemented encapsulation which doesn't validate inputs may get in a away of finding root causes.

BAC

Consider an encapsulated module A which accepts inputs from module B and generates outputs for module C. Module A generates correct output when presented with valid input. Module A also has got a flaw: it quietly generates incorrect output when presented with invalid input. In other words, module A does "garbage in, garbage out" instead of "garbage in, garbage stops". Even though you receive incorrect outputs from A, the root cause is in B.

To quote one of my mentors: "If you don't validate inputs, you don't have encapsulation."

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.