IT Blog

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

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

Автор описывает 7 принципов построения методологий, вот некоторые из них:

  • Общение лицом к лицу - самый дешевый и быстрый способ обмена информацией.
  • Избыточная “тяжесть” методологии стоит дорого.
  • Более многочисленные команды требуют более “тяжелых” методологий.
  • БОльшая формальность подходит для проектов с бОльшей критичностью.
  • Возрастание обратной связи и коммуникации сокращает потребность в промежуточных конечных продуктах.


Также в книге подробно рассмотрены различные виды обмена информацией между участниками проекта. Особенно интересными мне показались мысли автора об “осмотической коммуникации” - косвенном получении информации из разговоров коллег (как фактической информации, так и информации вида “ага, Коля знает про А, нужно спросит его при случае”).

Ну, думаю я достаточно рассказал, чтобы вас заинтересовать :)

P.S: Последнее время я испытываю острый недостаток интересного чтива. Интересуют как технические книги о подходах, паттернах и технологиях, так и бизнес-литература и книги по менеджменту. Интересуют подборки must-have книг. Можно ссылками на соц.сервисах, как например на http://moikrug.ru/profile/books/.

Для анализа логов nginx мне понадобилось регулярное выражение, которое бы корректно разделяло запись на отдельные поля. Немного по-колдовав над логом, я понял, что наилучший способ разобраться в формате лога - это выцепить его из конфигурации сервера.

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

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

import re

# формат из конфигурации nginx
FORMAT = '$remote_addr - $remote_user [$time_local] "$request" $status' + \
    ' $bytes_sent "$http_referer"' + \
    ' "$http_user_agent" "$gzip_ratio" "$cookie" $hostname'

# выражение, описывающее переменную в конфигурации логов nginx
TOKEN = '\$([a-z\_]+)'

# возможные скобки и кавычки вокруг переменных в конфигурации логов nginx
POSSIBLE_QUOTES = ('[]', '"', '\'')

def get_matcher(format):
    quotes = re.escape(''.join(POSSIBLE_QUOTES))

    pat = format
    for token in re.findall(TOKEN, format):
        res = re.search('([%s]?)(\$%s)([%s]?)' % \
            (quotes, token, quotes), format).groups()
        if not res:
            continue
        elif res[0] <> res[2]:
            tq = res[0] + res[2]
            tq_escaped = '\%s|\%s' % (res[0], res[2])
        else:
            tq = res[0]
            tq_escaped = '\%s' % res[0]

        tq = re.escape(tq)
        tq_escaped = re.escape(tq_escaped)

        if not tq:
            ftoken = '\$%s' % (token)
            ptoken = '(?P<' + token + '>[^\ ]*)'
        else:
            ftoken = '[%s]\$%s[%s]' % (tq, token, tq)
            ptoken = '[%s](?P<%s>(?:%s|[^%s])*)[%s]' % (tq, token, tq_escaped, tq, tq)

        pat = re.sub(ftoken, ptoken, pat)

    patc = re.compile(pat)
    def matcher(line):
        return patc.match(line)
    return matcher

def main():
    f = file('access_log')
    matcher = get_matcher(FORMAT)
    for line in f:
        print matcher(line).groupdict()

Возможно кому-нибудь будет полезным

UPD: Немного поправил код, чтобы он корректно работал с записями, в которых встречаются поля вида: “some text with escaped \” qoute”

К примеру, хочется иметь в объекте модели поле, дата которого будет задаваться при сохранении объекта.

Казалось бы, вот такой код будет логичным:

class MyModel(models.Model):
    time = models.DateTimeField(default = datetime.now())

Однако,  в приведенном выше примере - все создаваемые объекты будут иметь дату создания в памяти класса MyModel.

Правильным будет указать в качестве значения по-молчанию функцию, которая будет вызываться каждый раз, при сохранении объекта:

class MyModel(models.Model):
     time = models.DateTimeField(default = datetime.now)

upd:
Как подсказывает товарищ overplumbum, можно добавить в конструктор models.DateTimeField() auto_now=True - http://ff.im/bQyQO

Сегодня мне окончательно надоело пользоваться кривейшим сайтом локальной сети моего провайдера. Основное назначение сайта - публикация ftp-ссылок на фильмы, которые заливаются на несколько локальных серверов. Я задумал написать небольшой индексатор, который обойдет папки у ftp и соберет мне имена файлов.

