# Stable code

## Recommended Posts

Hello, I have been programming for about 2 years now.
Mostly in c plus plus.
Been working in the win32 and direct-x apis doing both 2D and 3D applications.

I consider myself to have the basic knowledge, but as they say, "the more you know the more you realize how little you know".

I would like to get some clarifications on what stable code is.

Any examples would be great.

##### Share on other sites
AFAIK Stable code is simply code that:

1. Is bug free or as close as possible.
2. Is not breakable by invalid input or abnormal or unexpected situations.

##### Share on other sites
Ok, so for example.

Lets say I want to get a value from an std::vector.

if(values.size() > i){   return values[i];}

return values[i];

##### Share on other sites
Quote:
 if(values.size() > i){ return values[i];}

Definitely a step in the right direction, but writing stable code is about thinking of EVERY possible way the code could go wrong and making sure it no longer can.

It's a mindset you will get yourself into after a while of practice. Go through your code you already have and imagine what would happen if input in your functions was not as expected. Think of the entire range of a given data type when you see it coming into a function. For example, integers can be negative, so:

if ( values.size() > i && i >= 0 ){   return values[i];}

##### Share on other sites

Thanks for the input.

If there is no more to stable code than that, I should be able to grasp it!

##### Share on other sites
in addition to making sure you handle unexpected input well, handling your memory correctly will also go along ways into making sure you code is stable,

nulling pointers when they are first declared,
anytime a pointer is deleted nulling it
and possibly implementing some form of garbage collection or reference counting can go along ways to making your code stable

one of the things that has helped me the most with making sure my code is stable, using readable/understandable variable and function names

##### Share on other sites
Quote:
 Original post by empirical2AFAIK Stable code is simply code that:1. Is bug free or as close as possible.
This. Stable code should be well tested, and unlikely to need change in the near future.
Quote:
 2. Is not breakable by invalid input or abnormal or unexpected situations.
This would be more along the lines of 'robust' or 'secure' code. It isn't generally expected that "stable" code be bullet-proof in the face of arbitrary/malicious invalid input.

##### Share on other sites
Quote:
 Original post by swiftcoderThis would be more along the lines of 'robust' or 'secure' code. It isn't generally expected that "stable" code be bullet-proof in the face of arbitrary/malicious invalid input.

Well personally I would not distinguish between stable and robust. If code is going to fall over because the user does something stupid (100% dead cert) I do not consider it to be stable. However, I'm not a professional and if 'stable' has a defined specific meaning, I, of course, accept that.

##### Share on other sites
If your coding something and your not sure if its gonna crash or not, avoid using while loops, cause they can infintesimally cycle if their break condition is never met.
Something that needs to be coded securely and robustly for example is CSG (constructive solid geometry) its when you get a ball and cube and take a chunk out of the cube with the ball or vice versa.

The code usually gets to be 1000 lines long (longer if you stuff it up) and theres many points inside that can stuff up if the piece of code before doesnt output correctly.

Tesselation is another algorythm which should be robust and allow invalid inputs and still work.

CSG and EAR CLIPPING are 2 algorythms that both best remind me to be very secure when I code, being less lazy can sometimes be less work than careless
programming that ends up getting you no-where.

Youll be coding these 2 algorythms when you are making a model editor or environment builder.

They are both in the "geometry tool" class of algorythms, and in this class of algorythms I say think it 4 times over! before you put hand to keyboard.

Even if you cant see how to get an algorythm to work with every single case you can think of... you can at least let it "fail gracefully" and not crash the program terminally.

##### Share on other sites
I think stable code is code that is (close to) unbreakable by user input and varying factors (time, thread scheduling, etc). On the other hand, I do *not* think that writing code in a way that it silently ignores bad input from the programmer is a good idea. Consider this silly example:

