Beware Of Migrationalism
When ordering changes to the system, the customer may be tempted to construct the ChangeRequest using declarations like "remove this" and "change that to this". In essence, this will contain the information about what is required to change, but in general will not be a clear guide to where to alter the system.
When starting from a certain perspective of the system, which may or may not be a complete view of all the functions of the application, and describing the migration to a new view of the system with some functions altered, the description will only contain the effect on elements of the system that were envisioned in this primary perspective of the system. I call this migrationalism.
So my advice is to explain this to the customer, and that a migrationalist ChangeRequest might lead to incorrect implementation of the changes, and may impact more functions than requested. Ask to revise the ChangeRequest into a proposition of how the revised system should work, without referring to the current operation of the system, optionally only describing part of the system that should undergo the changes. I call this propositionalism.
A description of a system and it's functions is a more independent document. It leaves it up to the architects and developers of the system to compare it to the current build-up of the system and determine where it is best to alter the system to reflect the changes as described in the propositionalist ChangeRequest.
You've been asked to construct an application. You fulfill the outlines of what has been described. The first version takes shape, passes testing, and is taken in use... by the end users... you don't know... The strangest stuff happens in the field, and may well not register by the application itself. System messages may not prompt operators to take desired action, but to add onto the anomaly. Anomalies like this generally do register with the operator's supervisors. And these people generally report anomalies to your supervisors...
Enrich the operator interface with an optional method of marking anomalies as such, so they can be picked up pro-actively, either by senior operators, operator supervisors, system support staff... Or if something is really wrong, form a good base to start work on reproduceabillity investigation, design revision proposals, feature requests...
I'm not promoting to ignore deadlines, far from it. A deadline is seldomly a fixed plain single moment in the future, and if it is, there's a very good reason why it is so. In most cases a deadline is an event unfolding, a change taking place, a request to change a process. I call this the modality of the deadline.
In some cases a phased deployment is possible. Sometimes some changes can already be made in preparation of the upgrade. Some changes can even take place on a calmer moment after an upgrade.
Repeat The Obvious
Development and construction may be technical and complicated as it is, most problems arise due to misunderstandings, minor nuances that didn't come through right, requests formulated with important specifications missing...
When you receive a request, try to keep the dialog going and ask questions. Start with silly questions, like these: Are we talking about the new application? Is it for the current users? Is it for all of the users? Is it for all of the items? Is it for all of the application?
Any assumption you make, (and we make some semi-unconsious, be aware of those!) may turn up later as a false assumption. So checking assumptions in setting up architecture and design is no luxury!
Name It Right
Use suitable names for things when talking about the project. Use names that are not confusing. Start a project-dictionary that describes more what is meant by which name. Use the dictionary to detect and eliminate confusion. If people tend to use the same name for two things, or use two names for one thing, persuade them to choose one, or to use a 'better' name. Have a thesaurus handy for searching names, for example:
On larger projects, with several groups of people (packaging, stock, order picking, marketing, accounting...), detect where between groups different names are used for the same thing, or the same name is used for different things. Start separate dictionaries, have translation guides handy when you traverse groups or meet with people across groups. Start a new prototypic dictionary to use for yourself, for the documentation, for the development... Or select the completest one of the existing, and stick with your selection.
Turn On The Light
When you're in a room in total darkness, you can't be sure about how big the room really is. You only know what is in the room by feeling, hearing, using other senses than sight. Unless you turn on the light. The light shines on the walls of the room and all objects in the room. You see their image, their size, their position.
When working on a project, check if you know about all of the modules. Check if all stakeholders are serviced by an application in the project, or an application the project interfaces with.
When you have access to all of the source, check if you can verify which modules are used where. One very basic technique to do this is 'grep'-like solutions. (I use DirFind especially for this purpose.) Anything helps that is getting you closer to an inventory of interfaces and/or cross-module calls.
Leave Out Adjectives
It's hard, sometimes, to be passionate about what you do and remain objective. When I feel like this, and are reviewing something I just wrote, I leave out all adjectives. It sounds like you're letting go of a lot of the text, but works miracles every time. I only put in single 'neutral' adjectives if the meaning changes when left out. I may try to rephrase that bit first, if I can find a short enough way to denote the same.
I also break up longer sentences in single, straight-forward sentences. Plain "A is B"-style writing is easy to understand. It avoids misunderstandings. Also don't switch too much between object and subject over sequencial sentences.
Explain It To A Child
When compiling an explanation, explain the concept at hand to an imaginary 7-year-old. Explain it to a 5-year-old if no reading is involved. Explain it to a 3-year-old if no language is involved.
Some have proposed to entertain real children with this undertaking, but I fail to see the sense in enlightening minors into the insides of production-grade systems, let alone keeping them from play.
Have your imaginary child be as inquisitive as possible. The best question is 'Why?', and the worst answer is 'Because it is so.'
Skip The Maze
Don't get lost in the maze. Skip the maze. Most labyrinths have something in common: they fit on a page, they have outer walls.
When mapping a structure, and you come across new levels of complexity, adjusting your estimated total level of complexity each time, skip the internal structure for a moment and look ahead for 'outer limits'. It helps to map the entire structure.
The global goal of the system, the high-level requirements, define to a degree what the components of the system should look like and how they should cooperate.
Set An Exception Boundary
When going through the first talks about a new project, and in any other talk about what needs to happen, there is always a way of how things are supposed to happen, and a number of ways for things to not go as planned, possibly causing trouble.
When issues like this come up, or if you think them up when you are checking up on the story you're being told, ask rightaway if it's possible to predict how often this might happen.
Exceptions to normal operation that may occur a lot, might not deserve to be called exception. It might even be better to cater for them in both project architecture and end-user education.
Exceptions to normal operation that may happen only a very few times, do not deserve extra features to cater for them specifically. Most projects have a number of strange exceptions like this, so providing for each of them takes you too far away from the task at hand. Some may even be impossible to predict beforehand.
Instead provide a single method of catching items that don't follow the rules, so that operators can fix them, or developers can see what's wrong.
The exception boundary is when occurance is high enough to decide an exception deserves more work, another name, other operations in handling.
Where to set the boundary may involve guessing. It may depend on revenue generated or lost. It could even differ per type of exception.
Handle the error
Let's say you're past the ugly phase of detecting and evaluating the error, and you really have an urgent case of an error taking place you have to handle. You need to act, and handle the error correctly.
There are four things to an error:
Minimize consequences. Prevent things from getting worse. Halt or interrupt systems where the faulty item could disturb other items. Stop the entire system if you have to. If possible leave the system operational for items without the problem and have the troubled items sent to a holding area for further investigation or getting corrected.
Post mortum. Find out what really went wrong. Find out what caused the problem, and understand the full extent of the problem. Don't point fingers yet. Just get to now every ugly detail of the accident.
Judge the error's origin. Make changes to prevent it from happening in the future, without impacting items that did not have the problem. Revise processes or properties if it could improve the situation. Add extra checks to the validation, if possible.
Prepare for more. Separate from trying to solve the issue, evaluate emergency measures. Were they efficient? Could you provide more tools to have ready in similar cases? What happens if validation fails? Is there a safe place to quarantine troubled items?
Information, Un-information, Dis-information, Re-information
Don't wrap the wrapper
If you want to do something, but the wrapper won't let you: Have a close look at the wrapper. Try to understand what it does. Try to fully understand what it is it's wrapping. Also check if the wrapper provides a singular interface to a multiple of options. If so, check wether the wrapper provides for a way to work with the underlying technology directly.
Then, and only then, try to decide wether you need another wrapper, if you're better of without a wrapper (!), if you yourself could do a better job at the wrapper (!!), or if you want to bypass the wrapper and lock yourself into the underlying thing (!!!).
But never, ever, wrap the wrapper in yet something else.