вторник, октября 31, 2006

О самонадеянности

Мне просто нравятся загрузочные экраны Windows. Всё взято с http://www.guidebookgallery.org/screenshots/splash. Версия 1.0 у меня была. Я запустил её на компьютере с 386м процессором. Она поработала секунд 10 и сдохла с неясной диагностикойПишешь что-нибудь на пару раз попользоваться, оно разрастается, начинает использоваться людьми и теряешь возможность внести какие-то исправления, потому что, оказывается, на базе этого уже построили свою функциональность. Но это ещё не самое плохое. Владелец кода in-house разработки может сказать: всё, меня пробило на улучшения: всё поноют, но сделать ничего не смогут. Главное - не смогут помешать изменять. И, в зависимости от количества дипломатических оборотов, которые хочет и может потратить программист, замена лучшего на более лучшее (слышал я такой оборот как-то от барана неместного) пройдёт более или менее безболезненно.

2.0 у меня не было, врать не буду.Но если программа (пусть это даже и целая система) писалась в сумерках разума (не важно, по какой причине) и эта программа ушла в production!.. Чтобы умилостивить богов, 90% участников проекта просто обязано застрелиться на рабочих местах (в оригинале - в кабинетах). В самом деле. Допустим, что есть некая вполне тонкая библиотека, абстрагирующая пользователя от того, как выполняется работа с базой данных. Она берёт на себя управление транзакциями, соединениями и прочее всякое. Работает. При тестировании работает just fine. Все вызовы абстрактного сервера данных надёжно защищены критическими секциями, железобетонная корректность открытия и закрытия транзакций также не вызывает никаких сомнений. Работает. Казалось бы.

А теперь посмотрим.

public virtual object SelectScalar()
{
lock(m_CommitSync)
{
int threadId = ThreadId.Value;
object result = null;
try
{
GenericConnection.Open(SQLDataAdapter, threadId);
result = SQLDataAdapter.SelectCommand.ExecuteScalar();
}
catch (Exception ex)
{
DumpException(ex, SQLDataAdapter.SelectCommand.CommandText);
}
finally
{
GenericConnection.Close(threadId);
}

return result;
}
}

А вот с 3.0 я натешился. Нестабильность, в которую я сейчас даже не верю, явно обозначенная прожорливость, но при этом - работает! Первая моя программа для Windows была написана и собрана на 3.0То есть, шансов нарушить выполнение нет (см. lock в начале метода). + соединение всегда закроется, это с гарантией. Всё, в общем, работает отлично. Но заметили: если выпустить программу в дикую природу, то начинаются проблемы c deadlocks, "timeout expired prior to completion" и т.д. Библиотеку протестировали вдоль и поперёк. Трудно придумать, какой тест я не написал, чтобы удостовериться, что всё ok. Но оно не работает.

Так как я себе верю (а ещё больше - зелёной полоске), то библиотека выводится из круга подозреваемых. Остаётся:

  1. Процессор
  2. SQL Server
  3. Данные

После некоторых колебаний процессор и SQL Server пришлось с сожалением убрать. Оккам показал на данные. Инспекция (чужого) кода показала, что присутствуют:

  1. Неправдоподобно длинные методы для Insert, Update, Delete
  2. Для чего-то производятся постоянные выборки всех записей (ок. 600000) из одной популярной таблицы

Да, и ещё ThreadId.Value возвращало Thread.CurrentThread.ManagedThreadId;

Почти день я прозанимался этой проблемой, свалившейся на меня (всё время всё сваливается на меня) из FB (приоритет 1, конечно). Что я могу на её счёт сказать? Раз уж сегодня всё пронумеровано, то вот:

  1. Длинные методы писались без понимания того, как это будет работать. Всё-таки один клоун Вася (Петя, Коля, Вова и пр.), запуганный своим кодом до того, что боится даже лишний раз нажать на кнопку в готовой (по его мнению) программе - это одно, а толпа тёток, которые без прелюдий ошибаются (кто бы мог подумать) и закрывают окна, когда они начинают скрывать их пасьянс (не говоря уж о том, что им просто обязательно провести собственный обезьяний тест) - это нечто радикально другое. Когда тётки наваливаются на несчастную чахлую тушку программы и начинают её накрячивать вдесятером - тут и выясняется, что у программиста ваще не было представлений о том, что он пишет, для чего и кто использует.
  2. Излишняя, преступная и вредительская самонадеянность ("такого никогда не может случиться"). Тут и расшифровывать даже не хочу.

Код нельзя просто написать, скомпилировать и дальше неделю пить пиво и пялиться по выходным в телек на новую серию "The Sopranos". Это так примитивно, что неловко даже писать: код должен развиваться. Его надо пересматривать. Он не должен отражать ваше понимание проблемы двухмесячной или двухгодовой давности. Для историй у нас есть SourceOffSite, а для ностальгических соплепусканий ("ах, как всё было просто много лет тому назад"- хрена с два! просто никогда не было!) - http://www.guidebookgallery.org/screenshots/

2 комментария:

Unknown комментирует...

Не хотел писать, на самом деле - ведь я тебе, вроде, все с дидлоками объяснил.
Такие методы, как приведенный тобой, вредны для работы с БД. Особенно с учетом вызова из этого метода других методов. На ком ответственность за порядок выполнения в таком случае - неизвестно, sql-код (который РЕАЛЬНО будет исполнятсья на сервере) не контролируется никем. В общем, можно поиметь довольно толстую задницу на самом ровном месте, и дидлок - не самое страшное. Куда страшнее лишний траффик, "переприпаривание" команд и т.п. А синхронизация потоков ВНУТРИ транзакции... Ты бы еще дилоговое окошко во время транзакции показал, и удивлялся бы блокировкам 8)
Я думаю, нужно более серьезно относиться к серверам БД, но раз уж даже гуру программирования Фаулер "забыл" (в толстой книжке про шаблоны проектирования для энтрепрайз-систем) про возможность дидлоков в шаблоне "транзакция" - то что уж с практикующих девелоперов взять?
указатели, стеки, рекурсия, потоки... Я думаю, наседая на эти области, ты часть полезного народа отсеиваешь - есть многое на свете, друг Горацио.
имхо, конечно.

Das Ich комментирует...

Мне кажется, ты не понимаешь, что такое синхронизация потоков.

А будешь много пиздеть, я вышлю тебе лог работы сервера за сутки, ты на его примере покажешь методы работы, которые "полезны для работы с БД".