вторник, 26 марта 2013 г.

Вместо приветствия...


18-ть лет программирую на Delphi. Знаю кроме всего прочего C, C++, Objective-C, asm PDP-11, asm-Intel86, FORTH и несколько "птичьих языков". Хочу делится тут ТЕХНИЧЕСКИМИ подробностями своей работы программистом. И своими мыслями по программированию/архитектуре.

Кроме программирования сильно интересуюсь TDD и UML.

Про TDD - регулярно слышу - "это нужно только Шуре" :-) и я к этому - "почти привык".

Действительно - тестирование - В ПЕРВУЮ ОЧЕРЕДЬ нужно - программистам. ХОРОШИМ программистам.. Ну или наоборот - ПЛОХИМ.. Не гениям... Тем кто не может ПРЕДСКАЗАТЬ - как поведёт их код при внесении МАЛЕЙШИХ изменений.

Приведу один пример. Я долго и нудно и с удовольствием и с интересом программировал редактор Эверест. И на нём сделан КОММЕРЧЕСКИЙ продукт.

Так вот - в Эвересте одна из граней функциональности - печать и предварительный просмотр печати. И как это отлаживать?

Когда документы бывают по нескольку тысяч страниц. Печатать? Несколько ПАЧЕК бумаги?

Даже виртуальный принтер не помогает.

И я ОЧЕНЬ долго правил код "машины печати". И попадал в "программистские качели". Правишь тут - сломалось там.. правишь там - сломалось тут.. И так - БЕСКОНЕЧНО... Мозги готовы били вскипеть... Хотелось убить кого-нибудь рядом... Функционал - не сходился...

А ещё Группа Качества находила одну ошибку за другой.. Группа Качества была как Бич Божий!! Они находили ошибки БЫСТРЕЕ, чем я их исправлял...

Всё время находилась 150-я страница документа, или 300-я или 550-я.. Которая не печаталась.. Или на которой приложение тупо падало....


И тут я задумался о ТЕСТИРОВАНИИ... Было страшно и жутко... Хотелось ПОКРЫТЬ весь функционал тестами.. Но я не понимал как это сделать... Мысли разбегались как тараканы.. Я думал - "как же найти СУПЕР-тест - чтобы СРАЗУ покрыл ВСЁ"....

И хотелось пойти и убиться головой об стену....


Но тут нашёлся умный человек...

Александр Можаев... Он сказал - "есть DUnit - Unit-тесты для Delphi... ты наверное знаешь.. ничего космического.. но очень полезно..." Я - НЕ ЗНАЛ...

И решил попробовать....

Когда я взял DUnit и посмотрел "внутрь" - РАЗАЧАРОВАНИЕ настигло меня... Не то что "ничего космического..." а..... аа... "ВООБЩЕ - НИЧЕГО"... код простой и "ровный"...

"Я тоже так умею"...

Я спросил Можаева - "и чо?"...


Он мне сказал - "попробуй.. понравится..."...


Я пожал плечами и решил попробовать...

К тому моменту за моими плечами было несколько написанных фреймворков.. Да и вообще я думал, что "я уж знаю как всех научить программировать" :-)

(это был сарказм конечно)

Взял я DUnit И начал "крутить в руках"...

"ничего необычного".. "где же тут серебряная пуля?"

ну published-методы, которые "зачем-то" показываются в "каком-то дереве"... ну и что?

Но я решил - "раз люди советуют - значит оно того стоит"...


И начал крутить дальше... И написал СВОЙ ПЕРВЫЙ ТЕСТ (конечно не первый в жизни, но ПЕРВЫЙ под DUnit).. Который просто печатал текст... Точнее строил "предварительный просмотр печати".. Через виртуальную канву.

И тест прошёл :-) И я увидел "зелёную полоску".

Дальше я занялся "сферическим конём в вакууме".. Я стал пытаться запустить этот тест в автоматическом режиме.. И тут меня постигло ОЧЕРЕДНОЕ РАЗАЧАРОВАНИЕ...

Я то думал, что достаточно запустить "экзюк" (спасибо Всеволоду Леонову за это слово - мы раньше говорили - "экзешник") и указать "экзюку" ключ запуска - "запусти мне тест в автоматическом режиме"....


НЕ ТУТ ТО БЫЛО!!!

