суббота, 14 декабря 2013 г.

Исповедь про тесты в разработке.

Сегодняшнюю запись я хочу озаглавить старой "поговоркой":
"Админы делятся на две категории:  те кто ещё не делают бэкап и те кто уже уго делает".

Как супер полезны тесты гласит каждая первая запись о них. Читаешь - глаз радуется.
Потом начинается фалометрия с test coverage. Что обязательно оно должно быть в 146% и пр. пр.
Я заниматься этим сейчас не хочу. Расскажу я про психологические аспекты при внедрение тестирования. Соответтвенно далее идут всё рассказываю про себя.

Боязнь забыть суть

Очень простая и здравая идея не делать тесты, если код делать 10 минут. Читается он легко уровней абстракции всего ничего. Радость просто. Для того, что бы понять код через месяц потребуется пять минут. А что если код вы делаете к примеру два раза в день по 2 часа. А это значит, что ваш объем кода достигнет таких объемов при котором: 
"# TODO: Надо тут поправить кое-что " -  будет вызывать у вас смутные подозрения, что вы этот кусок уже подзабыли. И на воспоминание этого "кое-что" уйдёт много времени...

А при чём тут тесты? 
Резонный вопрос, вроде бы ни причём, если вы не тестируете логику приложения. А когда вы её тестируете, то взглянув на тесты вы быстро понимаете приложение и кусок того, что надо сделать.
Вывод: тесты должны покрывать логику и граничные условия.

Боязнь изменения кода

Честно, я много раз ловил себя на том, что я уже не помню как этот кусок работает, суть не очень помню... хотя вроде тут совсем чуть-чуть поправить-то надо было... И спустя 3-4 часа это "чуть-чуть" плавно перерастает в "ОГОГО". Всё это было до тестов. С тестами я могу править кусок и не так сильно бояться за целостность приложения. Оно упало и мне надо подогнать под тесты и при баге добавить тест.

Вывод: тесты уменьшают ваш внутренний страх.

Нежелание возвращаться к коду

У меня такое было часто, до тестов. Почему? Страх изменения кода играл в этом ключевую роль. Я боялся, очень. Правда сказать я и сейчас боюсь, но куда меньше. Просто несоизмеримо меньше.

Ну это всё голые слова и ничего более

Я ничего ни кому доказывать не хочу, кроме как себе любимому.
Сделал я просто, взял и замерил два проекта приблизительных по объему и качеству кода. Т.к. всё это с двух моих проектов, которые делались в приблизительно одинаковый промежуток времени, то я смело считаю, что могу делать такое сравнение.
Замеры делал просто. Я брался за код, только в выходные. И не ранее чем через 2 недели для каждого проекта. Засекал время по следующим параметрам:
1. Сколько у меня уходит времени поправить баг?
2. Сколько у меня уходит времени сделать TODO(обычно это фичи или улучшения) в коде?
3. Сколько у меня уходит времени внести глобальные правки (разработать новый модуль)?

Стадии при разработки были такие
a. Понять суть задачи
b. Найти код который за неё отвечает
c. Запустить и посмотреть, что и как он делает сейчас.
d. Внести изменения.
e. Проверить и если что-то идёт не так, то вернуться к пункту "d".

Первый, второй и третий пункты одинаковы, по этому их время - константа. Обычно это около 15 минут для меня.
А дальше мы видим итерации, вот их я и считал. Вот данные по 2 пункту (TODO):
1. Количество итераций: Без тестов: 5-8 итераций. С тестами 12-16 итераций.
2. Время занимаемое на итерацию: Без тестов от 20 до 30 минут. С тестами от 5 до 10 минут.
Итог: без тестов от 1.5 часов до 4 часов, с тестами 1 часа до 3 часов.
Я стал замечать за собой, что после итерации я запускаю тесты и только когда они проходят иду уже смотреть конечный результат. Именно по этому итераций стало существенно больше, но все они стали проходить гораздо чаще. Мне морально проще смотреть промежуточный результат, когда код прошёл тесты.
Вывод: для меня тесты уменьшили срок выполнения задачи в 1.5-2 раза. Хотя на написание тестов в начале(3 пункт) я трачу в 1.5-2 раза больше времени, но само это время на порядок(около десяти раз) меньше, чем то время, которое я трачу на отладку без тестов.

