Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
...
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Spiceman, Вы писали:
S>Мда, с точки зрения быдлокодера — проект — это код, который в лучшем случае был успешно скомпилирован. Компилируется — проект завершен
Ваши слова, уважаемый, — бурлеск чистой воды. Равно как и вы — акциденция современности
S>Надо ли говорить, что наш проект использовал в одном незначительном месте стандартный генератор случайных чисел, а вызываемый при инициализации std::randomize() успешно заметал любые следы?.
я не С++ник, но по-моему имелось в виду, что если б рандомазе не использовался нигде в коде программы,
то при выполнении одной и той же последовательности действий после запуска программы, она вылетала бы о одних и тех же местах.
нет?
V>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>...
Улыбнуло конечно, но "несправедливо уволенный" просто м**ак.
V>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>...
первый же редактор с раскраской макросов отдельным цветом спалил бы этого чудика.
так что "не верю" (с)
Здравствуйте, cthsq, Вы писали:
C>Здравствуйте, e-Xecutor, Вы писали:
EX>>>>"Не верю!" (с) Станиславский
EX>>И кстати, что такое std::random? EX>>И в каком артефактном компиляторе есть exceptio.h ?
C>вот веть.... C>посмеялся бы над шуткой, кнопку [ ] нажал, да и ладно.
Ну байкоподобная шутка должна быть правдоподобной,
иначе она не смешная
К вопросу о шутках с дефайнами.
Гораздо страшнее дефайны задаваемые в проекте и/или makefile,
особенно если command line вызова компилятора не показывается.
Если передефайненный return тот же eclipse показывает цветом
дефайна и можно туда перейти (или посмотреть хинт), то
про дефайн из makefile-а он ни сном ни духом.
Я как-то что-то отладочное запихал в головной makefile,
а потом случайно закоммитал (да такой я раздолбай).
Прийдя на работу на следующий день обнаружил коллегу в состоянии
близком к истерике
До кучи:
Коллега завёл в классе поле
Mutex _mutex;
в другом месте был такой код:
[ccode]
MutexGuard guard(mutex);
[/code]
без подчерка (нахрена там вообще подчерк это другой вопрос).
Код компилировался без каких либо предупреждений и ошибок.
Но функция в итоге не была синхронизирована со всеми вытекающими.
Ловили достаточно долго.
В солярисе просто в каком-то из системных хидеров есть структура mutex.
Ну и получилось объявление функции...
А и еще по топику:
В gdb и dbx можно поставить breakpoint на место броска исключения.
Так шта...
Включайте в редакторе подсветку пробелов — узнаете много интересного.
Заодно и своих коллег обогатите словарным запасом в адрес их привычек к табуляции (и в адрес авторов стандартных библиотек и визардов тоже) .
А кстати: кому-нибудь зачем-нибудь нужна функция редактора "курсор за концом строки"?
V>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>...
V>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>...
Мда, с точки зрения быдлокодера — проект — это код, который в лучшем случае был успешно скомпилирован. Компилируется — проект завершен
Здравствуйте, Pyromancer, Вы писали:
ДД>>Интересно: что, не было никакой возможности стек раскрутить?
P>Так если рандомайз был то оно все время в разных местах получалось.
Под unix'ом, например, корку можно исследовать.
P>Да и в дебаггере не видно же с чего это ретурн эксепшн вдруг кидает
Просто надо правильными дебаггерами пользоваться
В ассемблерном представлении честный return и throw std::exception() очень отличаются.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, catBasilio, Вы писали:
SD>>первый же редактор с раскраской макросов отдельным цветом спалил бы этого чудика. SD>>так что "не верю" (с)
B>Пробовал в эклипсе. Не спалил. Походу у него для ключевых слов приоритет выше.
V>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>...
"Не верю!" (с) Станиславский
"cfdc.h", line 7: Warning: keyword "return" is being redefined.
S>>Надо ли говорить, что наш проект использовал в одном незначительном месте стандартный генератор случайных чисел, а вызываемый при инициализации std::randomize() успешно заметал любые следы?.
M>я не С++ник, но по-моему имелось в виду, что если б рандомазе не использовался нигде в коде программы, M>то при выполнении одной и той же последовательности действий после запуска программы, она вылетала бы о одних и тех же местах. M>нет?
ну, на самом деле, программа вылетала бы после выполнения определенного количества инструкций return. но вот где это происходило бы — зависит от программы. если число довольно большое, и программа представляет собой что-то гуевое — результат мог бы быть таким же (крах в произвольном месте). Другое дело, что при очень большом числе в условии бабаха, этого краха можно было бы и не дождаться
Надо ли говорить, что наш проект использовал в одном незначительном месте стандартный генератор случайных чисел, а вызываемый при инициализации std::randomize() успешно заметал любые следы?.
Шурыгин Сергей
"Не следует преумножать сущности сверх необходимости" (с) Оккам
Здравствуйте, SleepyDrago, Вы писали:
SD>Здравствуйте, Vain, Вы писали:
V>>здесь V>>
V>>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>>...
SD>первый же редактор с раскраской макросов отдельным цветом спалил бы этого чудика. SD>так что "не верю" (с)
Пробовал в эклипсе. Не спалил. Походу у него для ключевых слов приоритет выше.
UNIX way — это когда тебе вместо туалетной бумаги дают топор, рубанок и карту близлежащего леса
Здравствуйте, ДимДимыч, Вы писали:
ДД>>>Интересно: что, не было никакой возможности стек раскрутить? P>>Так если рандомайз был то оно все время в разных местах получалось. ДД>Под unix'ом, например, корку можно исследовать. P>>Да и в дебаггере не видно же с чего это ретурн эксепшн вдруг кидает ДД>Просто надо правильными дебаггерами пользоваться ДД>В ассемблерном представлении честный return и throw std::exception() очень отличаются.
Тем более с нормальным ИДЕ оно его будет подсвечивать как макрос, так что даже до ассемблера не должно было дойти
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
ДД>>В ассемблерном представлении честный return и throw std::exception() очень отличаются. V>Тем более с нормальным ИДЕ оно его будет подсвечивать как макрос, так что даже до ассемблера не должно было дойти
Иногда return перегружают для логгирования результатов вызова функций.
Здравствуйте, catBasilio, Вы писали:
SD>>первый же редактор с раскраской макросов отдельным цветом спалил бы этого чудика. SD>>так что "не верю" (с)
B>Пробовал в эклипсе. Не спалил. Походу у него для ключевых слов приоритет выше.
таки да. в xcode тоже самое. переход на определение работает, подсветка нет.
как страшно жить
Здравствуйте, Кодт, Вы писали:
К>Твоё true — не труъ,
Это не мое
К> ибо не является константой времени компиляции, и выдаст кучу ошибок
И это хорошо, правда же
Здравствуйте, e-Xecutor, Вы писали:
EX>Здравствуйте, Vain, Вы писали:
V>>здесь V>>
V>>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>>...
EX>"Не верю!" (с) Станиславский EX>
EX>"cfdc.h", line 7: Warning: keyword "return" is being redefined.
EX>
Здравствуйте, Vlad_SP, Вы писали:
V_S>Здравствуйте, Muxa, Вы писали:
V_S>что-то мне подсказывает, что в описанном случае не только комментариев к коммитам, но и самой VCS и в помине не было....
не, а что вы хотите в комментариях к коммиту увидеть?...
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, Vain, Вы писали:
V>>здесь ДД>
Как выяснилось, периодически возникало std::exception, но отследить, откуда оно бралось, у меня никак не получалось
ДД>Интересно: что, не было никакой возможности стек раскрутить?
вся прелесть в том, что return переопределен define-ом. В таком случае в дебаггере то, что спрятано в дефайне, просто не видно. сам матерюсь про такие участки нашего проекта....
Здравствуйте, ssmaslov, Вы писали:
S>Здравствуйте, Vlad_SP, Вы писали:
V_S>>Здравствуйте, Muxa, Вы писали:
V_S>>что-то мне подсказывает, что в описанном случае не только комментариев к коммитам, но и самой VCS и в помине не было....
S>не, а что вы хотите в комментариях к коммиту увидеть?...
S>
S>уволили меня несправедливо? ПОЛУЧАЙТЕ!!!
чисто для проверки убедиться, что чел перед увольнением ничего не коммитил. Или прочекать все, что было закоммичено. Но это тоже легко обойти (типа закоммитить от другого пользователя)
Здравствуйте, March_rabbit, Вы писали:
M_>вся прелесть в том, что return переопределен define-ом. В таком случае в дебаггере то, что спрятано в дефайне, просто не видно. сам матерюсь про такие участки нашего проекта....
Повторюсь:
Просто надо правильными дебаггерами пользоваться
В ассемблерном представлении честный return и throw std::exception() очень отличаются.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, robin_of_the_wood, Вы писали:
___>Code review или хотя бы просмотр комитов начальником делает такое почти невозможным
Так вроде как данный заголовочный файл не был включен в дерево исходников (в рассказе сказано, что дома из исходников не собралось). Наверное, обиженный программер подсунул его к системным библиотекам на машине где осуществляется сборка релизов для тестирования.
Здравствуйте, NikeByNike, Вы писали:
NBN>Подумал, что надо было сделать ошибку один раз на миллион вызовов или ещё больше, так было бы не очевидно, что надо что-то искать.
Смотря еще что за программа, где и как выполняется. Автоматизированное тестирование, бывает, успешно выявляет ошибки, возникающие и с меньшей вероятностью.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
NBN>>Подумал, что надо было сделать ошибку один раз на миллион вызовов или ещё больше, так было бы не очевидно, что надо что-то искать.
ДД>Смотря еще что за программа, где и как выполняется. Автоматизированное тестирование, бывает, успешно выявляет ошибки, возникающие и с меньшей вероятностью.
Выявить-то выявит, это не вопрос. Вопрос в том — как бы будешь интерпретировать, допустим, возникающую раз в день ошибку в случайном месте (особенно если не слишком опытен)? Опа — тестирование выявило падение. Проверили — не повторяется.
На следующий день упало в другом месте, проверили — не воспроизводится.
Для большей злобы, естественно, имеет смысл кидать не std::exception, а что-нибудь посистемнее, хотя бы запись в нулевой указатель. А можно и просто-где-нибудь в случайном месте память подгадить, ничего не сообщая.
Здравствуйте, NikeByNike, Вы писали:
NBN>Выявить-то выявит, это не вопрос. Вопрос в том — как бы будешь интерпретировать, допустим, возникающую раз в день ошибку в случайном месте (особенно если не слишком опытен)? Опа — тестирование выявило падение. Проверили — не повторяется.
При падении дамп процесса нужно снимать. Или в крайнем случае хотя бы адрес, по которому спровоцировалось исключение. Не знаю, что за платформа была у байкера (от слова байка, а не байк ), но неужели есть такие, где это невозможно? В молодости на delphi программировал, так там необработанное исключение окно показывало: такое-то исключение по такому-то адресу. Если из-под IDE запускаешь или в системе JIT-дебаггер зарегистрирован, то клацаешь "Debug" — и вот оно тебе то место, откуда исключение. А там вместо xor eax,eax\leave\ret какой-нибудь call __throw. В юниксах еще проще.
Ну а если не слишком опытен — так это не повод называть тривиальную подставу "садистским кодом".
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>При падении дамп процесса нужно снимать. Или в крайнем случае хотя бы адрес, по которому спровоцировалось исключение. Не знаю, что за платформа была у байкера (от слова байка, а не байк ), но неужели есть такие, где это невозможно? В молодости на delphi программировал, так там необработанное исключение окно показывало: такое-то исключение по такому-то адресу. Если из-под IDE запускаешь или в системе JIT-дебаггер зарегистрирован, то клацаешь "Debug" — и вот оно тебе то место, откуда исключение. А там вместо xor eax,eax\leave\ret какой-нибудь call __throw. В юниксах еще проще. ДД>Ну а если не слишком опытен — так это не повод называть тривиальную подставу "садистским кодом".
Ну вот выдало тебе в дамп что функция:
int GetOne() { return 1; }
попыталась что-то записать по нулевому адресу. Ты на неё смотришь — всё нормально Запускаешь — нормально. Ага, делаешь вывод ты, опять у этой грёбанной висты где-то драйвера лажанули, или это китайская память виновата.
А что скажешь про вариант порчи памяти? Какой дамп тут поможет?
Здравствуйте, NikeByNike, Вы писали:
NBN>Ну вот выдало тебе в дамп что функция: NBN>int GetOne() { return 1; } NBN>попыталась что-то записать по нулевому адресу. Ты на неё смотришь — всё нормально Запускаешь — нормально.
Буду смотреть на ее ассемблерное представление. Буду проходить по ней отладчиком пошагово по инструкциям. Для эффективного поиска и справления ошибок нужно переставать верить в чудеса.
NBN>Ага, делаешь вывод ты, опять у этой грёбанной висты где-то драйвера лажанули, или это китайская память виновата.
Ну уж не знаю, насколько надо быть "не слишком опытным", чтобы в возникновении спонтанных исключений в конкретной программе сразу винить драйвера. Я допускаю, конечно, что такая ситуация возможна, но перед тем как ее рассматривать, следует рассмотреть более очевидные причины.
NBN>А что скажешь про вариант порчи памяти? Какой дамп тут поможет?
В смысле, когда ошибки из-за реальных проблем с памятью? Такие ошибки проявляются не на одной конкретной программе, зато на одной конкретной машине.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, Muxa, Вы писали:
___>>Code review или хотя бы просмотр комитов начальником делает такое почти невозможным
M>вот начальнику заняться больше не чем — коммиты (с двумя М, кстати) отслеживать.
Если у начальника дел много — коллеги могли бы этим заниматься.
Очень полезно, люди будут знать кто чем занимается и как что-либо сделать.
Здравствуйте, ДимДимыч, Вы писали:
NBN>>int GetOne() { return 1; } NBN>>попыталась что-то записать по нулевому адресу. Ты на неё смотришь — всё нормально Запускаешь — нормально.
ДД>Буду смотреть на ее ассемблерное представление. Буду проходить по ней отладчиком пошагово по инструкциям. Для эффективного поиска и справления ошибок нужно переставать верить в чудеса.
Ну да, это выход, достаточно эффективный. Но перед тем как этим заняться, наверное сначала будешь анализировать код? Я имею в виду, что при возникновении редкой ошибки — не сразу догадаешься, что обычный ретурн может лажать. Я бы в таком случае предположил несколько других проблем.
NBN>>Ага, делаешь вывод ты, опять у этой грёбанной висты где-то драйвера лажанули, или это китайская память виновата.
ДД>Ну уж не знаю, насколько надо быть "не слишком опытным", чтобы в возникновении спонтанных исключений в конкретной программе сразу винить драйвера. Я допускаю, конечно, что такая ситуация возможна, но перед тем как ее рассматривать, следует рассмотреть более очевидные причины.
Спонтанные падения бывают при порче памяти. Так же были малопонятные падения:
1. забыли написать ретурн в одной функции — которая возвращала сложный объект. Варнинга об этом вроде-бы не было. Падало совсем в другой функции по малопонятной причине и только в релизе.
2. падало в случайном месте при выполнении потока занятого проигрыванием звука. На 1 компе из 10. Падало вместе с операционкой (XP) — даже файлы повреждались из-за незафлушенности.
Причина — модуль отвечающий за сетевое взаимодействие — выставлял специальные флажки процессору, чтобы на АМД и Интел вычисления с плавающей точкой вели себя одинаково.
NBN>>А что скажешь про вариант порчи памяти? Какой дамп тут поможет? ДД>В смысле, когда ошибки из-за реальных проблем с памятью? Такие ошибки проявляются не на одной конкретной программе, зато на одной конкретной машине.
В смысле, что вредитель вместо исключения — пишет чего-нибудь рандомное куда-нибудь в память?
alzt пишет: > > M>вот начальнику заняться больше не чем — коммиты (с двумя М, кстати) > отслеживать. > > Если у начальника дел много — коллеги могли бы этим заниматься. > Очень полезно, люди будут знать кто чем занимается и как что-либо сделать.
Во, но в данном случае еще проще творить ИБД.
Здравствуйте, NikeByNike, Вы писали:
NBN>Спонтанные падения бывают при порче памяти. Так же были малопонятные падения: NBN>1. забыли написать ретурн в одной функции — которая возвращала сложный объект. Варнинга об этом вроде-бы не было. Падало совсем в другой функции по малопонятной причине и только в релизе. NBN>2. падало в случайном месте при выполнении потока занятого проигрыванием звука. На 1 компе из 10. Падало вместе с операционкой (XP) — даже файлы повреждались из-за незафлушенности. NBN>Причина — модуль отвечающий за сетевое взаимодействие — выставлял специальные флажки процессору, чтобы на АМД и Интел вычисления с плавающей точкой вели себя одинаково.
Занятно.
У нас был случай: спонтанно начинало неправильно работать одно из периферийных устройств. Так как в продукте уровней абстракции много и предыдущие выявленные ошибки были в верхних уровнях, то причину искали в первую очередь в них. А причина выявилась позже, когда все-таки сняли осциллограмму с шины. Оказалось, что в новой, еще необкатанной линейке system-on-chip процессоров после определенного времени работы при определенной температуре (!) I²C-контроллер начинает clock'и передавать с некоторой задержкой. Не настолько малой, чтобы вписываться в тайминги по спецификации, но не настолько большой, чтобы все устройства, кроме одного, перестали принимать данные.
NBN>В смысле, что вредитель вместо исключения — пишет чего-нибудь рандомное куда-нибудь в память?
А, в этом смысле. Да, это более жестоко. Но все же, если это в обычном процессе, то такая порча затронет память только этого процесса — варианты с хардварными причинами и драйверами становятся маловероятными. И вредителю придется позаботится о том, чтобы запись с большой вероятность приходилась на доступную область, потому как запись в недоступную выявится так же быстро, по адресу вызвавшей ее инструкции.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
V>Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
V>...
надо было пользоваться vim-ом
set wrap и вся строка на экране, ничего не "уползет".
Ну и почаще смотреть вывод после отработки препроцессора, a.k.a. gcc -E ...
Здравствуйте, Кодт, Вы писали:
К>Включайте в редакторе подсветку пробелов — узнаете много интересного. К>Заодно и своих коллег обогатите словарным запасом в адрес их привычек к табуляции (и в адрес авторов стандартных библиотек и визардов тоже) .
К>А кстати: кому-нибудь зачем-нибудь нужна функция редактора "курсор за концом строки"?
только в одном случае — ASCII артом рисовать (таблички).
Здравствуйте, RedUser, Вы писали:
RU>В старых компиляторах (вроде VC++ 6.0, BC++ 5.0) хидеры, которые сейчас без .h, были с .h.
Не надо путать
— хедеры сишной стандартной библиотеки (apropos: header ['hedэ]) — традиционно, с .h
— достандартные С++ные (такие как iostream.h — достандартные потоки) — в старых компиляторах оставались для поддержки древностей
— хедеры стандартной библиотеки С++ (cstring — обёртка namespace std{ #include <string.h> }, string — STL-ные строки, iostream — STL-ные потоки)
То есть, это не вопрос окончания ".h", а вообще разное содержимое.
Здравствуйте, March_rabbit, Вы писали:
M_>Здравствуйте, ssmaslov, Вы писали:
S>>Здравствуйте, Vlad_SP, Вы писали:
V_S>>>Здравствуйте, Muxa, Вы писали:
V_S>>>что-то мне подсказывает, что в описанном случае не только комментариев к коммитам, но и самой VCS и в помине не было....
S>>не, а что вы хотите в комментариях к коммиту увидеть?...
S>>
S>>уволили меня несправедливо? ПОЛУЧАЙТЕ!!!
M_>чисто для проверки убедиться, что чел перед увольнением ничего не коммитил. Или прочекать все, что было закоммичено. Но это тоже легко обойти (типа закоммитить от другого пользователя)
А если(хотя скорее всего) этому несправедливо уволенному дали 2 недели на то, чтоб закрыть все что на нем висит, там коммитов масса могла быть... понятно, что круг поиска можно было бы сузить
Здравствуйте, ДимДимыч, Вы писали:
ДД>А, в этом смысле. Да, это более жестоко. Но все же, если это в обычном процессе, то такая порча затронет память только этого процесса — варианты с хардварными причинами и драйверами становятся маловероятными. И вредителю придется позаботится о том, чтобы запись с большой вероятность приходилась на доступную область, потому как запись в недоступную выявится так же быстро, по адресу вызвавшей ее инструкции.
Можно, например, написать inline или шаблонную функцию, которая будет фигачить в случайное место случайными данными, и ловить АV...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, March_rabbit, Вы писали:
S>>не, а что вы хотите в комментариях к коммиту увидеть?...
S>>
уволили меня несправедливо? ПОЛУЧАЙТЕ!!!
M_>чисто для проверки убедиться, что чел перед увольнением ничего не коммитил. Или прочекать все, что было закоммичено. Но это тоже легко обойти (типа закоммитить от другого пользователя)
В одной конторе, в день, когда стало понятно, что я тут больше работать не буду, мне обрубили доступ к репозиторию. Представляете мое состояние: я правлю код, чтобы отдать мою текущую работу в понятном для моего приемника виде, собираюсь чекиниться, и тут опа, наблюдаю, как в TortoiseSVN начинают пропадать папки.
Честно говоря, я был в шоке
Видимо, у моего тогдашнего начальника Михи был соответствующий опыт "несправедливо уволенных"
Оставшееся до официально прощаяния время я, кажется, просто сидел на рабочем месте...
Пользуясь случаем, хочу передать привет этому самаому Михе