• TwitterFacebookGoogle PlusLinkedInRSS FeedEmail

Robust Program

28.01.2020 
Robust

Defensive design considerationsThe purpose of defensive design is to ensure that a runs correctly and continues to run no matter what actions a user takes. This is done through planning for all possibilities (contingencies) and thinking about what a user may do that the program does not expect.Defensive design encompasses three areas:. protection against unexpected user or actions, such as a user entering a letter where a number was expected. maintainability - ensuring code is readable and understandable. minimising/removingThis anticipation and protection is done through:.

IntroductionRobust programming, also called bomb-proof programming, is a style of programming that prevents abnormal termination or unexpected actions. Basically, it requires code to handle bad (invalid or absurd) inputs in a reasonable way. If an internal error occurs, the program or library terminates gracefully, and provides enough information so the programmer can debug the program or routine.This handout discusses the principles of bomb-proof coding, and gives you a detailed example of how to do it right. Our example is library for managing queues (FIFO lists) of numbers. This allows the example to consider parameters and global variables. The principles apply to programs, also; specifically, input and parameters are equivalent, and the environment is like global variables. Principles of Robust ProgrammingA robust program differs from a non-robust, or fragile, program by its adherence to the following four principles:Paranoia.

Don't trust anything you don't generate! Whenever someone uses your program or library routine, assume they will try to break it. When you call another function, check that it succeeds. Most importantly, assume that your own code will have problems, and program defensively, so those problems can be detected as quickly as possible.Stupidity. Assume that the caller or user is an idiot, and cannot read any manual pages or documentation. Program so that the code you write will handle incorrect, bogus, and malformed inputs and parameters in a reasonable fashion, 'reasonable' being defined by the environment.

For example, if you print an error message, the message should be self-explanatory and not require the user to look up error codes in a manual. If you return an error code to the caller (for example, from a library routine) make the error codes unambiguous and detailed.

Robust programming meaning

Also, as soon as you detect the problem, take corrective action (or stop). This keeps the error from propagating.Part of the problem is that in a week, you most likely will have forgotten the details of your program, and may call it incorrectly or give it bogus input. This programming style is also a form of defensive programming.Dangerous Implements. A 'dangerous implement' is anything that your routines expect to remain consistent across calls. For example, in the standard I/O library, the contents of the FILE structure for allocated files is expected to remain fixed across calls to the standard I/O library.

That makes it a 'dangerous implement.' Don't let users gain access to these! They might accidentally (or deliberately) modify the data in that data structure, causing your library functions to fail - badly. Never return pointers or indices into arrays; always hide the true addresses (or indices) by using something called a 'token.'

Hiding data structures also makes your program or library more modular. For example, the queue manager uses arrays to represent queues.

Robust programs

This gives them a maximum size. You might decide that linked lists would be more suitable and want to rewrite the routines. If you have properly designed the interface and hidden as much information and data as possible, the calling program need not be changed; however, if you neglected this style of information hiding and information abstraction, programs that correctly function with the current representation might break if you changed that representation (because the caller assumed that the queue elements are in sequential integer locations, for example).Can't happen. As the old saw goes, 'never say `never.' ' Impossible cases are rarely that; most often, they are merely highly unlikely.

Think about how those cases should be handled, and implement that type of handling. In the worst case, check for what you think is impossible, and print an error message if it occurs. After all, if you modify the code repeatedly, it is very likely that one modification will affect other parts of the code and cause inconsistent effects, which may lead to 'impossible' cases occurring.Exercise 1. Relate the informal descriptions of the principles of robust programming to the more formal principles of good programming style, such as cohesion and coupling, information abstraction, information hiding, and good documentation.

The point of this exercise is to show you that robust programs arise from writing code in a good style; what you learn in school is useful!Robust programming is defensive, and the defensive nature protects the program not only from those who use your routine but also from yourself. Programming is not mathematics; errors occur. Good programming assumes this, and takes steps to detect and report those errors, internal as well as external.

Robust Program Bom

Beware of everything - even your own code! Example of a Fragile LibraryThis library implements queues in a very straightforward way. It's typical of what many C programmers would write. It's also very fragile code.

We'll analyze it in detail to support that statement.The library can handle any number of queues, and when a queue is created, its pointer is returned to the caller. Three entry points are provided: qmanage, for creating or deleting a queue; putonqueue, for adding an element to a queue; and takeoffqueue, for deleting an element from a queue.

All files calling this routine must include the header file fqlib.h, which defines the queue structure.Reviewing the structure and library functions will illuminate the problems with fragile code, and show why the usual C coding style is so fragile. SummaryThe library fqlib.c, the contents of which are presented in this section, is very fragile code. SummaryThe above routines give several examples of the differences between robust and fragile coding. The above routines are robust, because they cannot be crashed by poor or incorrect calls, or inconsistency in the caller. They form a module, and have informational cohesion and stamp coupling (the latter because they share data in common variables; specifically, queues, noncectr, and qeerrbuf.

While the coding of these versions of the routines takes more time than the fragile routines, they take much less to debug, and will require less debugging time for applications using these routines.Exercise 16. Rewrite this library to allocate space for each queue dynamically. Specifically, change createqueue to take the parameter int size, where size is to be the maximum number of elements allowed in the queue.

Allocate space for the queue array dynamically.Exercise 17.Rewrite this library to use a linked list structure for each queue.What are the advantages and disadvantages to this? ConclusionMany security problems arise from fragile coding. The UNIX operating system, and the C standard libraries, encourage this. They provide library calls that can cause severe problems; for example, gets(3S) does not check for buffer overflow.

Avoid these routines!Exercise 18. Why should the following functions be avoided when writing robust code: gets, strcpy, strcat, sprintf? How would you modify them to make them acceptable?Exercise 19. When should members of the scanf family of functions be avoided while writing robust code? What should you use instead?Acknowledgements: Chip Elliott (then of Dartmouth College, later of BBN Communications Corp.) provided the inspiration for this. His handout 'Writing Bomb-Proof Code' for Dartmouth's COSC 23, Introduction to Software Engineering class, succinctly described many of the principles and techniques which I have extended.Thanks to Kim Knowles for her constructive suggestions on this document. Also, the students of ECS 40 and ECS 153 here at UC Davis helped me refine this exposition by asking questions and indicating what was difficult to understand.

I hope this document is clear; it is certainly clearer than earlier versions!© 1998-2002 by Matt Bishop. Permission to redistribute this document is granted provided this notice is kept.