Что мне это дало?

Я перестал относиться к коду, как к УГ на которое мне сейчас надо убить уйму времени.
Я стал его рассматривать как задорные какушки, которые быстро и красиво можно поправить. И теперь мне стало легче.

Тестировать всё и вся!

Часто в статьях вижу, что тестами надо покрывать всё и вся. И тогда у нас будет coverage(покрытие) на все сто и мы точно застрахованы от всяких там ошибок.
Но вот вопрос. А что же надо покрыть и нужное ли мы тестируем? И вот тут возникает множество вопросов ответы на которое очень зависят от контекста задачи.
А для себя я определил что и в каких рамках я тестировать обязан.

четверг, 14 ноября 2013 г.

Прибило

Сидит дома композитор. Работы нет. Денег нет. Кризис.... И тут - звонок. Звонит приятель — режиссёр:
— Слушай, мне тут к фильму тема нужна на финальные титры. Сбацаешь что-нибудь простенькое? Премьера через 2 недели уже, погибаю, спасай!!!
— Данивапрос! Расскажи только о чём фильм, чтобы я с музыкальной темой не промахнулся?
— Да в нем вообще музыки нет! Тема только для титров нужна. Ну представь себе: с сухого дерева лист медленно зигзагом падает на мокрый асфальт, и как только долетает до земли — начинается твоя тема и титры.
— Ок. Через неделю сделаю!
И композитор скреативил неимоверно красивую, дивную музыку — хоть сейчас на "Оскара". Ну и отправил режиссёру. Тот ответил, мол все ок, и пригласил на премьеру ...
Приходит композитор — зал пустой. Только на галёрке парочка пожилая сидит - обоим далеко за 80. Ну, думает композитор, ясное дело — драма нынче не в цене, никого кроме старичков не интересуют. Сел он, свет погас и началось...
На фоне природы мужик самозабвенно ебёт тёлку с огромными, как баскетбольные шары, сиськами. Дальше — больше, еще парочка подошла, поменялись... Потом ещё негры, калеки, карлики - уже вся эта кодла в экран не помещается! Потом вообще собака прибежала!!! Сначала собака всех отодрала, потом все собаку трахнули...
И тут камера берёт крупный план, наезжает на сухое дерево, на лист, лист срывается и медленно падает зигзагом на землю, звучит неземная, дивная тема и идут титры. Зажигается свет...
Композитор сидит в шоке, красный как помидор от стыда. Думает "Ну, сука, режиссёр, ну удружил! Что обо мне люди подумают!" Встает со своего места, с этими мыслями идет к выходу и тут замечает, что пожилая парочка, в предынфарктном состоянии сидит и на него смотрит... И он ничего лучшего не находит как сказать:
"Музыка моя!"....
А они, продолжая смотреть стеклянными глазами на пустой экран, отвечают: "... А собачка наша..."

четверг, 24 октября 2013 г.

Давече вскрыл я utinet

В общем такой себе забавный интернет магазин.
И менеджер по продажам тебе позвонит, если с заказом тупишь  и цены низкие при этом. И вот тут у меня сразу прозвенел "звоночек". Слишком агрессивный и дорогой сервис и цена достаточно низкая. Так что могут быть огрехи.
Тут я с этим звоночком смирился, т.к. ошибки бывают у всех, если у вас из нет, то ответ у меня для вас только один: "б-г какого хрена ты это читаешь".

Второй звоночек был такой, что я не смог заказать по безналичному расчету через магазин.
Со мной связался менеджер и мы быстро решили данный вопрос. Счет был выслан в пару минут.

