Вот пример из реального мира:
Написание плагинов для Microsoft Dynamics CRM .
В этом документе вы увидите заметку с надписью: «Метод Execute плагина должен быть написан так, чтобы он не имел состояния».
И, в сущности, это означает, что быть классом без состояния является то, что не должно быть глобальных переменных (за исключением нескольких особых случаев, в которые я не буду входить, если их не спросить).
Причина, по которой это предписано CRM для разработчиков плагинов, заключается в том, что CRM пытается улучшить производительность путем кэширования и повторного использования экземпляров классов плагинов.
CRM выполняет свои плагины примерно так:
Основная нить:
YourCustomPlugin yourCustomPluginCached = new YourCustomPlugin();
затем позже:
Резьба1:
yourCustomPluginCached.Execute(context1);
и Тема 2:
yourCustomPluginCached.Execute(context2);
То, что некоторые разработчики делают неправильно, они создают глобальную переменную для хранения контекста, которую они устанавливают в качестве первой строки в методе Execute (). Таким образом, они не должны передавать это между всеми своими методами. Но это на самом деле огромная ошибка.
Потому что, если они это делают, и в сценарии выше, если выполнение в thread2 начинается до завершения выполнения из thread1. Это будет означать, что context1 в thread1 будет перезаписан context2. И теперь этот плагин будет иметь неожиданный результат. В 99% случаев, даже при неправильной разработке, проблем нет или нет заметных проблем. Но в 1% случаев это приведет к тому, что что-то пойдет не так, и что разработчику будет невероятно трудно понять, что пошло не так, и, вероятно, никогда не произойдет, когда он будет тестировать / отлаживать. Так что он, вероятно, останется незафиксированным долгое время.