ОКАЗАЛОСЬ - "ключа не было" НИКАКОГО....

Я стал "курить исходники" (как говаривал ещё один мой коллега).

После вдумчивого "курения исходников" - выяснилось, что для того, чтобы тесты выполнялись  в автоматическом режиме - надо собрать ДРУГОЙ "экзюк" и в "консольной моде". Не GUITestRunner,  а ConsoleTestRunner!

"что за чёрт!" - сказал я себе - "эти авторы DUnit наверное издеваются надо мной"....

Надо МНОЙ, над человеком, который укротил "птичий язык" и Rational Rose (это тоже был сарказм). Они издеваются?!!!

Но потом я подумал.. потом подумал ещё (и мне понравилось). И я решил - а почему собственно - я не могу иметь в ОДНОМ приложении и GUITestRunner и ConsoleTestRunner. Оказалось, что - НЕ МОГУ. Но это были ЧИСТО ТЕХНИЧЕСКИЕ сложности. И я их решил.

Я скрестил "ежа с ужом".. То есть GUITestRunner и ConsoleTestRunner, которые "допилил напильником". И ConsoleTestRunner получил ещё и наследника - KTestRunner - я тогда уже думал о публикации результатов работы тестов в нашей "базе знаний" и bug-треккере.

И в итоге тесты (ОДИН тест) - заработали как в "ручном" режиме, так и в автоматическом (если задавался ключ командной строки - ItsLAW).

Дальше я вставил тесты в автоматическом режиме в автоматический запуск из Scheduler'а и был СЧАСТЛИВ.

Счастлив - потому, что мне удалось заставить "это" работать, а не потому, что я понимал - "зачем это мне".

Пока.. Пока ТЕСТ НЕ УПАЛ!!! :-) И тут я ПОНЯЛ!! Меня - БУКВАЛЬНО осенило!

Я правил "очередную нудную ошибку от ГК". Опять же про ПЕЧАТЬ...

ВЧЕРА поправил, ЗАКРЫЛ ошибку и счастливый ушёл домой СПАТЬ.

Когда я пришёл утром - УПАЛ МОЙ ПЕРВЫЙ ТЕСТ!!!

И тут меня будто током ударило!!! Вот ОНО!! Я теперь "Знаю - ЗАЧЕМ"!!!

Я решил разобраться - "а в чём собственно дело? что же я сломал вчера?"

И тут (о боги!!!) я сделал НАИМУДРЕЙШУЮ вещь.. Я НЕ СТАЛ ПРАВИТЬ код... Я сделал ВТОРОЙ ТЕСТ.. Да.. да.. Это ОЧЕНЬ ПРОСТО.. когда знаешь это.. но я тогда - НЕ ЗНАЛ...

Я сделал (повторю) ВТОРОЙ ТЕСТ.. по мотивам ошибки, которую я закрыл вчера, и которую ГК проверила и тоже радостно закрыла.

И ВТОРОЙ ТЕСТ - КОНЧЕНО же прошёл...

А ПЕРВЫЙ ТЕСТ - как не проходил, так и не прошёл...

Дальше я НЕДЕЛЮ возился с тем, что я сломал в ПЕРВОМ ТЕСТЕ (ГК это пока не нашла) и это не давало мне покоя...


Я запускал этот тест в ручном режиме и крутил всякие разные колёсики... Я же - ПЛОХОЙ программист - я не могу АНАЛИТИЧЕСКИ решить сложную задачу (я пробовал). Я лишь могу - "крутить колёсики"....

И в какой-то момент... в какой-то момент.. в какой-то момент... Я КРУТАНУЛ НУЖНОЕ колёсико... И ПЕРВЫЙ ТЕСТ - ОТРАБОТАЛ!!!

Я запустил его раз  и РАЗ.. и он - ОТРАБОТАЛ...

(напомню - я запускал тесты в "ручном" режиме  - не ВСЕ сразу, а ОДИН - первый).

Я покоммител код. Написал ошибку и закрыл её. И довольный УШЁЛ ДОМОЙ....

Когда я пришёл на работу на следующий день - очередное РАЗАЧАРОВАНИЕ ждало меня...

Упал ВТОРОЙ ТЕСТ :-(

И опять хотелось пойти и "убиться головой об стену"....

Но я взял себя в руки (это опять был сарказм) :-)

