Мне часто говорят – эй, где технические статьи? Чё ты всякую чушь пишешь, про менеджеров, директоров, отношения с персоналом, корпоративные дрязги, ноешь про бессмысленность нашей работы и вообще. Мы хотим технические статьи!
Я, если честно, плохо понимаю, что такое «технические статьи». Я понимаю, что такое «задача» и что такое «решение». Еще я понимаю, что решение одной и той же задачи можно найти на разных уровнях – от «железного» до философского. Какой уровень правильнее – не знаю.
Чтобы разобраться, нужна ваша помощь. У меня есть прекрасный сквозной пример решения одной задачи на разном уровне. Сразу предупреждаю – пример из сферы 1С, но вашим прекрасным мозгам там будет где примениться. Попробуем найти место для «технической статьи» в этой цепочке.
Пример является собирательным из нескольких реальных историй. В смысле, он повторялся несколько раз, с разными действующими лицами, включением/выключением разных этапов, но суть одна и та же. Погнали.
Исходная ситуация
Исходная ситуация проста: не завершается расчет себестоимости в 1С.
Для тех, кто далёк от желтого мира, поясню. Расчет себестоимости – это примерно самая ресурсоемкая операция, которая бывает в 1С. Выполняется в конце месяца, иногда ее, по старинке, называют «закрытием месяца».
В течение месяца в систему вносятся т.н. «первичные документы» — приход материалов, перемещения между складами, выпуски продукции, списание со склада в производство, корректировки, поступления затрат, распределения, комплектации и прочее.
Суть у всех документов одна и та же: что-то куда-то перетекает. Со склада на склад, со склада в производство, из производства на склад, из одного цеха в другой, из одной номенклатуры в другую. Грубо говоря, происходит изменение состояния материально-производственных запасов и затрат. Было ничто – стал материал. Был материал – стал затратой. Был затратой – стал продукцией. Был продукцией – стал опять материалом. Был продукцией – стал выручкой. Был электроэнергией – стал затратой. Был затратой – вошел в стоимость продукции. Просто изменение состояния сущности, если абстрактно рассуждать.
Всё это дело в течение месяца записывается в одну большую таблицу, которую потом расчет себестоимости обрабатывает. У него две ключевых задачи – распределить затраты и скорректировать себестоимость. Распределить затраты – это типа включить в стоимость выпуска всё, что на этот выпуск было потрачено, вроде материалов, электроэнергии, зарплаты и т.д. (до расчета себестоимости это были разные записи таблицы, выпуск отдельно, затраты — отдельно). Ну а скорректировать себестоимость – это решить СЛАУ, чтобы привести стоимости к нужной стратегии списания (по средней или ФИФО).
Так вот, представим, что вся эта хрень не работает. Запускаем, ждем сутки, потом падает. Известно, что расчет идет на сервере под управлением Windows Server 2012, в одном процессе rphost.exe, СУБД – MS SQL.
Уровень окружения
Первый уровень – чисто пацанский. Ничего не хотим знать ни про какую 1С, смотрим только на окружение. Какая нам, в общем-то, разница, что там делает эта несчастная 1С? Мы и так знаем, что всё она делает неправильно, но мы как-нибудь обойдемся без сопливых.
Поле для экспериментов – огромное. Как и материал для настоящих, без кавычек, технических статей.
Начнем с выбора серверного оборудования. Ведь его наверняка подбирали 1Сники, которые в этом не петрят. Напишем про влияние объема ОЗУ на выполнение тяжелых 1Сных операций, исследуем жесткие диски разного физического исполнения, посмотрим, что важнее – количество процессоров или ядер. В реальной практике – еще и сервер новый закажем. Особенно с учетом откатов, которые платят поставщики серверов.
Дальше посмотрим на ОС. Не годится ведь приличные серверы держать под виндой? Тем более, что 1С уже давно умеет работать под линуксом. Да и, в конце-то концов, в 1С поддержана кластеризация, и мы, формально, можем поставить два и более сервера, даже под разными операционными системами. Вот матерьялец-то будет для статьи.
Ну и, конечно, не обойдем СУБД. Какого черта все уперлись в эту MS SQL? Как минимум, посмотрим на Postgre, которую 1С поддерживает уже лет 100. Даже под виндой. Мало того, что попробуем другую СУБД, так еще и поднастроим ее так, чтобы шум стоял. Правда, на эту тему уже написана куча статей, в т.ч. самой фирмой 1С, но мы обязательно найдем, что сказать в своей технической статье. В конце концов, интересно читать опыт людей, а не мануалы.
А задачу решим? Не исключено. Практика показывает, что на этом уровне решается довольно много задач – особенно, при первом появлении проблем с расчетом себестоимости, т.е. на тех порах, когда все настройки и ОС, и СУБД стояли по дефолту.
Но у нас история немного другая. Все возможности уже исчерпаны, лучшие умы города ковырялись в сервере – причем, купленном три месяца назад. Тогда, сразу после запуска, сервер порвал расчет себестоимости всего за 16 часов. А сейчас, увы, почему-то и за сутки не справляется.
Придется подниматься на уровень выше.
Уровень доработки 1С
Ладно, бросаем железо, лезем программировать. Несложный замер производительности показывает, что 1С зависает и падает при выполнении операции распределения затрат.
Там, на самом деле, всё просто. Есть таблица, в которой к моменту расчета 8 млн. записей. Грубо говоря, половина из них – затраты, вторая половина – база распределения. Т.е. надо взять первую половину, и бахнуть на вторую.
Сидим и думаем – где тут падать-то, родимая? Банальный перебор, хоть и сопровождающийся постоянными запросами к БД с хранением промежуточных результатов во временных таблицах. Ну, может, еще и в том проблема, что результат записать не удается, т.е. добавить к 8 млн. записей еще столько же.
Ничего сложного, но падает. Чего-то не хватает процессу rphost.exe. Так, стоп… А почему такую простую, и в общем-то, не особо зависимую от контекста операцию выполняет всего один процесс? Кто мешает поделить таблицу пополам, или даже на три части, и выполнять параллельно? Ведь 1С вполне себе умеет хоть 20 процессов запустить, но почему-то этого не делает. Так, а почему не делает? Или делает?
Ага, обнаруживаем, что наша версия 1С немного устарела, а в более современных распараллеливание вынесено прям в настройки – человек заранее может сказать, сколько параллельных потоков вот этих самых «вычислений» может выполняться. Непорядок!
Дописываем несложный код, который пилит таблицу на нужное количество частей и выполняет их параллельно. Напомню, что распределение одних затрат ну никак не зависит от распределения других, в рамках одной итерации.
Йоу! Заработало! Просрался расчет себестоимости! Иногда, правда, возникают блокировки для записи – пофиг, приделываем заплату в виде кеша записей с управляемой блокировкой для последующего помещения в основную таблицу. Красота! Работает!
У, сколько тут статей можно написать! Технических! Правда, с немного желтым окрасом. Хотя, с другой-то стороны, где наша не пропадала? Что, в вашей среде разработки и на ваших проектах не приходилось делить запись миллионов строк на куски, чтобы СУБД не сдохла?
Всё, победа вроде. Но что-то гложет… Себестоимость-то посчиталась, но всё равно – слишком долго. Те же сутки, просто падать перестала – объем записей никуда не делся, просто мы пишем их кусками, псевдопараллельно.
Ползем выше.
Уровень технической настройки 1С
Анализируя алгоритм, понимаем, что проблема не только в количестве записей, но и в многократной их обработке. Теоретически мы ведь понимаем, что для распределения 4 млн. записей на другие 4 млн. достаточно выполнить запрос, в котором сопоставить строки по нужным аналитикам, и потом записать результат.
А тут глядим – э, черт, а там цикл… Цикл, который выполняется по таблице из 4 млн. строк. А в нем еще один цикл, с безусловным прерыванием по какому-то странному условию. И выполняется тело вложенного цикла намного больше, чем 4 млн. раз. Блин…
Ковыряемся, и обнаруживаем третью таблицу, в которой хранятся настройки распределения. Грубо говоря, там и лежит сопоставление первых 4 млн. записей со вторыми. Но организовано там всё не однозначно, а с постепенным сужением фильтра. Сначала написано типа «все затраты с видом Общепроизводственные фигачим тупо на выпуск», потом «А вот эту статью – тоже на выпуск», потом «а вот эту статью пот по этому подразделению – тоже на выпуск», потом уточняется до номенклатурной группы, счета учета и т.д.
Самое-то поганое – алгоритм не определяет настройку распределения за один проход, а делает это циклически, постепенно приближаясь к цели. При том, что результат-то, в итоге, одинаковый. А, не, не это самое поганое – в этой таблице 10 тысяч записей. Явно вбитых руками.
Вспоминаем, как работают с этими настройками бухгалтеры. Программисты вбили в таблицу 4 строки, с самым широким фильтром. А у бухгалтеров что-то «не закрылось» — они зашли, и уточнили фильтр для конкретной статьи и конкретного подразделения. И так они сделали 10 тысяч раз, в течение многих лет.
В итоге, наши 4 млн. записей бегают по другим 4 млн. записей несколько раз. Что ж, накатываем для храбрости и идем в бухгалтерию. Не к главбуху – она наверняка не в курсе про эту настройку. Начнем с замглавбуха.
Приходим, объясняем смысл этой настроечной таблицы, и рассказываем (снова) как ей пользоваться. Убеждаем, что всё будет хорошо. Ставим тестовую базу, проводим эксперимент, предварительно прибив 10 тысяч записей, и вуаля – расчет себестоимости занял всего 8 часов!
Э-ге-гей! Какую классную статью теперь можно написать! Только будет ли она технической? Ну не знаю… Для определенных, желтых сообществ, наверное – да. Ладно, пусть она будет технико-методической. Заодно добавим пару абзацев про то, какие тупые бухгалтера.
И тут приходит мысль – раз уж сумел прорваться в бухгалтерию, может еще чего ковырнуть? Например, понять, почему записей в таблице – 8 млн. А главное – почему их с каждым месяцем становится всё больше.
Пробуем подняться уровнем выше.
Уровень ведения учета
Нам, программистам, понятно, что количество строк в таблице определяется шириной используемой аналитики, а не объемом выпуска. Тем более, что мы знаем – объемы выпуска родного предприятия, как и линейка его продукции, растет значительно медленнее, чем размер нашей таблицы.
Например, если бы единственной нашей аналитикой выпуска было подразделение, то количество строк в таблице было бы не больше, чем 2 * количество различных подразделений (половина под выпуск, половина под затраты). Этих подразделений у нас, дай Бог, сотня.
Если добавить, например, аналитику «Статья затрат», то количество записей будет равно (Количество подразделений) * (Количество статей) + (Количество подразделений), потому что вторая половина таблицы (выпуск) не содержит аналитики статьи (как правило, если нет передачи полуфабриката из подразделения в подразделение без использования склада). Самое поганое в этом уравнении — *, т.е. умножение. 100 подразделений да 100 статей – уже 10 тыс. записей.
Потом умножаем на количество номенклатур, характеристик, заказов на производство, номенклатурных групп, черт меня дери… Так и набирается 8 млн.
Или не набирается? Пересчитываем на калькуляторе – не, ни фига. Точнее, даже без калькулятора понятно, что количество записей не должно так быстро расти, из месяца в месяц.
Разворачиваем отчет по остаткам в разрезе всех используемых аналитик, и – ба! – оно ж, собака, тупо не закрывается! Поясню, что значит «закрывается» — это когда пришел остаток по набору аналитик, и в конце месяца весь ушел. А не закрывается – когда не ушел. Так образуется незавершенное производство, сиречь НЗП.
А не закрывается ровно по одной аналитике – заказ на производство. Для каждой партии продукции заводится некий документ, который эту партию типа отделяет от остальных. На него отправляются затраты (первая половина таблицы), по нему отражается выпуск (вторая половина таблицы), и всё должно закрываться. А оно не закрывается.
Зам. главбуха, которая сидит рядом, тоже в шоке. Знать не знала, что не закрывается – это ж ахтунг! Ковыряемся, выясняем – они, бухгалтеры, просто смотрят отчеты без учета заказов. Без этой аналитики всё закрывается, а с ней – нет.
И вот эти хвостики – незакрытые суммы по заказам на производство – тоже входят в состав 8 млн. строк, это входящие остатки затрат на начало месяца, которые надо закрыть в текущем (в принципе, такое бывает, если производство длится несколько месяцев, но это не наш случай). Проблема в том, что у нас они не могут закрыться, потому что выпуска по заказам прошлого месяца уже не будет, и затраты по ним вынуждены влачить жалкое существование еще хреналлион лет, постоянно увеличивая количество записей в таблице распределения.
Бежим в нашу тестовую базу, убираем все хвосты, и – едрить твою за ногу! – записей при расчете становится 1 млн.! Расчет уже укладывается в 2 часа!
А у нас уже задор исследователя – ведь такой материал для технической статьи наклевывается! Хвосты-то мы убрали, а в текущем месяце аналитика заказа до сих пор присутствует. Ладно, чё, база тестовая – режем заказы вообще, и таблица сворачивается до 400 тыс. записей.
Расчет идет 1 час. 1 час, Карл! Мы сократили время расчета в 24 раза! Ну теперь-то такенную статью напишем, почти техническую, что закачаешься!
Правда, осталось объяснить главбуху, что аналитика заказа – лишняя. Накатываем еще и ползем на второй этаж.
Уровень стратегии учета
Тешим себя надеждой, что всё пройдет на «ура». В конце концов, мы ведь проблему расчета себестоимости решили – да еще как! Предполагаем, что главбух не в курсе вообще про настройки детальности расчета, и аналитику заказа просто кто-то когда-то включил, типа пусть будет.
Ан нет. Как только главбух услышала «отключить аналитику заказа», прям вся взбеленилась. Начала гнать про офигенную необходимость для предприятия иметь полную картину себестоимости, и, главное, сравнивать цифры именно в разрезе заказов, в рамках одного контрагента, да и помесячно.
Набираем полную грудь воздуха, и задаем главный вопрос: это, Мариванна, а вы хоть раз в жизни делали такой анализ? По своей воле, или по заказу других подразделений?
Ну, несколько минут выслушиваем разнообразные прилагательные и существительные, преимущественно образованные от всего лишь четырех слов великого и могучего. Мысленно вспоминаем адреса сайтов с вакансиями. Но решаем идти до конца.
Не даем главбуху закончить, говорим – это всё прекрасно, но я хочу найти источник этого требования. Главбух психует и отправляет к финансовому директору, который и ее начальник, и экономистов.
Те ребята попроще, и содержащегося в крови алкоголя уже достаточно, чтобы с ними пообщаться. Пока идем, думаем – а что про это приключение можно написать? Технического – ничего, явно. Хотя проблема видна невооруженным взглядом. Ну т.е. понятно, что на всех уровнях ниже мы решали несуществующую проблему.
Уровень корпоративных игр
А финдир наш друг. Мы много помогали этой веселой тёте с автоматизацией. Поэтому спрашиваем в лоб – нафига бухгалтерия ведет учет с такой широкой аналитикой? Да еще так хреново.
Тётя сразу цепляется за слово «хреново» — чего хреново, где хреново, действительно ли хреново? Ну да, говорим, хреново, по-настоящему хреново. Из-за нее ИТ-отдел не спит кучу ночей, строчит кучу технических статей и вообще, выгорает.
Тётя берет быка за рога и просит изложить всё в письменном виде – что не так, почему и как я до этого дошел. Ладно, обещаем изложить. Но, опять же, идем до конца. Чего, говорим, главбух такой фигней занимается, причем, прикрываясь финдиром, т.е. тобой, тётя?
Получаем ответ в лоб – а пусть помучается, гадина. Нефиг было умничать на совещаниях. Говорить, что нет ничего важнее бухучета. Утверждать, что неправильно подчинять главбуха финдиру. Нести чушь насчет того, что главбух – второй человек на предприятии, после директора.
А чего, говорим, просто не уволить ее? А нельзя, говорит тётя. Это ж будет выглядеть, как устранение неугодных – типа, вякнула тетка, и тут же вылетела с работы. Звоночек неприятный будет для директора. Начнет копаться, как тут кто ведет учет.
А сейчас – картина маслом. Главбух не справляется с учетом. Положила базу на бок. Так если бы с пользой для дела – нормальный учет себестоимости по заказам так и не организовала.
Между делом спрашиваем – а вам, тётя, нафига этот учет по заказам, да еще в бухучете? В лоб отвечает – он мне вообще никуда не впился. Не пользуются ни экономисты, ни финансисты цифрами бухучета. Только первичными документами.
Э, говорим, как так? А откуда себестоимость берете? Вы ж без нее прибыль не посчитаете.
Сами, говорит, себестоимость считаем. Наполовину кассовым методом, материальные затраты собираем по ценам закупа, а распределяем в экселе, котловым методом, с использованием норм расхода материалов, с корректировкой до факта только по суммам.
Потому что, дорогой мой, наша задача в части себестоимости – выдать директору листок формата А4 под названием «Отчет о прибылях и убытках», где все затраты поделены на десять групп, плохо коррелирующих со статьями затрат бух.учета.
Грубо говоря, всё, что делает бухгалтерия, не нужно никому, кроме бухгалтерии. А бухгалтерии учет затрат нужен в очень короткой аналитике – ровной той, что присутствует на счетах бух.учета. А там, дай Бог, если три аналитики наберется.
Выходим из кабинета финдира в смешанных чувствах. С одной стороны, вроде, во всём разобрались – задачу-то вообще решать не надо, и проблема расчета себестоимости исчезнет навсегда. С другой – оказались втянуты в корпоративные игры.
Сейчас ведь как. Напишешь бумажку про главбуха – станешь для них врагом навсегда. Не напишешь – и дружбу с финдиром потеряешь, и с глабухом не наладишь. Она же не поверит, если рассказать историю типа «меня просили на тебя накапать, а я отказался».
И написать техническую статью не про что. Вообще. Хотя, уже понимаешь, что все проблемы на нижних уровнях решать не то, что бесполезно – вредно. Ведь все усилия и деньги (помните про недавно купленный новый сервер?) пошли не на пользу компании, а на пользу одной тёти, которая дружит против другой.
Настроение поганое, и тут на глаза попадается директор. Точнее, мы ему на глаза попадаемся. Парень прошаренный, видит дурной настрой, и сразу зовет к себе в кабинет.
Поднимаемся на уровень выше.
Уровень птичьего полета
Решаем всё-всё рассказать. Снизу доверху, без прикрас. Про всех. Терять-то нечего.
И про сервер за 1 млн. рублей, который теперь не нужен. И про раздутый штат бухгалтеров, который нужен для ведения столь сложного учета, который, как оказалось, никому уже не нужен. И про раздутый штат программистов, который нужен лишь для сопровождения дебильного бухучета. И про тётю-финдира, которая играет в свои игры за счет компании.
Директор внимательно слушает, иногда задавая вопросы как технического, так и методического характера. Прям живенько так вникает, на ходу понимает, будто программистом когда-то работал.
А сам всё цифры какие-то на бумажке пишет.
Мы всю душу программистскую изливаем. Про то, что рождены мы для решения технических проблем, а не для участия в корпоративных играх. Про то, что технический уровень решения должен быть самым последним, когда исчерпаны все иные способы – организационные, методические, стратегические и какие там еще есть. Про творческую натуру, абстрактное мышление, интровертов и прочие программистские байки.
А по дороге думаем, какая классная статья бы получилась. Только не техническая. И куда же ее разместить-то? Тоже проблема. Притвориться в статье, что всё решилось на техническом уровне, и им же ограничилось? Но ведь неправда. А скажешь, что дошел до директора – не поверят. Место программиста на заводе – возле параши, уж простите.
Директор вежливо выслушивает до конца, потом подводит черту под своими цифрами, и выдает: дружище, ты вскрыл проблему, которая обходится мне в 1 млн. рублей в месяц. Спасибо тебе большое. Прям вот так, без восклицательного знака.
Теперь, говорит, будет так. Запускаем проект приведения учета в порядок. Руководителем будешь ты. ИТ-директора я увольняю, на его место встаешь ты. Службе безопасности поручу проверить, получал ли он откаты за покупку оборудования.
От тебя жду четкого плана по учету, и бухгалтерскому, и управленческому. Чтобы всё красиво и взаимосвязанно, но – только в нужной аналитике. Ты будешь этот план внедрять. Любые изменения в учете теперь будут реализовываться только после твоего одобрения.
В плане учета должен быть расчет необходимого количества специалистов. Лишних – уволим, без размазывания соплей. Сразу думай, как можно автоматизировать деятельность оставшихся – возможно, и их многовато, если с умом подойти.
Только не зазнавайся, чувак. Ты теперь работаешь на меня. Будешь моими глазами и моим техническим мозгом. Никаких игр – ни со мной, ни с кем другим.
Выходим, на шатающихся ногах, и ползем в свой подвал. Голова кружится – то ли от счастья, то ли от страха. Хочется сбежать, как из странного сна, просто чтобы вернуться в привычную реальность. Неужели так бывает?
Не, не бывает. Не поверят. И статью про это не напишешь. Заплюют, заклюют и отправят в Cosmopolitan статьи писать про ИТ-золушек. И сам бы не поверил. Точнее, сказал бы, что не верю, лишь бы не признаваться, что боюсь вылезать из своей дыры и спрашивать «а нахера я эту чушь должен делать?». Хоть и на блестящем техническом уровне.
Собственно, вопрос
Где тут технический уровень? Про что интересно и полезно писать и читать технические статьи? Вот прям на этом примере.