Вы всегда должны знать о «побочных эффектах» и «детерминизме» в вашем коде. Если побочный эффект (то есть то, что происходит при выполнении кода) может повлиять на что-то другое (вставка, удаление строк, создание объектов и т. Д.), Вам необходимо знать порядок завершения и контролировать, когда это происходит.
Вам также необходимо знать о детерминизме вашего кода (то есть, могу ли я знать, что эта вещь будет там, когда она мне понадобится), опять же, если это необходимо, вам нужно контролировать, как исполняется ваш код.
Взять, например, обработку записей из базы данных. Вы должны иметь записи, прежде чем сможете их обработать, поэтому вы должны делать это в таком порядке. Если два процесса находятся в разных местах в вашем коде (потоки, обратные вызовы, события и т. Д.). Вторая функция (обработка записей) должна быть информирована о состоянии первой функции (получение строк), обычно выполняемой с помощью флагов, блокировок, семафоров и т. Д.
Для детерминизма подумайте о защитных утверждениях в функции. Если моя функция должна иметь строку и ненулевой объект, я сначала проверяю эти условия, когда мы входим в функцию, прежде чем начать вызывать методы для этих объектов (вызов string.ToLower () подходит для строки, но плохо для нуля объект). Таким образом, я делаю детерминизм во время выполнения, чтобы предотвратить ошибки в моем коде (такие как NullReference и т. Д.). Компилятор выполняет свой собственный детерминизм времени компиляции, но он не может знать о состоянии объектов во время выполнения, поэтому он выполняет только сравнения операций (независимо от того, допустимы они семантически или нет).