Just published "What is a contract", suddenly found that it is written by writing theory, there is no instance to prove. So quickly add a reverse case - C iostream. It is not because the iostream library is designed to be unpleasant (it's just the opposite, you can't find a more exciting C library than Iostream design), but want to show, in the ideological system without contract concept, component design will How much cost is paid for an unclear error handler.
Everyone knows that the C iostream library is very classic, and the first originating from the Bjarne Stroustrup Stream library, after the improvement of Jerry Schwartz, Martin Carroll, Andy Koenig et al., Becomes the iostream library, and is incorporated into the USD C library issued by Bell Laboratory Middle, widely spread. Later, the USD library gradually died, and iostream was spared by gaining widespread use, and it was placed in a standard library in a new form.
For erroneous processing, when the iostream library is born (about 1985-1987), C has no abnormal mechanism. Therefore, Jerry Schwartz invented such an error handling mechanism:
Example 1: Classic Iostream error handling:
IFStream IFS ("FileName.txt", iOS :: IN); if (! IFS) {// The operation // file to the VOID * transformation failed, implement an error handling}
Test if the file is opened, and the specific operation is implemented, which is a customary method (IDiom) of the classic iostream library.
We now envision the user does not perform this IDiom:
INT Val; ifstream IFS ("FileName.txt", iOS :: IN); IFS >> VAL;
What happens if FileName.txt failed?
If there is a Borland C 3.1 that year, you can test it. I estimate that anything does not happen, or said that the program is in extreme dangerous "undefined behavior" state.
This situation is unacceptable to the C library developer. Therefore, although the appearance of the problem is due to the user's error (they don't correctly test the flow state), the Iostream library developers start pursue component development technologies sufficient to cope with user errors due to the unclear in the non-contractual ideology. Thus, iostream begins in one direction to be dragged into the complex quenches.
We look at what to use this situation in the standard library. Standard iostream has a member function called Exceptions (), specifically used to help programmers switch exception mode. By default, the abnormality trigger is not open, so the situation is the same as the classic iostream library. If you call you as follows before operating iostream:
Strm.exceptions (std :: ios :: es: std :: os :: failbit);, when the stream is not in the GOOD state, perform similar STRM >> VAL; this operation, An exception will be thrown.
Do you look good, is it?
I don't think it is. I will forgive me the objection of my C standard, this is the first time I officially have an objection to the design of the C standard.
The shortcomings bringing this design, first is complicated. In Nicolai Josuttis's The C Standard Library, this mechanism has been explained in the entire 5-page paper, but also still is still unfinished. Complex design will inevitably bring complex usage rules, and face complex use rules, users can vote, that is, you are you, I don't have to! People who read this post, who uses Exceptions () in the actual project? In fact, I personally be afraid of Exception is very afraid of undefined behavior. For the user, you can do it, but you have to pay the cost of running performance and space for it. You are interested in tracking the implementation of an iostream function. See how much heart is consumed in order to support this exception, and your CPU has spent this much CLOCK.
The second thing is the problem of an abnormal itself - even if you caught an exception, what is it? The program may have completely left the execution environment when an abnormality, maybe you don't even know why you have an exception, how to deal with? It is not to inform the user: "I am finished, because an exception happens in XXXXXXXXX, if you want to report, give me email." Yeah, what can you do? "
We tried to use the contract point to analyze this situation. If you say "first test, then use" is traditionally a IDIOM, then rising in Contract ideas. For C , the "flow in the GOOD status" should be used as a contract to check in each member function. Even you can also set up a debugging period, specifically used to verify that the user checks the overcurrent state. Before you do the necessary operation, you can use the assertion to check if the user checks the overcurrent state, and meets the contract. In this way, under the contract, the user will be forced to use components in the correct way to greatly simplify the complexity of component development.
Let's consider anomalous. If an exception has occurred, a Retry mechanism is provided in Eiffel. Bjarne Stroustrup said that Retry can do it, but there is often no meaning. Why is it meaningless? Because there is no contract in C , abnormal production may be the programmer's bug. In this case, regardless of the number of RETRY, the result is the same. However, in the Eiffel, the situation is different. If all aspects are good to follow the contract, then when we really have an abnormal, we can make a great confident that it may be caused by a very accidental event. For example, in a network environment, another user suddenly implemented a file in that moment, or a casual abnormality of the hardware. For this case, "try again" into a reasonable choice. We are likely to kill an exception in the cradle so that no impact on the upper module.
Who said that the contract is not great?