И прогнал тесты - снова и снова... И "номер первый" (на деревянной ноге) - проходил, а "номер второй" (с босыми ногами) - упорно не хотел проходить...

Моё самолюбие "гениального программиста" и "укротителя Rational Rose" было уязвлено этим "маленьким босоногим дикарём", и я решился взяться за него всерьёз...

ЦЕЛЫЙ день я искал причину его падения.. и не мог найти... В конце-концов часам к 12-ти ночи причина была найдена.. Она крылась в "маленькой запятой".. Но что это была за запятая!!! Серебряная пуля меркнет по сравнению с ней. Но она была найдена.

И НОМЕР ВТОРОЙ - прошёл!!!

Счастью моему не было предела.


Я покоммител код. И собрался домой... Вышел из комнаты.. Запер её... Пошёл на стоянку...


Но ЧЕРВЬ СОМНЕНИЯ глодал меня... я осознавал, что "я что-то не доделал"....

И я вернулся...

И прогнал ОБА ТЕСТА в автоматическом режиме...

НОМЕР ВТОРОЙ - отработал.. А НОМЕР ПЕРВЫЙ - упал :-(

Моё самолюбие было опять уязвлено..

Идти домой катастрофически расхотелось...

"Качели" подумал я..

"Эти чёртовы пограммистские качели"...

И я не ушёл....

Ошибка нашлась сама собой.. Я же находился "в потоке" и я - ЗНАЛ - что я правил и в НОМЕРЕ ПЕРВОМ и в НОМЕРЕ ВТОРОМ.. И я проанализировал изменения...

И "узорчик"!!! СОШЁЛСЯ...

Я внёс изменнения и прогнал НОМЕРА ПЕРВОГО.. И он - ПРОШЁЛ..

Тогда я прогнал и НОМЕРА ВТОРОГО.. и он.. ТОЖЕ ПРОШЁЛ...

Я счастливый отправился ДОМОЙ...

Теперь - я ЗНАЛ, ЧТО ДЕЛАТЬ и "зачем всё это нужно"...

----------------------------


"Регрессионное тестирование" - спросите вы...
"Конечно!!" - отвечу я...

Но! Плохой Гениальный программист и "укротитель Rational Rose" - НЕ ЗНАЛ этого, хотя и прочитал "миллион статей".. где "умные люди" - пытались донести "это" до "него"...

Но теперь - Я ТОЧНО ЗНАЮ ЧТО ДЕЛАТЬ...

---------------------------

Теперь у нас порядка 2000 "регрессионных" тестов.. которые гоняются КАЖДУЮ ночь.. и КАЖДЫЙ день на РАЗНЫХ машинах.. немногих.. их по пальцам пересчитать.. и мы ЗНАЕМ ЧТО ДЕЛАТЬ.. главное, что мы можем - ОПЕРАТИВНО реагировать.. находясь "в потоке".. пока "вчерашние" изменения в памяти и на слуху.. и "узорчик" - чаще - складывается, чем не складывается...

----------------------------

Ну а тестов печати у нас - всего штук 100 (оценка сверху) и СУПЕР-тест, который "покрывает всё" - нам не понадобился.. И спим мы спокойно :-)

------------------------------

P.S. в следующий раз, если не остыну, я расскажу вам о знакомстве с VGScene (ака FireMonkey) И как я её ругал.. и как тупил.. и не мог проникнуть в "слоёный пирог" стилей.. и как Антон (сам того может быть не зная) - навёл меня на понимание гениальности архитектуры данной библиотеки...

P.P.S. Также хочется рассказать - как мы локализовывали приложения под Delphi и что мы из этого вынесли.

P.P.P.S Ещё хочется рассказать как я "на коленке" делал FORTH-машину для тестирования приложений под DUnit. Как Дима писал к этому обвязку и что из этого получилось.

P.P.P.P.S Интересно также рассказать про "программирование на UML" vs. "прототипирование на UML" и метафоре "номенклатуры микросхем" vs. "собирание логики на триггерах".

P.P.P.P.P.S Ну и конечно хочется рассказать "о деле всей жизни" - редакторе Эверест. Технические подробности и решения. Которые родились в процессе этой разработки.

Ну и команда, которая делала "ту самую версию":


Комментариев нет:

Отправить комментарий