По банку всё провели, деньги поступили. Получил SMS, что готовят к телепортации.
По времени телепортации предупредили за пару часов. Но тут стоит сделать финт ушами и кое-что уточнить. У безналичного расчета есть некоторый нюанс: получить товар без доверенности или печати нельзя. Моя практика показывает, что фирмы, которые часто работают с безналом отправляют курьеров, которые этот нюанс спрашивают.

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

Я человек терпеливый, но и моё терпение имеет свои разумные границы.

Вот как-то так, чуть позже когда вся эпопея кончится, я выложу номер заказа, что бы было честно.

Как это произошло и как с этим бороться вполне очевидно. Надеюсь, что магазин себя покажет, а я пока подожду годок другой.


Звоночки в голове

Это то ощущение, когда что-то идет в разрез с известными мне принципами. И происходит такой вот странный когнитивный диссонанс.

Самая важная когниция:
Инженерный принцип.
Можно сделать быстро, дешево, качественно - выбирайте любые два условия.
Ещё ни разу меня не подводил. Работает абсолютно всегда и везде. Исключений нет.

Если звонит этот "колокольчик", то стоит сразу задуматься.

Вторая когниция:
Качество - абстрактный термин.
Стоит помнить, что время и деньги - это простые параметры, которые легко формализовать под каждую задачу. И часто недопонимание приходится на термине "качество".
Для дешево всегда можно установить лимит денег, по времени тоже можно лимит установить. А вот качество необходимо оценивать в каких-то точных показателях. И для каждого продукта и услуги они вами должны быть точно описаны и сформулированы.
Как следствие, для определения качества мы должны описать все параметры которые нас интересуют и придать им весовое значение. Качество - комплексная величина.

Третья когниция:
Слова данные устно и слова данные письменно - всегда разные.

Если кто-то дает вам слово письменно, то он его будет держать, а вот устное слово ничего не значит. Тем более, что разные абстрактные термины, вроде качества, трактуются людьми различно.

Четвертая когниция:
Дьявол кроется в деталях(мелочах).
Надо четко и подробно формализовать все абстрактные и/или не ясные для вас детали.

По своей сути эта когниция расширяет четвертую и дополняется третьей когницией.

P.S.: По мере формализации своих "звоночков" я буду дополнять данный раздел.
Сразу скажу, что все эти знания я усвоил на собственном опыте.


воскресенье, 26 мая 2013 г.

Навеяло воспоминание

С за.е.баш.а

Попросил знакомый(работает в полиции) прикупить хард, потестить на нашем стенде и 1С залить до кучи. У него самого карма плохая: если диск сам купит, обязательно либо с браком, либо ещё какой косяк выходит. Ну, значит, купил, проверил, отзвонился, что можно забирать. Накинул ветровку, вышел на крылечко, курю. Выходит шеф. Посмотрел на меня, достал сигареты, тоже закурил. И всё бы ничего, но угораздило же знакомого приехать на служебной машине! Представьте себе ситуацию:
Перед нами останавливается машина с ППСниками. Из неё выбирается парнишка в форме, здоровается, протягивает пару косарей, забирает хард:
— Ну что, бухгалтерию залил?
— Залил.
— Тогда я сейчас по-быстрому в прокуратуру смотаюсь, а вечером обмоем.
Шеф стал седым в 35 лет

суббота, 18 мая 2013 г.

ido2db - Could not bind socket: Address already in use

 find /var -name "ido.sock" -exec rm {} -f \;
Вот и весь рецепт.
Если не хотите, что бы при:
 /etc/init.d/ido2db start (restart)
Такое повторялось, то найдите этот файл: 
find /var -name "ido.sock"
и в /etc/init.d/ido2db в разделе do_start в начале напишите:
 rm -f /var/lib/icinga/ido.sock

Замечено, что ido2db оставляется это файл, если был force halt (really power off).

воскресенье, 5 мая 2013 г.

АСУП и как его едят...

Сегодня расскажу немного про автоматизацию на предприятии.
АСУП - Автоматизированная Система Управления на() Предприятии(ем).
Автоматизированная не равно автоматическая. Это значит что потребуется оператор, но роль оператора мы должны свести к минимум за минимум средств.