void addPlayerToWorld(Player* player, const Vector3* spawnPoint){    // Must not be null.    if(spawnPoint == NULL)        return;    player->setPosition(spawnPoint);    players.push_back(player);}

If someone, for whatever stupid reason, assumes that NULL is a valid value for the second parameter, the program will not crash. Instead, it will silently ignore the error and do nothing, leaving the programmer confused as to why the desired result isn't achieved. A better way to handle this might be with a debug assertion, so that the programmer can clearly see what went wrong, and where, without affecting production code.

##### Share on other sites
Quote:
 Original post by empirical2Well personally I would not distinguish between stable and robust. If code is going to fall over because the user does something stupid (100% dead cert) I do not consider it to be stable.
The difference is in the potential cost of failure, and whether it justifies the increased cost of development.

There are fields (airport traffic control, nuclear reactor control, medical equipment, etc.) where robustness is not only desirable but required. In these fields, even a single error among millions of lines of code can cost people their lives, and thus you spend an incredible amount of time/money/effort in making sure that no error can ever occur, and an even larger amount on making sure that when it does occur, you can handle it gracefully.

For normal software (applications, games, etc.), we don't need to handle every eventuality robustly. There are many cases where it is acceptable to just crash, for example: power-outages, hard-drive crashes, a dying memory chip returning random values, some random idiot manually corrupting your stack with a debugger, ...

##### Share on other sites
Quote:
 Original post by swiftcoderFor normal software (applications, games, etc.), we don't need to handle every eventuality robustly. There are many cases where it is acceptable to just crash, for example: power-outages, hard-drive crashes, a dying memory chip returning random values, some random idiot manually corrupting your stack with a debugger, ...

No but then, thats not at all what I meant by robust. Or by the user doing something stupid. I meant mishaps in day to day operations.

Example of what I did mean by user stupidity:

User clicks the delete button without first selecting an item. Stable (perhaps would be called robust) would be "No, you must select an item first" not "Unhandled exception".

Example of what I did not mean by user stupidity:

User open case and goes at the RAM with a hammer and chisel.

Dealing with mistakes a user is likely to make would, [u]to me[/u], be a part of code stability.

But if code stability means something else in a professional environment, fair enough.

##### Share on other sites
To make this clear, "stable" and "robust" are different but overlapping qualities of code.

Stable means: The code (that could mean interface or implementation) is unlikely to change, well tested (that follows from the former, since only well tested code needs no more changes), in one word: reliable.[1]

Robustness is one quality of code among others that make software stable - as in, no more bugfixes.

[1] "A live release is considered to be very stable and relatively bug-free with a quality suitable for wide distribution and use by end users."

##### Share on other sites
Quote:
 Original post by empirical2User open case and goes at the RAM with a hammer and chisel.

##### Share on other sites
I'm a little surprised I haven't seen it above, so throwing it in.

Use assert.

The built-in assert macros are a start, but a full-blown logging assertion system is a must for large projects. It is useful for assertions to make log entries, and for the system to give a way to silence future instances of a specific assertion.

Assert that your inputs are valid. Assert that your results are sane. Whenever you discover someone called a function with invalid data, add an assertion that would capture it in the future.

Every assertion should have both the assert (seen by programmers and testers by hitting a breakpoint, logging and/or showing some UI) and the corrective action that is taken (action when assert is skipped and on shipping builds).

Assertions cause the debugger to kick in so programmers can find the issue in the call stack, and a good assertion library will let QA and testers grab useful information. They are also awesome because they are compiled out of final builds so there is zero cost to the customer.

One feature of a mature code base is that the code is covered with asserts and each one of them has a corrective action.

##### Share on other sites
Quote:
 Original post by frobOne feature of a mature code base is that the code is covered with asserts and each one of them has a corrective action.
Or for a more formal specification of the same, Design by Contract, primarily with respect to languages which support contract programming natively, such as D.

##### Share on other sites
Noob question: Is this assert thing like exception handling?

##### Share on other sites
Quote:
 Original post by PrestoChungNoob question: Is this assert thing like exception handling?

No.

You error-check stuff that could go wrong. The objective of error checking is to correct the problem, or gracefully tell the user you had a problem.

Exceptions are similar but handle errors that shouldn't be happening normally.

You assert things that can't go wrong. Asserts are for sanity checking. It keeps a function from being used incorrectly, and stops in the debugger when it is used incorrectly. They should never get hit, but if they ever do you know their is a bug in the code.

// Reading a file. Anything could go wrong.// Same with user input. Network data. etc.std::ifstream file("my.txt");int data;if( !( file >> data ) ){  std::cerr << "ERROR! CAN"T READ HEADER!!!" << std::endl;}vs// Allocating memory, it should almost always just work// but we could have fragmented too much or some other edge case.try{  foo = new foo[200000];}catch(...){// whoops! out of memory!}vs// Sanity check inputs! The function has error correction anyway, but// a dev will hit the assert in the debugger.  This gives easy access// to the problem without having to debug as much. The asserts aren't errors or// exceptions because this function isn't EVER supposed to be called with bad// data. If the data is bad, the caller screwed up something or someone overwrote// the caller's data with something bad.void DoStuff( unsigned char *buffer, const size_t sz, const foo &object ){  assert( buffer );  assert( sz < MAX_BUFFER_SZ );  if( !buffer || sz >= MAX_BUFFER_SZ )      return;   assert( object.is_valid() );  assert( object.is_active() );  if( !object.is_valid() || !object.is_active() )      return;......}

(Windryder's example is probable better, and less made up...)
edit:
Quote:
 I would go about:if(values.size() > i){ return values[i];}

The "at" member of a std::vector does those range checks for you, ie. values.at(i);. They are asserts as well, and can be (usually are?) disabled in release.

##### Share on other sites
Quote:
 Original post by WindryderI think stable code is code that is (close to) unbreakable by user input and varying factors (time, thread scheduling, etc). On the other hand, I do *not* think that writing code in a way that it silently ignores bad input from the programmer is a good idea. Consider this silly example:

void addPlayerToWorld(Player* player, const Vector3* spawnPoint){    // Must not be null.    if(spawnPoint == NULL)        return;    player->setPosition(spawnPoint);    players.push_back(player);}

Quote:
 Original post by WindryderIf someone, for whatever stupid reason, assumes that NULL is a valid value for the second parameter, the program will not crash. Instead, it will silently ignore the error and do nothing, leaving the programmer confused as to why the desired result isn't achieved. A better way to handle this might be with a debug assertion, so that the programmer can clearly see what went wrong, and where, without affecting production code.

No, that sucks. A better way would be using a reference.

##### Share on other sites
I strongly recommend this article, which was published in Communications last year:
http://sdg.csail.mit.edu/pubs/2009/dnj-cacm-full.pdf
While it tends to be targeted for critical and semi-critical applications, which games are not examples of, the underlying concept is a very useful one for any software developer: that one should directly be able to argue from the design and implementation (in away that leaves no doubt in the verifier who is reading the 'proof') that certain behaviors of the overall system are unconditionally met. The emphasis on the whole system forces consideration of interactions and side-effects, which may be incorrectly assumed to be not an issue if one is just doing unit tests, for example; at the same time, in order to make a detailed argument of the safety of this code tractable, there is additional constraint of minimizing coupling and side-effects, which I'd say is a good thing. But I can't do the article justice here, so just read it.

In the meantime, formal verification by automatic checkers is slowly making advances and correctness proofs of complex real-world programs will be a reality in a decade or two.

##### Share on other sites
Quote:
 Original post by return0No, that sucks. A better way would be using a reference.

In that case, yes -- obviously. I was just using it as an example to make a point.

##### Share on other sites
I think nobody has explicitly mentioned the importance of checking the return values of all the system calls you make. This is especially important when you are writing networking code.

About the difference between "robust" and "stable", the way I use the terms, "robust" means the code won't break if it receives stupid or malicious input, and it handles all exceptional conditions gracefully (at least providing a meaningful error message). "Stable" means it doesn't change much over time. Code that is not robust often needs to be patched as problems are discovered, so it tends to not be stable either.

##### Share on other sites
Just be thankful you don't need to program according to the "Type C" standard that our new electric fence controllers are written to. There, not only does your code need to be pretty much bulletproof, but you also are not allowed to trust the processor that your code is written on. Every calculation result has to be independently verified by a different operation etc.
I'm sure they do the same kind of thing for the space shuttle too.

## Create an account

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627654
• Total Posts
2978444

• 10
• 12
• 22
• 13
• 33