What are the general strategies to employ when attempting to ensure that a module of code will function correctly on the live system? A common problem we have at our software house is that we typically deploy solutions to a remote client's server, which hasn't got any software-development-related software installed on it. When problems (inevitably) arise in the deployed software, we get annoyed clients telling us to fix the issue, but since we can't remotely debug the code, we get locked into a cycle of effectively having to guess whether our code will work before we deploy it, and then repeating the cycle when the deployed code has issues.
Furthermore, due to the remoteness of the client, it's typically not possible to get a full working test copy of their system set up on our end, so we end up developing against approximations of their system on our end. This makes our debugging and code planning on the development side significantly less effective, because when we deploy we don't know precisely what variable between our test system and the live system is causing problems with our code.
So far, I've implemented a basic error logger in all deployed code that captures the stack trace, exception details, method, class, namespace, parameters and additional messages and error codes at each exception, but this really just speeds up the process of fixing that specific error. I've also tried writing individual tests for specific subsections of modules as executables and running them on the client system, but for modules that are tens of thousands of lines long, this usually just isn't feasible without grinding all development to a halt.
I'm trying to get a strategy in place which would help us better avoid the exceptions in the first place, but I'm stuck on the fact that:
We don't have (and typically can't get) a working test system that accurately models the live system, e.g. an image of the live system, if we do have it then it's months out of date
We can't install remote debugging software on the live server
The client typically has no dedicated test server, so any deployments have to go straight to live
Having no access to a copy of the live system means that we can't write effective unit tests which actually model the conditions the code will run under on the client side
If it helps, the code is typically C# running under .NET 3.5. How to better tackle this issue?