Я приведу ряд своих правил для автоматизации, которыми я пользуюсь давно и они мне очень помогают.

Первое правило автоматизации

Внимательно изучите все входящие и выходящие данные. Не бывает так, что бы не было входящих или исходящих данных. Если вы видите, что каких-то данных нет, то добивайтесь этих данных, хоть пытками, иначе дальше дело завалится.

Второе правило автоматизации

Составьте схему процесса. В начале сделайте набросок в общих чертах и детально изучите, что, куда и как движется в вашем процессе. Желательно это задокументировать. Если схема простая, это значит, что любой сторонний человек может её понять за 5-10 минут, то  просто записать, если сложная, то рисуйте диаграммы, схемы (UML, дракон-схемы и пр. вам в помощь).

Третье правило автоматизации

Детально и внимательно отнеситесь к тому, что и как делают реальные пользователи с данными. Тут проще пройти цикл работы самому. Опытному пользователю(да-да это именно вы) не составит труда самому поработать и оценить свою скорость и скорость опытного оператора. Если интерфейс взаимодействия хорош, то скорость оператора раза в 3-4 будет выше, чем ваша и при этом вы не будете ругаться на интерфейс через 20-30 минут. Если ваша скорость равнозначна с опытным оператором, то интерфейс надо переделывать. Если оператор медленнее вас, то он не опытен. Когда вы пройдетесь сами по сценарию пользователя, то вы на много адекватнее воспринимаете и критику и предлагаемые изменения.

Четвертое правило

Заранее оцените какие сторонние или внутренние средства предлагаются вам для автоматизации. К примеру для софта желательно иметь хотя бы C-API. Изучите весь комплекс средств, поговорите с разработчиками. Попросите их документацию, если такая имеется. Это может вам сэкономить десятки, а то и сотни часов рабочего геморроя. Ни разу не шучу. Документацию надо читать и естественно очень настораживает, если таковой нет в природе.

Пятое правило

Задачу можно решить несколькими методами. Если вы нашли только один метод решения, то у вас беда. Оцените каждый метод по трудоемкости. Если вы не способны оценить задачу по трудоемкости и времени, хотя бы в порядок величин, то вы не инженер.

Шестое правило 

Посчитайте на сколько вы способны улучшить процесс и сколь затратно это будет вам.
Рабочее время разработчика в среднем в 5-7 раз дороже времени оператора.
Оптимальный срок окупаемости - финансовый год. Вот от сюда надо и плясать. Так же стоить помнить. что вам надо избавиться от дополнительных операторов или же суметь максимально нагрузить операторов.

P.S.: и помните об этих правилах когда вам предлагают ERP или АСУП системы ушлые сэилзы, им втюхать и деньгу получить, а все вышеизложенные пункты нужно будет всё равно пройти... просто сэйлз предложит вам пройти их ещё доплатив раза в 3-4 дороже.

вторник, 23 апреля 2013 г.

VMWare server + VNC

Конечно у вари есть веб-клиент, но вот, он не очень хорош, на мой взгляд.  А бывает так, что родной vnc плагин для браузера ешё и не установишь... Что делать?
KVM вообще сразу торчит на 5900 порту. А вот варя нет. Что ж, давай те научим.

Конфиги виртуальных машин у меня лежат в /var/lib/vmware/Virtual Machines/
В этом каталоге идет перечисление виртуальных машин
drwxr-xr-x 2 vmware    vmware         4096 Apr 21 20:39 Virtual Machine

drwxr-xr-x 2 vmware    vmware         4096 Apr 21 21:30 Virtual Machine_1
drwxr-xr-x 4 vmware    vmware         4096 Apr 21 21:21 Virtual Machine_2

Ну как-то так...

В каждом каталоге находится свой файл с конфигурацией, называется <имя виртуальной машины>.vmx

Опций на самом деле там совсем чуть-чуть, о них естественно надо бы читать в документации, но нам надо добавить всего ничего:


RemoteDisplay.vnc.enabled = TRUE
RemoteDisplay.vnc.port = 5901

И рестартануть варю.

