2017-06-04 0:39 GMT+02:00 Robert Ramey via Boost
On 6/3/17 2:59 PM, Gottlob Frege via Boost wrote:
How many non-outcome things would I need to understand? Should it be
that hard? Shouldn't outcome be easy? And how important should this be in a review?
I would appreciate answers to that from not just Niall, but anyone else who understands the inner workings (as it is always hard for the author to see their work from someone else's perspective).
P.S. the internals of many (most?) boost libraries are hard to
understand - too many macros, etc. Is Outcome on the same level, better? worse? Even if it is on the same level of most of boost, I'm sad :-(
I'm going to rephrase this question in a more general form.
Is it important to understand the internal implementation of a library? If the answer is yes, how important is it?
To me the central questions are:
a) is this library intuitive to use correctly? b) is this library hard to use incorrectly? c) is it more work to figure out the above than it is to just write the functionality from scratch? That is, is usage of the library economic?
d) can I verify that it actually does what I think it does?
a, b, c are basically variations on the same idea. I need yes answers to all of these. Get to "yes" on these will involve reviewing documentation, and sometimes tests, examples and code which implements the library. In addition to these things, the library will need a clearly stated purpose describing what it is meant to do. "parse any json file so contents can be easily processed by a user's program" is such a statement. In other words can I understand what this thing does without having fill my head with a lot of detail. If I can't do this I can't use it. I know this sounds trivial - but it's not. It's amazing how many boost libraries don't pass this bar - and boost is way better than most.
Assuming we're past a, b, and c - what about d)? Why do I need to care about what's under the covers. There are a couple of reasons.
a) I want to be able to verify that it in fact works the way I think it does. I want to see what the code does. No, I'm not necessarily going to go through it line by line, but I expect to be able to trace down to the bottom for a few cases to know that it is in fact doable should I need to track down some problem. But more than that, if I can't do this even for a couple of cases, I don't have confidence that the implementation is reliable. Testing is helpful in convincing me there is quality there. But it's not the same as knowing I trace through some cases and verify that it does every required step and only those required steps. Only then can I feel confident in using the code in something important.
I realize that this is a very, very high bar that most of us boost authors have difficulty meeting. It's just very hard. It takes a lot of work, stamina and brain power. More tools, tests, etc can't do all the work. It's just very hard.
So, I'm inclined to stick to things that are simpler to understand. (usually). Something like shared_ptr I and understand. something like state_saver I can understand. I could probably understand outcome but I'm concerned that something which would seem so simple can require this amount of discussion. It's just not easy to be confident about it under these circumstances. Note that it's quite possible that were it presented in a different manner, I might have a totally different opinion. I'm not saying it's bad, I'm saying I can't understand it in the time I think it would take to write my own less general version.
But I also have to mention things like spirit, serialization, boost.units. These are things that one can't hope to really understand the way one really should. This might be why places like Google exclude these types of components from their list of libraries approved for usage at Google. But I still use them. Doesn't this contradict what I said above? Hmmmm - yeah except the economic argument. These packages save so much future time, I'm willing to break the other rules to include them. There is no way I'm going write my own alternatives so it's either use them (and pray they actually work) or just not do what they do.
Maybe the way to say this - to quote our spiritual guide - keep simple things simple. to which I would add - If you can.
Robert, I agree with what you say about a library implementation. I also agree that in case of Outcome review the shape of the documentation was the reason for misunderstandings that could have been otherwise avoided. But to make the picture complete, I would add this is one of these "vocabulary type" libraries, and that this alone causes lots of controversies. I remember the same form standardizing `boost::optional`. People have very strong expectations which are often contradictory. One says, Optional MUST provide `operator->`and explicit conversion to bool, otherwise the interface is counter-intuitive and does not fit into C++. Others say, it MUST NOT provide these clever operators, as this is the source of all bus. Or, "only pointer are allowed to have operator* and operator->. One says, implicit conversion from T is unsafe and is the root cause of many problems and gotchas with optional; the other says, "if I cannot write `return 1`, optional is useless". Why don't we have implicit conversion to T as other languages? Some people demand that Optional must provide iterators, as otherwise it cannot be used in generic contexts. Nearly every decision is controversial. The discussion about having or not having narrow interfaces: it isn't related especially to Outcome. It applies to practically any "vocabulary type". It is this being a fundamental "vocabulary type" that somehow attracts discussions. Regards, &rzej;