It happens in programming because generally speaking it is very difficult and almost impossible to always foresee all possible edge cases that are affected by a change in the code. In this case very specific types of wallets were affected, not everything.
P.S. This also highlights the importance of following safety guidelines such as keeping a separate backup of the wallet files, seeds, etc. which can be different depending on the software used.
I think the core problem why software breaks is..the software these days are too complicated for anyone to memorize...you can change one piece of code that might affect some other parts in ways you never expected.....and don't get me wrong..I'm not saying the programers were careless..no..rather the number of possible combinations is very huge..so you really can't test every part of it..you can think of it as a large network of dominoes...you nudge one and a domino falls into a corner you never knew was connected....but in the wallet case, the bug couldn't crash everything (just some specific types of wallets)....you might experience such because, as we know, you can't test every possible combination because of probably how numerous they are...and bugs survive in these configurations that are rarely used..untill someone somewhere run into them...
That's why backups are always recommended....yes you can't build a perfect software (as it is mathematically impossible) but you can build some safety nets...(Recovery seeds.. backup files and you can store multiple copies separately)
Good engineering was never about making mistakes...but rather..making sure that when mistakes happen (and it will) people won't lose everything...