Для решения этой задачи наиболее адекватным инструментом мне показался CURL. За двадцать минут я написал 70 строк кода на питоне, и отправил сканер гулять по серверам. Информация начала литься в индекс, но счастья не случилось.  Сканер начал намертво зависать после нескольких минут работы.

Ошибка оказалась дурацкой и слегка неожиданной. В цикле обхода я для каждого запроса создавал новый объект PyCURL, и потом чистил его. Конечно,  это все накладные расходы, но в моей задаче мне на них был наплевать. Но не тут то было.  После создания многих экземпляров, при их чистке CURL вешает процесс.

Решение простое - создает один объект PyCURL, и работаем только с ним, через pycurl.setopt меняя параметры и много раз вызывая метод perform().

Пусть у нас есть несколько условий, которые могут выполнятся одновременно. И есть несколько ветвей алгоритма, которые нужно выполнить в зависимости от результатов проверок.

Для примера рассмотрим такую задачу. Мы разрабатываем веб-приложение с графическим интерфейсом, в котором можно рисовать прямоугольники. Размер прямоугольника можно менять “потянув” за край или угол. Нужно, в зависимости от положения мыши относительно прямоугольника, изменить курсор мыши так, чтобы пользователю было понятно, как можно изменить размер прямоугольника.

Читать полностью »

За последние несколько месяцев поток порно-спама перешел все мыслимые и не мыслимые границы. Akismet с ним не плохо справляется, но количество комментариев так велико, что мне уже лень очищать от них очередь спама.

В Wordpress есть вполне действенный механизм “черных списков”, но, к сожалению, по-умолчанию комментарий, не прошедший через проверку, помечается как “спам”. Поэтому я быстренько соорудил небольшой плагин, который сразу отклоняет такие комментарии и не засоряет базу.

Сделал небольшое дополнение для firefox, которое форматирует rss + дополнительные поля из jira в виде небольших карточек, удобных для печати.

Буду рад предложениям и замечаниям.

Задачка про базы данных, старая и не моя.

Имеется таблица, один из столбцов которой - уникальный целочисленный идентификатор. Каждый новый идентификатор получается инкрементом предыдущего значения (проще говоря - auto_increment в MySQL).

Иногда строки из этой таблицы удаляются и в последовательности идентификаторов возникает пробел. Требуется найти идентификатор, находящийся до или после первого пробела.

Небольшая иллюстрация:

| id | ...
| 1 | ...
| 2 | ...
| 3 | ...
| 5 | ...
| 7 | ...

PhpUnit Вчера потратил изрядно времени на восстановление работоспособности тестов, после перехода на новую версию PHPUnit - фреймворка для написания unit-тестов на php.

Изменение, которое попортило немало крови - смена интерфейса у мок-объектов, которые генерируются классом PHPUnit_Framework_MockObject_Mock. Если раньше им можно было пользоваться для генерации моков (например во вспомогагательных классах, для упрощения создания однотипных мок-объектов), то теперь наиболее корректным способом видится использование метода getMock() у TestCase. Разработчики изменили имя метода, проверяющего корректность мока с verify() на __phpunit_verify() (видимо verify() популярное название, и может пересекаться с методом тестируемого класса), тем самым поставив ручную проверку мока вне закона.

Другое изменение, доставившое много хлопот, связанно с backup / restore глобальных переменных между тестами. Разработчики PHPUnit внесли правки, чтобы обойти баг php, связанный с десериализацией объектов. К сожалению, новый код не рассматривает возможность, что суперглобальные массивы могут содержать скалярные величины. Конечно, в реальности такого быть не должно, но в нескольких тестах, проверяющих работу с POST и GET тестовые значения были скалярными.

Недавно начал читать SICP (Structure and Interpretation of Computer Programs) в русском переводе. Надо сказать весьма приятная книга, заставляет шевелиться мозги, что уже само по себе полезно. Найти pdf с русским переводом sicp можно здесь, а в блоге Сергея Хенкина - обсуждение решений задач из книги и множество полезных сопутсвующих материалов.

Первые главы навели меня на мысли о простой задачке на собеседовании:

В чем разница между:


// выполняем логическую операцию
function mOr($a, $b) {
    return $a || $b;
}

mOr([Операнд1], [Операнд2])

и


// и тут тоже выполняем логическую операцию
[Операнд1] || [Операнд2];

UPD: немного поправил условие задачи