Здравствуйте, Poopy Joe, Вы писали:
PJ>Если память утекла, то ни одна из функций работать не будет.
Опять: для очень широкого класса приложений это не так. Веб приложения вообще по умолчанию рестартят каждые 15 минут.
PJ>Озвучь еще раз, в явном виде, если в результате рефакторинга исчез баг, то это рефакторинг неаккуратненький и цель не достигнута?!
Тут самое время задаться вопросом: если
намерения починить баг не было, но он таки починился — это что же, разработчик не понимал, что он делает?
Ну, ок, один баг он починил. А сколько
добавил?
На самом деле, конечно, я не предложу откатывать такой рефакторинг. Да меня никто и не спросит — я в техническую часть разработки уже много лет почти не влезаю.
PJ>Что-то сильно не так со... всем и вся. Если проще написать KB Article, чем исправить ошибку.
Добро пожаловать в реальный мир, Нео. Я когда впервые читал статью про то, что MS часто вместо респина релиза выкладывает KB, тоже был сильно удивлён.
Прошли годы, я сам поварился в продуктовой части разработки, осознал мудрость старших товарищей.
PJ>Раз за вас, только что это меняет? Типа прикладной софт можно и нужно криво писать?
Да, конечно. Любой софт должен решать поставленные перед ним задачи. Вот вы действуете в молчаливых предположениях, что можно точно знать все сценарии использования публичного АПИ. Возможно, для какого-то системного софта это так и есть (неспроста же производители железа дают доступ к своим datasheet вовсе не всем подряд). А для обычного гражданского прикладного софта — вроде того, который нас окружает в повседневной действительности — это недостижимая утопия.
Зато нет жёстких требований к утечкам памяти и корректной обработке всех fail path.
PJ>Я не оправдываю кривой рефакторинг, а я говорю о том, что кривой рефакторинг все еще называется рефакторинг. И ты, не смотря на свой догматизм, называешь его так же, как и кривой дизайн.
S>>Из опыта и наблюдений.
PJ>PJ>- А я тебе говорил — место проклятое!!! А то всё "руки из жопы, руки из жопы"
PJ>
Место ни при чём. Во всех местах, с которыми мы взаимодействуем, происходит примерно то же самое. В большинстве мест — хуже, чем у нас.
S>>Смотря что считать некачественной программой. Программу, которая игнорирует ошибки, поддерживать значительно дешевле, чем ту, которая их все аккуратно обрабатывает.
PJ>Ну поддерживать-то ее может и дешевле, а вот как на ней заработать? В моей реальность эдак не только не заработать, а и на деньги попасть можно.
А в моей — нет. Другой бизнес-ландшафт. В моей действительности есть более-менее критичные пути — например, нельзя брать деньги за покупку дважды. А есть некритичные пути — например, если заказ "не удалось разместить", то это более-менее ок, если происходит не слишком часто. Это как телеком — если вы, набирая номер, услышите пик-пик-пик, или посреди разговора связь оборвётся, или там начнутся разрывы в звуке — ну, пустяки, дело житейское, радиоволны — штука малоизученная. А вот если вас соединят вместо сбербанка с ИК-18, то это ай-яй-яй.
Так и у нас — мало ли, почему нам не удалось принять заказ. Там цепочка вызовов проходит через десяток систем — каждая могла лажануть. Где-то место для логов кончилось, где-то админ накриворучил, где-то связь с апстримом легла на 10 секунд. Никто не требует и не ожидает от фронт-енда всеведения и способности уникальным образом обработать каждую из полуторых сотен возможных неисправностей.
По факту, многие компоненты ухитряются даже не хранить подробности проблемы — типа "в лог насрали — можно и упасть". А потом оказывается, что логи ротируются каждые 48 часов, так что к моменту, когда реквест доезжает до инженеров, смотреть уже некогда. Это, кстати, не "наш" компонент — чтобы вы не подумали, что я вам опять рассказываю, какие мы тут самые убогие.
И, кстати, этот не наш компонент прекрасно зарабатывает большие деньги. NDA миллионов долларов в месяц.
PJ>Неа. В аккуратной программе кода меньше. Хотя бы потому, что он лучше структурирован и меньше дублирования, и уж точно меньше зависимостей.
Мы говорим про разную аккуратность. Как ни крути, а программа с
catch(Exception e) { log.Write(e)} короче, чем программа с 10 сatch на разные типы исключений.
PJ>Я может чего не понял, но че-то не впечатлился масштабом проблемы заменить один код, на другой три раза за два года.
Отож. Это если совсем нечего больше делать — то нет проблемы. Ну, и если забыть про то, что код стоит не только у нас в лабе, а ещё и партнёров, и каждый хотфикс требует раскатывания каждому из них, а у них, естественно, свои политики тестирования в стейджинге и прочее.
А если не забывать, то становится понятно, что одна вот такая безответственная выходка приносит убыток в размере от сотни тысяч до миллиона долларов.
PJ>Ну ты просто посмотри на это с точки зрения MS, они тоже могу сообщить о количестве "пользователей, администраторов, реселлеров, менеджеров и прочего обслуживающего персонала." А ты про них говоришь "недоумки".
Ну да. Потому что это их количество пользователей, администраторов, реселлеров, менеджеров и прочего обслуживающего персонала получено в значительной мере благодаря усилиям технологических партнёров вроде нас.
Кто стоит между недоумками и конечными потребителями, корректируя недоработки детишек из Бельвью и Редмонда.
PJ>Меняет. Почти невозможно его провести не изменив хотя бы чуть-чуть. Чисто физически. Ну и если вы в дотнете, то это вообще не аргумент.
Конкретно мы — в дотнете.
PJ>А вот какое-нибудь многопоточное изменение состояние вы поймать может запросто. Думаю и ловили.
В рамках рефакторинга — нет. У нас не F#, безумцев, которые в рамках рефакторинга будут менять схему раскладывания задач по потокам, нету.
В рамках переделок, не сводящихся к рефакторингу — да, там сколько угодно. Ну, если многопоточное изменение понимать в широком смысле — у нас практически нет кода, асинхронного в рамках одного процесса.
Там скорее код бизнес-процессов, где мы обрабатываем цепочки событий, порождая свои события. И вот там-то запросто можно напороть, типа "а давайте мы перенесём вот эту штуку с этого шага на вон тот" — и потом что-то идёт не так, потому что параллельно с этим выполняется какой-то чужой код.
Ну там, простейшая штука — конвертируем trial to paid. С точки зрения пользователя это одно событие "разместить change order, указав новый период подписки и нужное количество лицензий". А в системе это два разных события "period change" и "quantity change". И ядру всё равно, в каком порядке посылать, а микрософту — нет, потому что у триалов изменять количество нельзя.
Поэтому когда на стороне ядра системы делается рефакторинг, в результате которого порядок этих событий из (непреднамеренно) детерминированного становится случайным, внезапно отваливаются некоторые привычные сценарии.
(На всякий случай поясню: ядро системы — не на дотнете. У нас с ним вообще нет общей кодовой базы; и нет никакого build tool, который бы запустился и сказал "ой, у вас тут несоответствие типов — один из модулей использует ваши события вот таким способом).
PJ>Так любой баг это "poorly done фича" или вы их отдельным процессом вносите?
Отдельным процессом
В нынешнем состоянии продукта большинство багов — это результат изменения внешней системы. Типа того же Microsoft, который в какую-нибудь из пятниц выкатывает breaking change без предупреждения.
PJ>Хождение по кругу. Не зная задачи в деталях, я не могу сказать точно, что вам надо было делать и что надо делать сейчас.
Ну да. Но при этом вы почему-то уверены, что мы делаем всё неправильно.
PJ>Мы обсуждали технический долг. Мой поинт был в том, что технический долг возникает не в момент когда покупку объявляешь подпиской, а в момент когда ты вместо выдавания totals или еще какой производной от ордеров, выдаешь сами ордера чтобы клиент с ними что-то делал.
А им не нужен totals как таковой. Нужна гарантия, что если через систему прошло 11 миллионов долларов, то у нас должны выдаваться ордера на всю эту сумму.
Ну ок, мы можем выдать им отдельную операцию GetOrderTotals — толку-то? Ей всё равно придётся выбирать, с чем быть консистетной — с суммой
всех ордеров или с суммой ордеров
подходящего для GetOrdersV1 типа.
PJ>И, в конечном итоге, его проще выкинуть и написать заново.
Ну, пока что мы пережили две попытки выкинуть и написать заново (это из тех, которые я знаю). Точнее не так; выкидывать продукты — слишком рискованный бизнес.
Приходили ковбои, которые говорили "ваш продукт нежизнеспособное говно, неспособное к быстрым изменениям. Мы в своём продукте любую из фич, которые вы пилите по три месяца, делаем к концу недели".
Практика показывала, что нет, не к концу недели. И что не любую из фич. Хрен с ним с тем, что у нас из коробки идут вещи, которые конкурентам пилить и пилить годами — даже прикручивание чего-то нового (вроде тех же однократных продаж) в нашей системе делается быстрее и работает надёжнее.
PJ>Так ты его и не обеспечил. Инвариант это неизменность свойства при любых трансформациях. У тебя покупка стала подпиской. Это не инвариант.
Игра словами. У меня по-прежнему деньги совпадают с деньгами. Это — самый главный инвариант. На фоне него то, что покупка называется "подпиской на вечную лицензию" — мелочь, не стоящая упоминания.
Ну, как в кофейнях на чеке написано имя клиента и 0,00 — это потому, что кассовая система не умеет учитывать имя клиента, и эта доработка стоила бы как самолёт.
Поэтому бариста пробивает "АННА 1шт" по цене в 0 рублей (а продажа штучных товаров мимо каталога в кассе уже есть), и все довольны.
PJ>Ну так может стоит начать их выражать явно? Глядишь в следующий раз грабли уже не ударят по лбу.
Ок, давайте. Выразите явно в контракте тот факт, что сумма от IEnumerable<Order> GetOrders() совпадает с суммой от IEnumerable<Invoice> GetInvoices().
А потом попробуйте добавить новый вид ордеров, не меняя ни этого факта, ни сигнатуры GetOrders(). При том, что Invoice-то как раз одинаковый для любого вида ордеров.
Может я научусь чему-то новому.
PJ>Вот я примерно про такое и говорю. Гниение и разложение. А все потому, что технические проблемы не казались главными или важными.
PJ>Три месяца, чтобы понять что делать... Ты же сам говорил, что вы настолько даже не планируете?!
Вы невнимательно читаете. Я говорю не про нас — мы-то как раз любимчики у Microsoft. Я говорю про компании, которые потребляют те же API, что и мы, только работают по-другому. Например так, как я описал.
В приличной корпорации получить анализ проблемы за три месяца — это ещё хорошо. Представьте, что вам нужно получить экспертное заключение по
непрофильному для вас виду деятельности. Сколько времени ваша компания будет выбирать подрядчика для этого заключения? По-хорошему, надо объявлять тендер. Вы же не будете проводить его "сегодня до вечера". Сначала вы объявите тендер — подготовка к нему займёт около недели. Потом ещё месяц вы будете собирать предложения. Ок, прошло пять недель — вы выбрали подрядчика. Теперь ваши юристы с его юристами занимаются согласованием взаимных NDA и утрясанием IP Rights, потому что вы не хотите попасть в ситуацию, когда этот подрядчик перепродаёт налево оплаченные вами наработки. А подрядчик, естественно, именно этого и хочет.
Если всё суперхорошо, и обе стороны полностью довольны документами друг друга, это займёт неделю. Если нет — то две-три. Иногда — месяц (обычно, если согласование юристами занимает больше месяца, то сделки не будет. но это не точно).
Ок, ладно, шесть недель прошло — наконец-то подрядчик получил доступ к вашему legacy и теоретически может начать анализ. На практике у него конечно же нет команды инженеров, которая плюёт в потолок в ожидании подписания сделки. Если подрядчик — хороший, то его инженеры сейчас пашут на другом проекте; кто-то освободится через пару недель как минимум.
С кодовой базой он не знаком; насколько она документирована — большой вопрос. Редко когда заказная разработка идёт с подробными комментариями, диаграммами пакетов и прочими артефактами. В хорошем случае инженеры подрядчика недельки через две будут готовы выдать
предварительный результат. Уточнение и проверка займут ещё пару недель — потому что новый API почти похож на старый, но есть важные нюансы, и подрядчик не захочет рисковать выдачей заниженной оценки. Вот у нас уже три месяца и натикало — и это без неожиданностей типа "наш юрист заболел" или "начался мировой карантин, поэтому мы не сможем приехать к вам в офис".
Ещё раз подчеркну: это — совершенно нормальные, типичные для индустрии административные трудности. Очень легко рассуждать с позиции кодера: "да я внесу изменение в наш клиент к этому API за 15 минут".
Ну, так в наш код и я внесу, хоть я и менеджер — дальше-то что?
Лично мной мир не исчерпывается. И я более чем один раз наблюдал, как идеи "а давайте-ка выкатим ломающее изменение к февралю" откладываются на год-полтора. И у нас, и у Microsoft. Потому, что какой нибудь Telmex или Dell говорит "вы охренели", и архитектурные астронавты спускаются из стратосферы на землю грешную.
Потому как это вам оттуда кажется, что всё плохо там, где я работаю. А на практике оказывается, что как раз у нас-то всё более-менее лучше всех, по крайней мере в нашем сегменте.