Désolé !
Une erreur est survenue lors du traitement de votre requête :
Cet article n’existe pas. Il est possible qu’il ait été supprimé par la personne qui l’a créé.
Voici un lien vers la page d’accueil de la communauté Steam.
© Valve Corporation. Tous droits réservés. Toutes les marques commerciales sont la propriété de leurs titulaires aux États-Unis et dans d’autres pays. Certaines données géographiques de ce site sont fournies par geonames.org.
Politique de protection de la vie privée | Mentions légales | Accord de souscription Steam | Cookies
В «osu!» играй, про ошибки не забывай
Приветствуем всех любителей экзотических и не очень ошибок в коде. Сегодня на тестовом стенде PVS-Studio достаточно редкий гость – игра на языке C#. А именно – «osu!». Как обычно: ищем ошибки, думаем, играем.
Игра
Osu! – музыкальная ритм-игра с открытым исходным кодом. Судя по информации с сайта игры – довольно популярная, так как заявлено более 15 миллионов зарегистрированных игроков. Проект характеризуют бесплатный геймплей, красочное оформление с возможностью кастомизации карт, продвинутые возможности для составления онлайн-рейтинга игроков, наличие мультиплеера, большой набор музыкальных композиций. Подробно описывать игру не буду, интересующиеся легко найдут всю информацию в сети. Например, тут.
Мне больше интересен исходный код проекта, который доступен для загрузки с GitHub. Сразу привлекает внимание значительное число коммитов (более 24 тысяч) в репозиторий, что говорит об активном развитии проекта, которое продолжается и в настоящее время (игра была выпущена в 2007 году, но работы, вероятно, были начаты раньше). При этом исходного кода не так много – 1813 файлов .cs, которые содержат 135 тысяч строк кода без учёта пустых. В этом коде присутствуют тесты, которые я обычно не учитываю в проверках. Код тестов содержится в 306 файлах .cs и, соответственно, 25 тысячах строк кода без учёта пустых. Это маленький проект: для сравнения, ядро C# анализатора PVS-Studio содержит около 300 тысяч строк кода.
Итого, для проверки игры на ошибки я использовал не тестовые проекты, содержащие 1507 файлов исходного кода и 110 тысяч строк. Однако результат меня отчасти порадовал, так как нашлось несколько интересных ошибок, о которых я спешу вам рассказать.
Ошибки
V3001 There are identical sub-expressions ‘result == HitResult.Perfect’ to the left and to the right of the ‘||’ operator. DrawableHoldNote.cs 266
protected override void CheckForResult(. ) < . ApplyResult(r =>< if (holdNote.hasBroken && (result == HitResult.Perfect || result == HitResult.Perfect)) result = HitResult.Good; . >); >
Хороший пример копипаст-ориентированного программирования. Шуточный термин, который недавно использовал (ввёл) мой коллега Валерий Комаров в своей статье «Топ 10 ошибок в проектах Java за 2019 год».
Итак, две идентичных проверки следуют одна за другой. Одна из проверок, скорее всего, должна содержать другую константу перечисления HitResult:
public enum HitResult
Какую именно константу нужно было использовать, или вторая проверка вообще не нужна? Вопросы, на которые способен ответить только разработчик. В любом случае, допущена ошибка, искажающая логику работы программы.
V3001 There are identical sub-expressions ‘family != GetFamilyString(TournamentTypeface.Aquatico)’ to the left and to the right of the ‘&&’ operator. TournamentFont.cs 64
public static string GetWeightString(string family, FontWeight weight)
И снова copy-paste. Я отформатировал код, поэтому ошибка легко заметна. В первоначальном варианте всё условие было записано одной строкой. Здесь также трудно сказать, каким образом можно исправить код. Перечисление TournamentTypeface содержит единственную константу:
public enum TournamentTypeface
Возможно, в условии дважды по ошибке использована переменная family, но это не точно.
V3009 [CWE-393] It’s odd that this method always returns one and the same value of ‘false’. KeyCounterAction.cs 19
public bool OnPressed(T action, bool forwards) < if (!EqualityComparer.Default.Equals(action, Action)) return false; IsLit = true; if (forwards) Increment(); return false; >
Метод всегда вернёт false. Для таких ошибок я обычно проверяю вызывающий код, так как там часто просто нигде не используют возвращаемое значение, тогда ошибки (кроме некрасивого стиля программирования) нет. В данном случае мне встретился такой код:
public bool OnPressed(T action) => Target.Children .OfType>() .Any(c => c.OnPressed(action, Clock.Rate >= 0));
Как видим, результат, возвращаемый методом OnPressed, используется. И так как он всегда false, то и результат вызывающего OnPressed также будет всегда false. Думаю, следует лишний раз перепроверить этот код, так как высока вероятность ошибки.
Ещё одна подобная ошибка:
- V3009 [CWE-393] It’s odd that this method always returns one and the same value of ‘false’. KeyCounterAction.cs 30
public TournamentTeam() < Acronym.ValueChanged += val =>< if (. ) FlagName.Value = val.NewValue.Length >= 2 // ; . >
В условии оператора ?: с переменной val.NewValue работают небезопасно. Анализатор сделал такой вывод, так как далее в then-ветке для доступа к переменной используют безопасный вариант работы через оператор условного доступа val.NewValue?.Substring(. ).
Ещё одна подобная ошибка:
- V3042 [CWE-476] Possible NullReferenceException. The ‘?.’ and ‘.’ operators are used for accessing members of the ‘val.NewValue’ object TournamentTeam.cs 48
private void reload() < . new ActionableInfo < Label = "Current User", ButtonText = "Change Login", Action = () =>< api.Logout(); // , Value = api?.LocalUser.Value.Username, . >, . > private class ActionableInfo : LabelledDrawable
Данный код менее однозначен, но я думаю, что ошибка тут всё же присутствует. Создают объект типа ActionableInfo. Поле Action инициализируют лямбдой, в теле которой небезопасно работают с потенциально нулевой ссылкой api. Анализатор посчитал такой паттерн ошибкой, так как далее при инициализации параметра Value с переменной api работают безопасно. Ошибку я назвал неоднозначной, потому что код лямбды предполагает отложенное выполнение и тогда, возможно, разработчик как-то гарантирует ненулевое значение ссылки api. Но это только предположение, так как тело лямбды не содержит никаких признаков безопасной работы со ссылкой (предварительных проверок, например).
V3066 [CWE-683] Possible incorrect order of arguments passed to ‘Atan2’ method: ‘diff.X’ and ‘diff.Y’. SliderBall.cs 182
public void UpdateProgress(double completionProgress) < . Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); . >
Анализатор заподозрил, что при работе с методом Atan2 класса Math разработчик перепутал порядок следования аргументов. Объявление Atan2:
// Parameters: // y: // The y coordinate of a point. // // x: // The x coordinate of a point. public static double Atan2(double y, double x);
Как видим, были переданы значения в обратном порядке. Не берусь судить, ошибка ли это, так как метод UpdateProgress содержит довольно много нетривиальных вычислений. Просто отмечу факт возможной проблемы в коде.
V3080 [CWE-476] Possible null dereference. Consider inspecting ‘Beatmap’. WorkingBeatmap.cs 57
protected virtual Track GetVirtualTrack()
Анализатор указал на опасность доступа по нулевой ссылке Beatmap. Вот что она собой представляет:
public IBeatmap Beatmap < get < try < return LoadBeatmapAsync().Result; >catch (TaskCanceledException) < return null; >> >
Ну что же, анализатор прав.
Подробнее про то, как PVS-Studio находит такие ошибки, а также о нововведениях C# 8.0, связанных с подобной тематикой (работа с потенциально нулевыми ссылками), можно узнать из статьи «Nullable Reference типы в C# 8.0 и статический анализ».
V3083 [CWE-367] Unsafe invocation of event ‘ObjectConverted’, NullReferenceException is possible. Consider assigning event to a local variable before invoking it. BeatmapConverter.cs 82
private List convertHitObjects(. ) < . if (ObjectConverted != null) < converted = converted.ToList(); ObjectConverted.Invoke(obj, converted); >. >
Некритичная и довольно часто встречающаяся ошибка. Между проверкой события на равенство null и его инвокацией, от события могут отписаться, что приведет к падению программы.
Один из вариантов исправления:
private List convertHitObjects(. )
V3095 [CWE-476] The ‘columns’ object was used before it was verified against null. Check lines: 141, 142. SquareGraph.cs 141
private void redrawProgress()
Обход коллекции columns в цикле производят небезопасно. При этом разработчик предполагал, что ссылка columns может быть нулевой, так как далее в коде для доступа к коллекции используют оператор условного доступа.
V3119 Calling overridden event ‘OnNewResult’ may lead to unpredictable behavior. Consider implementing event accessors explicitly or use ‘sealed’ keyword. DrawableRuleset.cs 256
private void addHitObject(TObject hitObject) < . drawableObject.OnNewResult += (_, r) =>OnNewResult?.Invoke(r); . > public override event Action OnNewResult;
Анализатор предупреждает об опасности использования переопределённого или виртуального события. В чём именно заключается опасность – предлагаю почитать в описании к диагностике. Также в своё время я писал на эту тему статью «Виртуальные события в C#: что-то пошло не так».
Ещё одна подобная небезопасная конструкция в коде:
- V3119 Calling an overridden event may lead to unpredictable behavior. Consider implementing event accessors explicitly or use ‘sealed’ keyword. DrawableRuleset.cs 257
private void onScreenChange(IScreen prev, IScreen next)
Для лучшего понимания проблемы – приведу синтетический пример того, как сейчас работает код:
x = (c * a) ?? b;
Ошибка была допущена вследствие того, что оператор «*» имеет более высокий приоритет, чем оператор «??». Исправленный вариант кода (добавлены скобки):
private void onScreenChange(IScreen prev, IScreen next)
Ещё одна подобная ошибка в коде:
V3123 [CWE-783] Perhaps the ‘??’ operator works in a different way than it was expected. Its priority is lower than priority of other operators in its left part. FramedReplayInputHandler.cs 103
private bool inImportantSection < get < . return IsImportant(frame) && Math.Abs(CurrentTime - NextFrame?.Time ?? 0) >
Здесь, как и в предыдущем фрагменте кода, не учли приоритет операторов. Сейчас выражение, передаваемое в метод Math.Abs, вычисляется так:
(a – b) ?? 0
Исправленный код:
private bool inImportantSection < get < . return IsImportant(frame) && Math.Abs(CurrentTime – (NextFrame?.Time ?? 0)) >
V3142 [CWE-561] Unreachable code detected. It is possible that an error is present. DrawableHoldNote.cs 214
public override bool OnPressed(ManiaAction action) < if (!base.OnPressed(action)) return false; if (Result.Type == HitResult.Miss) //
Анализатор утверждает, что код обработчика OnPressed, начиная со второго оператора if, является недостижимым. Это следует из предположения, что первое условие всегда истинно, то есть метод base.OnPressed всегда вернет false. Взглянем на метод base.OnPressed:
public virtual bool OnPressed(ManiaAction action)
Переходим далее к методу UpdateResult:
protected bool UpdateResult(bool userTriggered)
Обратите внимание, реализация свойства Judged здесь не важна, так как из логики метода UpdateResult следует, что последний оператор return эквивалентен такому:
return false;
Таким образом, метод UpdateResult всегда вернет false, что и приведет к возникновению ошибки с недостижимым кодом в коде выше по стеку.
V3146 [CWE-476] Possible null dereference of 'ruleset'. The 'FirstOrDefault' can return default null value. APILegacyScoreInfo.cs 24
public ScoreInfo CreateScoreInfo(RulesetStore rulesets) < var ruleset = rulesets.GetRuleset(OnlineRulesetID); var mods = Mods != null ? ruleset.CreateInstance() // (); . >
Анализатор считает небезопасным вызов ruleset.CreateInstance(). Переменная ruleset ранее получает значение в результате вызова GetRuleset:
public RulesetInfo GetRuleset(int id) => AvailableRulesets.FirstOrDefault(. );
Как видим, предупреждение анализатора обосновано, так как цепочка вызовов содержит FirstOrDefault, который может вернуть значение null.
Заключение
В целом проект игры «osu!» порадовал небольшим числом ошибок. Тем не менее, я рекомендую разработчикам обратить внимание на обнаруженные проблемы. И пусть игра и далее радует своих поклонников.
А для любителей поковыряться в коде напоминаю, что хорошим подспорьем будет анализатор PVS-Studio, который легко скачать с официального сайта. Также замечу, что разовые проверки проектов, подобные описанной выше, не имеют ничего общего с использованием статического анализатора в реальной работе. Максимальной эффективности в борьбе с ошибками можно добиться лишь при регулярном использовании инструмента как на сборочном сервере, так и непосредственно на компьютере разработчика (инкрементальный анализ). При этом задача максимум – вовсе не допустить попадания ошибок в систему контроля версий, исправляя дефекты уже на этапе написания кода.
Удачи и творческих успехов!
Ссылки
Это первая публикация в 2020 году. Пользуясь случаем, я приведу ссылки на статьи о проверке C#-проектов за прошлый год:
- Ищем ошибки в исходном коде Amazon Web Services SDK для .NET
- Проверяем исходный код Roslyn
- Nullable Reference типы в C# 8.0 и статический анализ
- WinForms: ошибки, Холмс
- История о том, как PVS-Studio нашёл ошибку в библиотеке, используемой в… PVS-Studio
- Проверка исходного кода библиотек .NET Core статическим анализатором PVS-Studio
- Проверяем Roslyn analyzers
- Проверка Telerik UI for UWP для знакомства с PVS-Studio
- Azure PowerShell: «в основном безвреден»
- Ищем и анализируем ошибки в коде Orchard CMS
- Проверка обёртки OpenCvSharp над OpenCV с помощью PVS-Studio
- Azure SDK for .NET: история о непростом поиске ошибок
- SARIF SDK и его ошибки
- Топ 10 ошибок в проектах C# за 2019 год
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Sergey Khrenov. Play «osu!», but Watch Out for Bugs.
Статьи бизнес-тренеров
Первым и явным признаком неэффективности организационной структуры управления (ОСУ) является ситуация, когда генеральный директор начинает сам рисовать квадратики, соединенные линиями, с фамилиями и названиями подразделений.
Вторым – когда, поняв, что сам не справится, генеральный вызывает ближайших доверенных сотрудников и поручает «рисование» им.
Третьим – когда, получив вариант, устраивающий всех топ-менеджеров, генеральный директор начинает понимать, что такой вариант не устраивает его самого. И он опять начинает рисовать квадратики.…
Симптомокомплекс организационных «художников»
Но что вообще служит поводом для всех этих рисунков из квадратиков, фамилий и названий? Симптомов, как правило, несколько, и проявляются они в следующем:
- директор инстинктивно начинает чувствовать, что что-то явно не то;
- падает исполнительская дисциплина: в большинстве подобных ситуаций процент выполнения приказов директора качественно и в срок не превышает 8-9 %;
- на уровне менеджмента среднего звена появляются, обычно, 2 или 3 «незаменимых» руководителя, к которым идут за решением вопросов даже те, кто им и не подчиняется; и даже по тем вопросам, которые, официально не в их компетенции;
- пропадает коллегиальность и открытость при подведении итогов работы, формированию требований к продажам и закупкам, их реальному исполнению;
- премии начинают выплачивать не на основании утвержденной системы экономической мотивации, а на основании решений неформальной группы внутренних лидеров;
- утвержденной и реально действующей системы экономической мотивации для самого генерального директора и топ-менеджеров нет;
- генеральный директор начинает бояться уволить некоторых менеджеров, а собственники – уволить самого директора, из опасений, что за этим последует развал компании или серьезная потеря качества бизнеса.
Чем это чревато? В первую очередь, системным сбоем. Необходимо помнить, что в ОСУ содержится информация не только о том, кто и кому подчиняется, но и о том, кто за какой функционал отвечает. Это определяет и оценки и систему показателей экономической мотивации всех подразделений и менеджеров всех уровней соответственно. Т.е., при неформальной схеме управления в виде ОСУ, системы оценок и мотивации начинают носить формальный характер и выпадают из реального управления. Возникает система неформальных оценок и неформальной мотивации в условиях реальных денежных потоков. И это опасно различного рода последствиями. Какими? Это проще рассмотреть на примере реальной компании.
КОГДА СИТУАЦИЯ УПРАВЛЯЕТ ДИРЕКТОРОМ
Дискомфорт в управлении генеральный директор компании «А**ка» выразил, с одной стороны, в весьма туманной, но, с другой стороны, в достаточно ясной фразе: «Мне кажется, что не я управляю ситуацией в компании, а ситуация мной!» В начале 2008 года компания представляла собой активного участника рынка Москвы и Московской области в сегменте определенного вида хозяйственных товаров народного потребления. Численность компании составляла 280 человек, включая всех специалистов, менеджеров, рабочих складов и сборочного цеха. Типичная торгово-производственная компания. И, как потом выяснилось, с достаточно типичным набором проблем. Включая проблемы организационной структуры управления. Анализ начался именно с нее.
Первой проблемой оказалось несоответствие утвержденной организационной структуры управления реальной. Надо отметить, что для предприятий малого и среднего бизнеса такое несоответствие реальной и утвержденной ОСУ обычное дело.
Очень важно уметь отслеживать и настраивать реальную организационную структуру управления. Дело в том, что на практике происходят непрерывные искажения ОСУ, которые могут быть обусловлены несколькими причинами.
Во-первых, возникновением неформальных лидеров. Которые, в силу объективных обстоятельств, выделяются в рамках организационной структуры и, в том или ином виде, перетягивают на себя «одеяло управления». Происходит так называемое искажение функционала.
Во-вторых, обычным делом, в случае слабости отдела по работе с персоналом, является длительное не закрытие вакансий менеджеров среднего звена и, особенно, топ-менеджеров. В этих случаях происходит переподчинение ряда линейных подразделений другим руководителям. И эта ситуация начинает носить постоянный характер, не отражаясь тем не менее в организационной структуре управления. Изменение требований к специалистам и подразделениям, для которых произошло это естественное, но якобы временное переподчинение, не происходит. В итоге возникает коллизия между реальным функционалом, который реализует тот или иной менеджер среднего звена либо топ-менеджер и ответственностью, в виде показателей, которые должны быть учтены в системе его мотивации, но соответствующим образом не учтены.
Следующим существенным моментом, который во многом определяет нереальность ОСУ, является внесение в ОСУ подразделений, либо специалистов, либо каких-нибудь еще элементов, которые вводятся в расчете на решение будущих задач организации. Т.е. реальная потребность в таком элементе еще не возникла, но уже переписывается организационно-штатное расписание, меняется фонд заработной платы, и в организационной структуре управления появляется подразделение, которое не имеет актуального значения в рассматриваемый период. Возникают так называемые «мнимые элементы» ОСУ, которые, на самом деле, просто искажают реальную структуру управления.
ПРОБЛЕМНОЕ ПОЛЕ ОРГАНИЗАЦИОННЫХ ЧУДЕС
В рамках исследования уже реального состояния ОСУ выявилось следующее:
1. Компания имеет 5 уровней иерархии. В данном случае под уровнями иерархии понимаем количество «этажей» руководителей, исключая первое лицо (ЛПР). При условии, что для компаний численностью от 150 до 500 сотрудников оптимальное количество таких уровней может составлять не более трех, а предельное не выше четырех (причем четвертый уже будет избыточным), можно сказать, что в компании проявился очевидный избыток и явный недогруз менеджеров среднего звена. Это проявилось очень ярко при расчете лимитов коммуникации каждого руководителя. Их (руководителей) оказалось 54 человека при общей численности персонала компании, напомню, в 280 человек. То есть, 19,3 % от общей численности сотрудников компании составляют руководители. Это явно выше нормы, которая для компаний численностью 150–500 человек, не должна превышать 14 %. Из этих руководителей 39 человек (72,2 % от общего числа руководителей) имели показатели лимита коммуникаций (предельно допустимое количество непосредственных подчиненных, которыми руководитель может руководить эффективно) в 2–2,4 раза ниже нормального уровня.
На практике, для компаний класса 150–500 человек, оптимальное значение показателя лимита коммуникаций следующее: для линейных менеджеров – от 10 (крайний минимум) до 20 (предельный максимум) подчиненных; для менеджеров среднего звена, топ-менеджмента и ЛПР – от 7 до 10 подчиненных. Особенно необходимо выделить значение лимита коммуникаций для первого руководителя: в случае если реальный лимит коммуникаций превышает предельное значение, это будет на практике означать, что реально генеральный директор не сможет эффективно руководить несколькими подразделениями. Если реальный лимит коммуникаций, особенно у менеджеров среднего звена, ниже минимального значения, то это говорит просто о реальной недогрузке менеджера как руководителя. При расчете лимита коммуникаций очень важно учитывать только реальных сотрудников, без учета вакансий и «подснежников».
Можно сказать, что в анализируемой компании до 40 % управленцев среднего звена были явно лишними. При этом у 19 руководителей лимит коммуникаций был значительно превышен. Это касалось, в первую очередь, менеджеров высшего звена. Т.е. ряд менеджеров высшего звена управления были явно физически не в состоянии эффективно руководить. При этом ситуация с управленческим недогрузом одних менеджеров и перегрузом других для компаний среднего бизнеса является достаточно типичной. Но, как правило, она находит слабое отражение в мотивационной системе и, особенно, в уровне базовой заработной платы. Также не стоит забывать, что если какой-либо менеджер не может физически осуществлять управление, то реальное управление переходит к другому управленцу. Как правило, управление перетягивают на себя неформальные лидеры с потенциально сильной коррупционной составляющей.
2. При сравнении реальной ОСУ с утвержденной было обнаружено, что ряд подразделений, которые по формальному признаку должны были подчиняться генеральному директору, фактически находились в реальном управлении у коммерческого директора. В числе этих подразделений оказались отдел продаж, отдел закупок, отдел доставки, склады, планово-экономический отдел и отдел АСУ. Т.е. все определяющие подразделения, в том числе и с антагонистическим функционалом. Таким образом, была создана ситуация, в которой коммерческий директор сам определял условия и задания по продажам и закупкам; назначал входные и выходные цены, оценивал работу ключевых подразделений.
На практике выявление подобной ситуации производится простым анализом подписантов определяющих документов, прямым многоуровневым интервьюированием, а также элементарной здравой оценкой реалий. Формат проведения подобного рода исследований может быть разным, но общим для всех форматов является отражение в том или ином виде реальных связей по управлению и их отображение на схеме утвержденной организационной структуры управления.
3. Надпроцессных образований ОСУ, в виде ценового комитета, бюджетного комитета, плановой комиссии не было. Ситуация в этом отношении достаточно типичная Характерно, что даже эксперты по анализу ОСУ зачастую тоже не рассматривают напроцессные и внепроцессные структурные образования в качестве обязательного элемента организационной структуры управления. Но вернемся к рассматриваемому случаю. Решения и оценки принимались на основании информации, в основном поступающей из отдела АСУ (тоже подчиняющегося коммерческому директору). Т.е. механизмов объективного контроля деятельности подразделений коммерческого блока просто не существовало. Мало того, сложилось твердое убеждение, что они и не нужны, так как результаты деятельности компании всех устраивали (это был 2008 г.). Совмещение продаж и закупок под управлением одного лица – ситуация достаточно частая в малом и среднем бизнесе. Но в малом бизнесе это допустимо при условии, что в качестве генерального директора работает сам собственник, а в среднем бизнесе – только при наличии таких элементов ОСУ как ценовой комитет, бюджетный комитет и, самое главное, сильный отдел маркетинга. Во всех остальных случаях всегда возникают коррупционные схемы.
4. Отдел маркетинга, по требованию отдела закупок и отдела продаж, был расформирован полгода назад за ненадобностью. Единственный источник альтернативной информации по лимитам закупочных цен и уровням продажных перестал существовать. И это тоже достаточно типичная ситуация. Типичная и драматичная для бизнеса. Недооценка роли независимой маркетинговой информации практически всегда затрудняет и снижает экономическую эффективность компании в целом. Именно компании, а не блока продаж или закупок, которым маркетинговая служба усложняет работу и повышает требования к ним. Абсолютное большинство компаний в период кризиса 2009 года сокращения начали именно со служб маркетинга. Выжившие и развившиеся в кризис, наоборот, начали его усиливать. Кстати, в рассматриваемом случае, ни образование ценового и бюджетного комитетов, ни восстановление службы маркетинга генеральному директору провести не удалось. Категорически против этого выступили финансовый и коммерческий директора, которые мотивировали свою позицию тем, что введение этих организационных образований будет являться выражением недоверия им. Собственников устраивал финансовый результат и генеральный директор, поняв, что хозяин в доме не вовсем и не всегда он, отступился от этих инициатив.
5. Еще одним характерным проявлением недостатков действующей ОСУ стала ситуация с выявлением у ряда менеджеров и ключевых специалистов двойного, тройного и более подчинений. Например, в реальности финансовый директор выполнял команды и генерального и коммерческого директоров. Чаще – второго. Начальник службы автодоставки выполнял распоряжения и генерального, и коммерческого, и финансового директоров, а также начальников отделов закупок и продаж. В условиях допущенной ситуации он, фактически, сам определял, что и когда делать, чьи и в какой степени распоряжения выполнять. В аналогичном положении оказался начальник складов, руководитель финансового отдела (группа платежей), ведущие менеджеры по продажам. Т. е. в рамках действующей ОСУ фактически сложились центры внутренней манипуляции управлением в лице перечисленных руководителей и специалистов. Особенностью подобных манипуляторов является их жесткая ориентация на лиц, обладающих в компании реальной властью и экономическими рычагами. Таким человеком для них в компании «А**ка» в 2008 г. был коммерческий директор.
Кроме приведенных недостатков ОСУ в компании «А**ка» позже было выявлено и кумовство родственников акционеров, и слабый подбор кадров, и отсутствие привязки параметров текущего планирования к стратегическому плану, и многое другое, что к структуре не имело прямого отношения. Иными словами, модель родственных, конфессиональных и неформальных устойчивых связей в рамках реализованной ОСУ не формировалась и не анализировалась. Принцип сводимости мотивационных показателей линейных подразделений к показателям и инструментам исполнения бюджета не соблюдался. Механизмов объективного контроля в реальном режиме времени со стороны не только генерального директора, но собственников создано тоже не было. Но самое главное, генеральный директор понял, что два последних года он уже не управлял компанией, а лишь имитировал управление. Истинное управление принадлежало иным руководителям, а реальное состояние ОСУ существенно отличалось от формально утвержденного. По результатам анализа ОСУ это поняли хозяева компании, но ничего в 2008 году не сделали, так как побоялись конфликта и потери прибылей. Генеральному директору под давлением группы неформальных лидеров пришлось уйти из компании. После чего восстановился естественный порядок вещей: новым генеральным директором стал бывший финансовый директор, который ничего не стал менять.
ПРОФИЛАКТИКА ПРОБЛЕМ НА РАЗ, ДВА, ТРИ…
В таком достаточно пессимистическом финале был виноват сам генеральный директор. Что можно порекомендовать управленцам, для того чтобы не допускать подобные ситуации?
Во-первых, необходим мониторинг реального состояния организационной структуры управления. Для компаний численностью от 300 человек и выше он должен проводиться не менее одного раза в год.
Второе. Типичной структурной ошибкой явилось объединение в рамках коммерческого блока отделов снабжения и продаж, и тем более складов. В любом случае, при любых реализациях ОСУ для компаний малого и среднего бизнеса склады и отдел продаж необходимо подчинять первому руководителю, так как каждое из этих подразделений является жизненно важным для работы компании в целом. Особенно отдел продаж.
Третье. При выходе компании на рынок сбыта сверх регионального уровня принципиальное значение приобретает появление в ОСУ специалиста (подразделения) по маркетингу и PR. Здесь также должно быть подчинение непосредственно генеральному директору.
Четвертое. В реализации управления определяющее значение имеют качество, своевременность и достаточность информации, отражающей как минимум результаты снабжения, производства и продаж. С этой точки зрения оптимальным является подчинение отдела IT опять-таки генеральному директору, либо иному топ-менеджеру, но которому не подчинены ни отдел продаж, ни склады, ни отдел закупок.
Пятое. В случае если уровень автоматизации информационного обеспечения низкий, то крайне эффективным структурным решением является подчинение ядра склада (собственно зоны хранения) либо генеральному директору, либо финансовому директору, либо главному бухгалтеру. При этом вся отчетность по закупкам, отпуску на комплектование и продажи и выполнение производственных планов (в случае наличия производства) ведется только по данным складов. Подобного рода структурные решения резко повышают качество и объективность управленческой информации.
Шестое. В любом случае, в качестве системных стабилизаторов должны реально работать надпроцессные образования в виде плановой комиссии, бюджетного и, особенно, ценового комитетов. В деятельности ценового комитета наиболее эффективным является определение не только параметров и условий продаж, но и соответствующих показателей закупок
Повторимся: эффективным структурным решением, объективно повышающим качество информации по закупочным ценам сырья материалов и комплектующих и ценам продаж, является специалист (подразделение) маркетинга. Учитывая, что маркетинговая информация всегда должна быть максимально объективна и носить альтернативный характер информации подразделений закупок и продаж, маркетинговое подразделение (специалист) ни в коем случае не должно быть ни в составе отделов, ни в подчинении у руководителей отделов закупок и продаж, ни у коммерческого директора. Исследования показали, что в 94 % случаев главной причиной неэффективности работы отдела маркетинга был именно вариант указанного недопустимого подчинения.
Это минимальный набор действий, которые позволили бы избежать сложившейся ситуации и, что самое главное, которые генеральный директор мог бы реализовать сам, без привлечения внешних специалистов. Но именно минимальный. Следует принимать во внимание, что ситуация и во внешней среде и внутри компании непрерывно меняется. Объективно необходимо: наличие внутреннего механизма индикации новых требований; быстрой, качественной и комплексной реакции на них самой компании в части соответствующих изменений ОСУ; системы экономической мотивации, бюджетирования и т. п. На практике в качестве таких механизмов выступают подразделения комплексного мониторинга состояния системы в виде отделов, групп, просто специалистов координации, организационного развития, системного контроллинга или им подобных.
Обобщая ситуацию с ОСУ в компании «А**ка», можно выделить ряд недостатков, которые оказали существенное влияние на организацию управления.
- Несовпадение реальной и утвержденной ОСУ. Неумение связать реальную и формальную ОСУ при реализации управления.
- Избыток менеджеров среднего звена, который приводит к дополнительным затратам (это самый «финансово емкий» недостаток ОСУ), снижению качества и скорости принятия решений. Показателями этой характеристики могут быть расчеты лимитов коммуникаций, количества уровней иерархии и т. д.
- Недопустимое смешение функционалов в рамках одного подразделения (например, маркетологи в отделе продаж) или подчинение одному лицу (отдел продаж и отдел закупок).
- Отсутствие или неполнота реализации обязательного функционала. Например, отсутствие службы маркетинга на стадии развития для торговых компаний, начиная с региональных рынков и выше, или службы HR, начиная с численности от 150 человек и др.
- Слабость контроля над возникновением и предупреждением недопустимого смешения конкурентного функционала при подчинении одному лицу.
- Невыполнение комплексных изменений в системах бюджетирования и мотивации, контроля затрат и подбора персонала при изменении таких параметров ОСУ как функционал подразделения и (или) смена подчиненности.
Продолжение истории с компанией «А**ка» было не очень оптимистичное, но поучительное. В кризисный 2009 год коммерческий директор и ряд ведущих специалистов ушли из компании и создали конкурирующую фирму. Численность этой новой компании в 2009 – 2010 гг. была 150–158 человек. За первые 4 месяца 2010 года ее оборот превысил оборот «А**ки» в 4 раза. Основной акционер и он же генеральный директор – бывший коммерческий директор «А**ки». У него работает и ценовой комитет и два очень хороших маркетолога. Смешение функционала в ОСУ его компании практически отсутствует. Из надпроцессных образований первой была введена комиссия по подведению итогов. Есть бюджетный комитет и многое другое. Он умеет быстро и правильно делать выводы и принимать решения.
На конец года в компании было запланировано первое проведение внешними аудиторами комплексной организационной диагностики, одним из элементов которой является анализ организационной структуры управления.
2500 pp 400 часов. Что со мной не так?
Импрув также вопрос концентрации. Я с августа по декабрь 0pp поднял играя без мотивации и из-за стертых глайдов на мышке. А потом еще 2 месяца привыкал к новому ковру и новым глайдам.
Скор в 121pp был после 2.5 дней плейкаунта 11 месяцев назад, сейчас 13 дней и как-то недалеко ушел, всё те же сраные фармилки.
Последний раз редактировал Baboon4 2022-04-03T09:50:50+00:00 , всего правок: 3.
Дата регистрации: декабря 2017
Автор темы
Baboon4 wrote:
Импрув также вопрос концентрации. Я с августа по декабрь 0pp поднял играя без мотивации и из-за стертых глайдов на мышке. А потом еще 2 месяца привыкал к новому ковру и новым глайдам.
Скор в 121pp был после 2.5 дней плейкаунта 11 месяцев назад, сейчас 13 дней и как-то недалеко ушел, всё те же сраные фармилки.
У меня с декабря как раз, когда появилась мотивация, все пошло по одному месту стал вместо часа в день играть по два, а то и больше. Только толку от этого никакого. Так и сижу на 5 звездах и с трудом пытаюсь хотя бы играть на 95 акурас
Дата регистрации: апреля 2020
Lelysh L wrote:
Baboon4 wrote:
Импрув также вопрос концентрации. Я с августа по декабрь 0pp поднял играя без мотивации и из-за стертых глайдов на мышке. А потом еще 2 месяца привыкал к новому ковру и новым глайдам.
Скор в 121pp был после 2.5 дней плейкаунта 11 месяцев назад, сейчас 13 дней и как-то недалеко ушел, всё те же сраные фармилки.
У меня с декабря как раз, когда появилась мотивация, все пошло по одному месту стал вместо часа в день играть по два, а то и больше. Только толку от этого никакого. Так и сижу на 5 звездах и с трудом пытаюсь хотя бы играть на 95 акурас Очевидно с тобой это не работает. Замыливается глаз, устаешь, я не знаю. Концентрироваться нужно больше, а не играть.
Алсо это наказание за грехи фарма дт. Я не так давно покаялся, открестился от тв сайзов и начал играть более праведные мапы. Curse rejected, evil purged, holiness increased, virginity protected.