- BrainTools - https://www.braintools.ru -
Детективная история с дураками и умниками, жадинами и инвесторами, миллионом долларов, который дали, но не нам, и моралью, свежей и оригинальной, как говорил самый известный советский программист товарищ Привалов.:)
Все совпадения случайны, имён я не назову, а если Вам кажется, что вы знаете имена из этой истории — Вам кажется.:)
(Это третья статья из серии про подводные камни при заказной разработке ПО, предыдущие здесь [1] и здесь [2].)
Эта история случилась более десяти лет тому назад, так что, наверное, её можно уже рассказать.
С тех пор сменилось всё или почти всё. Думаю, никто из упомянутых людей уже не работает в том же месте, да и самих компаний, скорее всего, нет.
Всё началось в один из непростых годов нашей истории (а какой год у нас был простой — ковидный, разве что:) — в дверь Digital Zone постучался потенциальный клиент.
В дверь тогда ещё просто молодой компании — юный софтверный бизнес под управлением Димы Завалишина, который формально директор, а реально и архитектор, и продавец, и на дуде…
Задача была сложная, но интересная — сделать полную и бескомпромиссную систему управления таксопарком. Новым, который вот только создаётся. Большим и очень современным таксопарком. Систему с картографией, с планированием маршрутов, с бесконечными возможностями формирования вот вообще произвольных тарифных планов, с ассет менеджментом, шахматами, поэтессами и прочим. Сейчас всё это почти обыденность, а тогда проект был на грани технологических возможностей.
А ещё клиент хотел чуда — чтобы ему сделали систему, которая будет бесконечно гибкая и может настраиваться во всём и везде. Ну — чтобы получить её у нас один раз, и больше НИКОГДА, вообще никогда ничего не дорабатывать.
Надо сказать, что я его отговаривал: бесконечной гибкость всё равно не будет, а делать столь универсальную систему дорого. Дешевле будет разработать то, что сейчас точно нужно, и планировать развитие. Но клиент настаивал, а клиент, как известно, всегда прав. Особенно если готов оплачивать свои мечты.
Второй сложностью (второй понятной на старте проекта сложностью!:) было требование обеспечить работу таксометра (мобильного приложения, в нынешних терминах) прямо в машине независимо от сервера: при потере связи всё должно было работать безотказно. А, надо сказать, мобильное покрытие тогда даже в Москве было изрядно дырявое, и были места, где голосом мобильник ловил, а интернета не было. Ну, как Интернета — GPRS. Не разгуляешься.
При этом если связь есть — вся работа таксометра должна верифицироваться на сервере в реальном времени. Потому что таксист наверняка попробует подхачить таксометр, чтобы завышать счётчик и обманывать компанию.
На всё про всё у клиента было N миллионов рублей, где N — цифра, а не число. Мы бы, конечно, не осилили этот огромный проект в таком тесном бюджете, если бы не две вещи. Имевшиеся от других проектов наработки и умение придумывать изящную архитектуру.
В итоге система сконфигурировалась примерно так: на машине стоял подключенный к бортовым датчикам компьютер на базе Windows Moblie (помните такое?), который был синхронизирован с сервером, пока есть связь. Тарификация была сделана вот как: автомобиль от начала поездки писал шлейф перемещений и событий, состоящий из сегментов движения и других важных факторов — ожидания, смены тарифа и тому подобное
Шлейф по мере наличия связи отсылался сегмент за сегментом на сервер. Сегменты были компактные, генерировались относительно редко, и это позволяло пропихивать их в неторопливый GPRS без особенных проблем.
И на сервере (enterprise java), и на клиенте (windows) мы запускали идентичный groovy скрипт, в котором и был реализован алгоритм тарификации. Имея идентичные параметры и шлейф скрипт генерировал на клиенте и на сервере идентичную стоимость поездки на каждый шаг пути. Стоимость регулярно отсылалась на сервер и сравнивалась с посчитанным там значением, что гарантировало решение обеих задач: всё будет работать без связи, но как только связь появится — всё будет проверено до мелочей.
Не нам решать, был заказчик параноиком или нет — времена были бедные, а лихих людей среди таксистов всегда хватало.
Сам сервер тоже был устроен непросто — отдельный блок на выделенной машине отвечал за картографию: кеширование карт, маршруты, сравнение планового и реального маршрутов, оценка поведения [3] водителя (превышения скорости и ускорения), в общем, всё, что касается географии. Отдельный сервер держал входящие и активные заказы, занимался их назначением и ведением статуса — диспетчерская деятельность.
Ещё одна подсистема отвечала за таблично‑карточные дела. Реестры машин и водителей, прохождения тех‑ и медосмотров, параметры тарифов, договоры с партнёрами (и партнёрские тарифы), и проч. При этом для гибкости почти вся бизнес‑логика была вынесена в groovy скрипты.
Плюс оркестрация, плюс интеграции, плюс отчёты, плюс UI, плюс балансировщик нагрузки — это был совсем не игрушечный проект. И, в принципе, мы взялись его делать за очень разумные деньги. Которые таксопарк брал у своего инвестора. Траншами.
Проект мы тоже старались сдавать этапами, по мере готовности части функций, но клиент с этим не соглашался — мол, зачем мне часть системы: хочу только всё и целиком. В итоге на промежуточных сдачах акты нам подписывать отказывались. Фиксировали, что требования реализованы верно, и всё. Мы страдали, но разработка шла — надо сказать, проектом мы горели. Действительно, для своего времени он был хорош, да и инженерные задачи подогревали наш и без того кипящий разум. Фильтрация данных GPS с подавлением всплесков ошибок, аккуратная работа с передачей данных по GPRS, распределение нагрузки на сервера — скучно не было.
Ну и совсем уж весело стало, когда менеджер клиента сообщил нам, что они потеряли инвестора и денег больше нет. В этот момент система в целом была готова — мы начали уже поездки на машинах с целью тестирования алгоритмов работы с маршрутом. Практически все функции, которые можно было протестировать без выезда в город уже были проверены и работоспособны. Ну, то есть, месяц багфикса — и поехали в прод.
Облом был жутким. И по деньгам — мы оказались в жёстких убытках, и эмоционально — ну и зачем мы так убивались? При этом весь написанный код заказчику передавался, но, как я уже говорил, не под акты — прав на код у него не было. Заказчик пару раз подкатил на кривой козе — мол, а давайте оформим передачу системы нам бесплатно. Мы пару раз ответили одним словом — «зачем?», и он ушёл грустный.
Мы тоже грустили. С таксопарком происходили какие‑то посмертные пертурбации, и какое‑то время мы надеялись, что бизнес оживёт и система будет у нас выкуплена. Через полгода стало понятно, что надежды тщетны. И тогда я принял решение выставить систему на продажу. Если честно, без особой надежды — велики ли шансы, что прямо в этот момент кто‑то запустит таксопарк и ему будет нужна ERP система, и именно такая… ну — чудо, не меньше.
Шли месяцы, чуда не случалось, я мысленно похоронил надежду. И вдруг…
Все детективы начинаются с «и вдруг». Но обычно в детективах вдруг убивают или воруют, а у нас вдруг на никому не нужную систему явились три (!) покупателя сразу. Чтобы вы не радовались за нас раньше времени сразу скажу — из них систему в итоге никто не купил.:)
Это уж постфактум я понял, что все трое были перепродавцами, и реальный покупатель был один, и нам он не был виден. До какого‑то момента. Но трое прокси‑клиентов различались кардинально.
Первый был крупным известным бизнесом из близкой области. Этот сразу сказал, что берёт систему на перепродажу, но обставил разговор так, что никакого конкретного клиента у них нет. Мол, тема для их бизнеса понятная, существующим клиентам продукт может зайти. Выставят на рынок и будут ловить рыбу. Разговор был спокойный, продуманный, и в итоге просто ничем не кончился.
Второй делал сложное лицо и ничего не объяснял, но точно не был конечным клиентом — уж мы‑то к тому времени хорошо понимали, что именно обычно болит у реального таксопарка и как он ведёт себя на переговорах. В общем, таксопарк от прокладки отличить смогли.
Третий был молодой нахал, который пришёл и выложил нам весь расклад, описанный мной выше — откуда‑то он вполне детально узнал, для кого мы делали систему, что с ней и с клиентом произошло и где конкретно мы с этой системой оказались. В сложной ситуации мы оказались. Он знал, что копия исходников есть у первичного заказчика. И запросил цену за то, чтобы официально купить у нас систему и перепродать её с доработками.
Я не стал пытаться закрыть за его счёт все свои убытки — попросил смешные даже в то время 3 миллиона рублей за систему as is плюс план на закупку у нас нескольких человеко‑месяцев на багфикс и доработки. Мотивируя это тем, что нашими силами сделать эти работы будет эффективнее и быстрее, чем вводить в неё новых людей. Всё же, мы свою систему хорошо знаем.
Юноша рассмеялся мне в лицо. Извините за затасканную фразу, но у нас же тут детектив, верно?:)
«Вы всё равно с ней встряли», сказал юноша, — «и деваться вам некуда. Так и быть, даю целый миллион рублей, а вы мне гарантируете, что в системе нет ошибок, а если найду — устраняете за свой счёт».
Я сдержал эмоции [4], и ответил, что так не выйдет. Стоимость системы в разы выше, финальное тестирование мы не закончили, а значит ошибки [5] точно есть. Если брать оценку трудозатрат на багфикс в 20% от суммарной стоимости системы, то это ощутимо больше миллиона. Зачем мне продавать и так убыточную систему генерируя себе новый убыток? Предложенная мною цена более чем комфортна, я готов договариваться об оплате частями и тому подобное
«Так оставайся же ты ни с чем», сказал мне юноша — «я куплю исходники у твоего бывшего заказчика».
Вы спросите, куда я его послал. Я сдержался. Сам удивляюсь.:) Сказал лишь, что, видимо, в следующий раз мы встретимся в суде.
На этом «тот прошлый я» поставил окончательную точку в этой истории, но проницательный читатель догадывается, что это не конец. И верно.:)
Через небольшое время мы получили запрос от четвёртого потенциального покупателя на демонстрацию системы. На этот раз запрос пришёл — да, да, именно от того, кому нашу систему планировали впарить все три прокси‑перепродавца. Мы снова воодушевились, потому что по всем разговорам было видно, что проект живой, настоящий, с крепким финансированием и компетентным менеджментом. Во всяком случае, по разговорам было видно, что люди знают своё дело и оно у них спорится.
Мы несколько раз приезжали в офис таксопарка, поговорили с ключевыми специалистами, показали систему в работе, описали варианты доработок и модификаций, сделали оценки — в общем, пошла, наконец, нормальная предпродажная работа и очень предметный разговор. Впрочем, в итоге всё опять кончилось ничем. «Ваша система не вполне готова, а нам надо сесть и поехать», сказал заказчик. «Мы купим совсем готовую».
«Но наша практически работает, а любую покупную в какой‑то степени вы всё равно будете дорабатывать! И доработка простой не будет!» — удивились мы. Но, тем не менее, получили отказ.
И снова, в третий раз я похоронил будущее нашей системы управления для таксопарков, и опять зря — твоя проницательность тебя не подводит, о терпеливый мой читатель.:)
Прошло ещё полгода. Суммарно от старта этой истории, пожалуй, прошло года два.
И вот, одним спокойным днём я получил звонок с незнакомого номера. В трубке прозвучал крайне корректный, спокойный и какой‑то очень вменяемый с первых звуков голос.
— Дмитрий Константинович?
— Да, чем обязан?
— Это же вашу систему расматривал для покупки таксопарк ХХХ?
— Верно, но они отказались.
— Мы отказались. Но мы готовы обсудить этот вопрос ещё раз. Вы можете подъехать?
— Да. Офис там же?
— Там же, но рядом есть замечательный ресторанчик. Давайте в нём.
В ресторанчике я встретился с дорого, но неброско одетым джентльменом, который с первого взгляда произвёл впечатление [6] человека крайне профессионального, вдумчивого, не склонного к спонтанным решениям, да и просто умного.
И вот человек этот просит меня рассказать всё в мельчайших подробностях про нашу систему. И я — не торопясь и ничего не скрывая — рассказываю примерно всё, что вы к этому моменту прочли. Только с именами, фактами, цифрами и иными важными деталями.
— Хорошо. Можем ли мы доработать систему с учётом вот этих требований? (Распечатанное ТЗ лежит на столе, читаю.)
— Да, надо около трёх месяцев и столько‑то денег.
— А за месяц запуститься реально?
— Очень тяжело, но если урезать до этого места, то справимся.
— Хорошо. Сделайте нам оффер. И пригласите нас в офис.
— Конечно, хоть сейчас, поехали.
— Нет, не в Московский. У вас же разработка в Казани? Вот туда.
— Откуда вы знаете?
— Знаю. Когда вы можете принять нас в Казани?
— В принципе, хоть завтра.
— Хорошо, завтра. У вас будет мой человек. Не я.
Слегка ошалевший я ставлю сотрудникам задачу проработать ТЗ, написать план проекта и оффер, а сам тем же вечером лечу в Казань, где, действительно, всё и разрабатывалось. Следующим днём мы с директором Казанского офиса встречаем в аэропорту ещё одного джентльмена. Привозим его в офис, знакомим с авторами частей системы, начинаем рассказывать, как она сделана, но он прерывает нас — «покажите код».
Окей, офигеваем мы, пойдём. В следующую минуту мужик этот ныряет в код и по локоть в крови начинает в нём копаться, задавая совсем не детские вопросы стоящим вокруг архитекторам и разработчикам системы.
Проходит часа два.
Мужик возвращается в переговорку вымотанный, но в прекрасном настроении. Как после хорошего крепкого секса, знаете?:)
За ним идут разработчики с круглыми глазами. Но тоже довольные.:)
— «У меня два результата. Первый: систему сделали вы, я это подтверждаю. Второе — в ней есть три архитектурные проблемы.»
После чего называет три действительно не очень приятных места в системе, которые при очень большой нагрузке могут проседать. Первые два мы с ходу понимаем, как закрыть, а третье сложнее. Впрочем, как мы все решили, тысяч до двадцати автомобилей проблем не будет, а до такого числа ещё дожить надо, и пока не светит. Так что непосредственных угроз нет.
Возвращаюсь в Москву, снова встречаюсь с корректным джентльменом. Он уже получил отчёт своего специалиста, который летал к нам в Казань, он уже получил наш план и оффер, его всё устраивает, и давайте бегом заключать контракт и начинать работу. Месяц пошёл!
Лирическое отступление: более быстрой и профессиональной работы заказчика по выбору поставщика и контрактации я не видел ни до, ни после.
Дальше начинется бешеный галоп — сейлы оформляют контрактные документы, архитекторы уже планируют работу программеров, разворачиваются тестовые сервера, идёт обмен контактами с клиентом — в общем, спешная, но обычная работа по запуску проекта. Все воодушевлены, потому что трижды похороненный проект восстал из могилы. Правда, прибыльным его всё равно сделать нельзя, но есть шанс значительно сократить убыток.
«Тем временем в замке шефа» — так, кажется, в детективе должна называться очередная глава.
«Кстати, » — говорит мне на очередной встрече тот самый джентльмен, — «тут же до вас этот проект делали другие подрядчики, и они не справились. давайте я передам вам их наработки.»
Я возражаю, мол — чужие наработки нам не помогут, там больше времени уйдёт только разбираться, но джентльмен настаивает. Он получит что сможет с облажавшегося исполнителя и передаст нам. Ну — окей, я, конечно, соглашаюсь — «никто не спорит с природой».
Проходит около недели. Звонок от джентльмена:
— Дмитрий Константинович.
— Да?
— Я вчера отправил вам наработки от предыдущего исполнителя. Скажите пожалуйста, Вы их ПОСМОТРЕЛИ?
Нажим на слове «посмотрели» был очень явным. Если бы по этой истории снимали кино, в этот момент едущий за рулём я должен был бы с визгом резины развернуться через две сплошных и под бибиканье окружающих машин рвануть смотреть код. Я опять проявил выдержку, и доехал до разворота. Через полчаса я распаковывал архив с явскими исходниками.
По экрану летели имена пакетов, которые начинались с ru.dz [7].имя_того_самого_проекта_из_начала_этой_истории:)
Вот только в этот момент я понял всё, и, наконец, вся эта картина собралась у меня воедино!
Если вы думаете, что это финал, то — опять нет!:)
Проговорю очевидное — наглый молодой человек действительно оказался тем самым предыдущим исполнителем. Он действительно купил наши исходники на стороне за копейки и заявил, что сам их разработал. Злые языки говорят, что получил от заказчика на доработку сумму сопоставимую с миллионом долларов.
И имея ПОЛНОСТЬЮ РАБОТАЮЩУЮ СИСТЕМУ И МИЛЛИОН БАКСОВ за полгода не смог не то, что исполнить контракт, а даже выйти на тестирование.
Дальше было скучно. Наглый юноша заявил, что это он — автор системы и что он подаст на всех в суд. С нами подробно и тщательно поработал юрист заказчика, мы показали, что доказать авторство можем, что права на код у нас есть и, в итоге контрагенты наши юношу послали лесом. Контракт был завершён и система сдана в работу.
Любопытно было, впрочем, посмотреть на результат мытарств предыдущего исполнителя. Отмечу — мы пишем качественно. Да, если честно, я вообще не видел в мире Java некачественного кода — правила платформы и наработанный в сообществе опыт [8] заставляют всё достаточно тщательно проектировать и комментировать. Покорёженные исходники я передал авторам с просьбой просмотреть и дать фидбек. Если мне не изменяет память [9], то примерно четверть украденного у нас кода системы предыдущим подрядчиком перерабатывалась, причём часть потому что и правда было надо, а часть — потому что люди в системе не разобрались и решили кое‑что просто переписать с нуля.
Старая фраза «жадность фраера сгубила» тут, конечно, блещет во всей красе. Наглый парень мог отдать нам половину того, что получил от заказчика, ВООБЩЕ ничего не делать, и заработать $0.5 млн просто сидя на печке. Мог заплатить то, что я запросил, получить от нас доработки и передачу знаний своим разработчикам — в этом варианте работать бы им уже пришлось, но проект был бы сдан и компетенции переданы. Но нет, товарищ решил пожадничать.
И, как обещал, мораль, свежая и оригинальная: в сложном проекта потеря ключевых людей смерти подобна.
Ой, нет, не то. Жадничать и наглеть — плохо.
Автор: dzavalishin
Источник [10]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/38535
URLs in this post:
[1] здесь: https://habr.com/ru/articles/1094480/
[2] здесь: https://habr.com/ru/articles/1102620/
[3] поведения: http://www.braintools.ru/article/9372
[4] эмоции: http://www.braintools.ru/article/9540
[5] ошибки: http://www.braintools.ru/article/4192
[6] впечатление: http://www.braintools.ru/article/2012
[7] ru.dz: http://ru.dz
[8] опыт: http://www.braintools.ru/article/6952
[9] память: http://www.braintools.ru/article/4140
[10] Источник: https://habr.com/ru/articles/1107632/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1107632
Нажмите здесь для печати.