Наслаждайтесь, только помните, что когда гостевая ось тушит свой монитор, vnc клиенты любят вырубаться, что может вызвать ряд не нужных проблем.

P.S.: машин на kvm у меня на порядок больше, но вот когда-то они не умели прокидывать usb dongle, а варя умела.


воскресенье, 31 марта 2013 г.

russian mount

Ну собственно вроде всё хорошо, но моменты всякие бывают.
К примеру вы можете создать пользователя "Вася". А вот смонтировать нормально раздел через fstab может не получаться.
Тут всё просто. Монтируем раздел через mount. Идем в /etc/mtab и спокойно копируем всё что нам надо )

воскресенье, 10 марта 2013 г.

SIKULI

Один из нюансов SIKULI.

Если вам надо что-то напечатать в активное поле, то можно использовать две разные штуки.
Либо: type('some text')
Либо: paste('some text')

А в чём разница? А вот всю просто. Первое вставит данные символы как вы печатаете на клавиатуре, в той раскладке которая сейчас активна для приложения... да-да, правильно, если открыта русская локаль, то будет не 'some text', а 'ыщьу еуче'. А вот второе именно вставит, а не напечатает, т.е. будет сразу 'some text'.

вторник, 5 февраля 2013 г.

Хочу интернет-магазин

Да, вот именно с таким вопросом ко мне часто обращаются.
И я рад помочь в этом вопросе, тем более, что кое-какой опыт всё же имеется :)

Сразу скажу, что с таким вопросом мне регулярно (2-3 раза в месяц) обращаются люди. И у 90% из них в голове реальная каша. Вот, что я выяснил за время общения с таки людьми:

Я не понимаю, чем я буду торговать

Скажите так не бывает, а вот и я так когда-то думал. Реально человек кроме совершенно простой идеи, даже без намёка на проработку, создания концепции, "реперный" бизнес-план и пр. Хочу говорит торговать и всё тут.
Аналогия: покупать молоток для забивки шурупов и закручивания болтов.

Хочу за бесплатно или условно-бесплатно

Это скажем так, самое частое, что я вижу. Т.к. создание сайта - это услуга, можно сказать творческая услуга. То делают её сидя ну стуле (стол, пол, шкаф, диван - нужное подчеркнуть) уткнувшись в монитор. И заказчик почему-то считает, что сделать сайт -  5 минут, ну 2-3 часа на интернет магазин и стоить это должно - 5000 рублей... хорошо, "скрипя сердцем" отдам 20 т.р. 
Аналогия: хочу клёвое помещение в центре Москвы за 300 рублей кв. метр в год.

У меня есть розничная точка, нужен по-быстрому интернет магазин

У заказчика складывается ощущение, что интернет-магазин на много проще, чем розничная точка. Хотя реальность говорит, что через розницу, что через интернет, продавать одинаково не просто и нюансов в обоих случаях - много.

Целевая аудитория - все

Это сразу выдает, что заказчик не понимает азы продаж. Возможно, что у него что-то получается продавать, но вот выстроить бизнес-схему без анализа нельзя. А заказчик сразу расписывается, что он анализа не знает и не понимает.

Прим.: даже хлебушек не все любят, а значит целевую аудитория надо сужать, дробить, категоризовать и анализировать, анализировать и анализировать.

Сделал сайт и сразу же должны пойти супер продажи

Такое слушаю я в 50% случаях. Ну что тут можно сказать. Адекватность хромает у человека и надо её как-то поднимать из руин. Продаж не будет, т.к. в организацию продаж надо вкладывать ресурсы. Интернет магазин - площадка(основа) будущего бизнеса.

Аналогия: дом состоит из фундамента, коробки, первичной отделки, дверей и окон, финальной отделки, интерьера и доп. оборудования. Понятное дело, что только в одном фундаменте и коробке особо жить не будешь.
 

Маркетинг гауно, только сарафанное радио

