What we strive for, then, is to avoid losing data, and in those cases where we cannot avoid losing data, to do our very best to be sure that the user is made aware of the loss. In many cases, if users are aware that data has been lost, they can find some way of getting it again, especially if they are told at the time of the loss.
So what can we do to reduce the chances of losing data? For starters, we can design our programs using data-safe techniques. For example, when I write a program which requires data or configuration files, I design it to minimize the loss, even if the program crashes. Two of the common techniques I use are to store data in text files, and to design my read/write functions so that the files are not left open.
By using text files for my data and configuration information, I gain the simplicity of being able to edit them with a normal editor. That is not any particular help for data safety. However, if anything does go wrong, such as the disk crashing, I know that whatever information I can pull from the crashed disk will be in a readable format. I also know that humans are very good at remembering things if they're given clues. A partially destroyed file provides a lot of clues, and using a text editor, it may be possible to reconstruct the entire file from the recovered text.
One of the annoying things about writing programs which store data is that many operating systems will let you write the data to disk, but will not actually update their directory information until you close the file. That means that a power failure will result in all your work being lost, even though it was written to disk. There's nothing you can do to protect yourself against the power failure occurring while you're writing to disk, but you can write your programs to close the file when it is finished updating it. There's a small overhead in opening the file each time, but this largely eliminates the risk of losing all your data.
But what about those times when you have no choice? For example, you cannot write to disk if the disk is full. In these cases, it may be that the best you can do is let users know that some data has been lost. Remember, you are writing this program to help the users, so give as much useful information as you can. Rather than a message which says "Data lost", pop up one which says "Could not save GARBLE.DAT, disk is full". Get their attention (message box, maybe even a beep), let them know what went wrong (couldn't save the file), and give them a clue how they can fix it (disk was full, make room then try again).
Probably the worst thing you can do is nothing. If you simply don't write the file, and don't let the user know that you didn't, then the user won't notice that something is wrong until the information is needed. By then, it's probably too late to recover it. If it was your program that lost the data, the user will have serious doubts about dealing with you again.
Amazingly enough, I recently had such an experience with some commercial software - the terminal program shipped with some modern operating systems. With the previous version, if you tried to download a file and there was already one with that name, it would automatically try another name. That could be annoying, but at least there was no loss of data. Now that they've upgraded and "fixed" that renaming, the program simply doesn't transfer the data. No warning box, no message, no renaming, no data! As far as I can tell, there's not even an option for it. The program simply throws your data away! Don't the people who write these programs think about their users? Don't they care about our data? Don't they want us to buy their other programs?