А вот это на самом деле возникает из-за того, что никто не считал маркетинговую компанию. И, соответственно, не видел результатов этой компании. А результаты эти, как правило достаточно показательны и достаточно эффективны. Ну что можно сказать, скупой платит дважды, трижды, четырежды ... пока не надоест, и ещё один раз, что бы всё исправить.

Бизнес-план, концепция, финансовый план, риски - это для лохов

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

воскресенье, 6 января 2013 г.

Всех с релиз кандидатом джанги.

Спасибо разработчикам, за долгий и нудный отказ от герои... USER model и позволение нам, простым смертным, использовать свою собственную модель без onetoone :)

Внимательно читаем release note, т.к. внесено достаточное кол-во ломающих проект плюшек.

пятница, 4 января 2013 г.

Django. Template tag с закрытием

Собственно, в джанге в родном шаблонизаторе есть возможность писать свои теги и фильтры.

А вот у меня встала задача. Есть какой-то контент, ну к примеру формируется он так:
 # some_template.html  ;

<div class="head-ev-bg">
    <div class="head-ev-numb">
        <div class="ev-character ev-{{ number }}"></div>
    </div>
    <div class="head-ev-l"></div><div class="head-ev-r"></div>
    <div><h4 class="titlec">{{ title }}</h4></div>
</div>
<div class="ev-cont">
    <div class="ev-cont-bg">
    {{ content }}
    </div>
    <div class="ev-cont-bt"></div>
</div>


Ну вроде бы ничего так. Надо передать какое-то число, заголовок и контент.
Беда в том, что контент - это ещё куча html кода. И вот выше изложенная последовательность повторяется пару раз на странице. Обычный тег должен проглотить контент через параметр.
К примеру:
{% some_tag "number" "title" "content" %}
Всё было бы не плохо, если бы не листинг в две страницы в этом поле "content" ))) Как-то сразу отпадает желание.
Вот и подумалось мне, ну раз есть {% for %} {% endfor %}, то наверное можно так же написать свой собственный тег, тег с закрытием.
А для меня он будет выглядеть так:
{% some_tag "number" "title" %}
content
{% endsome_tag %}

Красиво? Ну вот и я так считаю. Что же, а теперь листинг кода.

from django import template

register = template.Library()

class SomeTagNode(template.Node):
    def __init__(self, nodelist, id, title):
        self.nodelist = nodelist
        self.id = id
        self.title = title

    def render(self, context):
        output = self.nodelist.render(context) # выдаст то, что было между открывающим тегом и закрывающим
        t = template.loader.get_template('some_template.html')
        c = template.Context({ 'number': self.id, 'title': self.title, 'content': output})
        return t.render(c) # формируем шаблон и выводим

def do_sometag(parser, token):
# parser - структура шаблона
# token - то, что передадим тегу в качестве параметров
    try:
        tag_name, id, title = token.split_contents()
    except ValueError:
# Для меня важно получить два параметра
        raise template.TemplateSyntaxError("%r tag requires exactly two arguments" % token.contents.split()[0])
# Проверяю, что бы каждый параметр шёл в кавычках
    if not (id[0] == id[-1] and id[0] in ('"', "'")):
        raise template.TemplateSyntaxError("%r tag's first argument should be in quotes" % tag_name)

    if not (title[0] == title[-1] and title[0] in ('"', "'")):
        raise template.TemplateSyntaxError("%r tag's second argument should be in quotes" % tag_name)

    nodelist = parser.parse(('endsometag',)) # построить структуру до заданного тега
    parser.delete_first_token() 
    return SomeTagNode(nodelist, id[1:-1], title[1:-1]) # отправим струкуру

register.tag('sometag, do_sometag) # загрузим наше представление тега в общую библиотеку


P.S.: Я ничего не сделал того, что не описано в документаци к джанго. Даже более, это есть практически в таком виде в самой документации. Но, почитать и понять придется.
P.P.S.: Для меня это было в качестве упражнения и не более, т.к. html структура была вот такой, какой я её здесь описал. Но, с другой стороны, теперь мне, если  придется поменять структуру, то я буду делать это в одном шаблоне, а не в десяти местах в разных шаблонах, что радует.