Сегодня я решил разобрать коробку с книгами, оставшуюся после последнего переезда, и наткнулся на эту книгу.
Очень рекомендую её всем, кто интересуется методологиями разработки ПО, коммуникацией внутри команды и задумывается о применимости того или иного подхода к своему проекту.
Автор описывает 7 принципов построения методологий, вот некоторые из них:
- Общение лицом к лицу - самый дешевый и быстрый способ обмена информацией.
- Избыточная “тяжесть” методологии стоит дорого.
- Более многочисленные команды требуют более “тяжелых” методологий.
- БОльшая формальность подходит для проектов с бОльшей критичностью.
- Возрастание обратной связи и коммуникации сокращает потребность в промежуточных конечных продуктах.
Также в книге подробно рассмотрены различные виды обмена информацией между участниками проекта. Особенно интересными мне показались мысли автора об “осмотической коммуникации” - косвенном получении информации из разговоров коллег (как фактической информации, так и информации вида “ага, Коля знает про А, нужно спросит его при случае”).
Ну, думаю я достаточно рассказал, чтобы вас заинтересовать
P.S: Последнее время я испытываю острый недостаток интересного чтива. Интересуют как технические книги о подходах, паттернах и технологиях, так и бизнес-литература и книги по менеджменту. Интересуют подборки must-have книг. Можно ссылками на соц.сервисах, как например на http://moikrug.ru/profile/books/.
Выделяем поля из логов nginx на python
01.01.2010
Для анализа логов 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
Ошибка при работе с pycurl
17.10.2009
Сегодня мне окончательно надоело пользоваться кривейшим сайтом локальной сети моего провайдера. Основное назначение сайта - публикация ftp-ссылок на фильмы, которые заливаются на несколько локальных серверов. Я задумал написать небольшой индексатор, который обойдет папки у ftp и соберет мне имена файлов.
Для решения этой задачи наиболее адекватным инструментом мне показался CURL. За двадцать минут я написал 70 строк кода на питоне, и отправил сканер гулять по серверам. Информация начала литься в индекс, но счастья не случилось. Сканер начал намертво зависать после нескольких минут работы.
Ошибка оказалась дурацкой и слегка неожиданной. В цикле обхода я для каждого запроса создавал новый объект PyCURL, и потом чистил его. Конечно, это все накладные расходы, но в моей задаче мне на них был наплевать. Но не тут то было. После создания многих экземпляров, при их чистке CURL вешает процесс.
Решение простое - создает один объект PyCURL, и работаем только с ним, через pycurl.setopt меняя параметры и много раз вызывая метод perform().
Пусть у нас есть несколько условий, которые могут выполнятся одновременно. И есть несколько ветвей алгоритма, которые нужно выполнить в зависимости от результатов проверок.

Для примера рассмотрим такую задачу. Мы разрабатываем веб-приложение с графическим интерфейсом, в котором можно рисовать прямоугольники. Размер прямоугольника можно менять “потянув” за край или угол. Нужно, в зависимости от положения мыши относительно прямоугольника, изменить курсор мыши так, чтобы пользователю было понятно, как можно изменить размер прямоугольника.
Борьба с порно-спамом
24.12.2008
За последние несколько месяцев поток порно-спама перешел все мыслимые и не мыслимые границы. Akismet с ним не плохо справляется, но количество комментариев так велико, что мне уже лень очищать от них очередь спама.
В Wordpress есть вполне действенный механизм “черных списков”, но, к сожалению, по-умолчанию комментарий, не прошедший через проверку, помечается как “спам”. Поэтому я быстренько соорудил небольшой плагин, который сразу отклоняет такие комментарии и не засоряет базу.
Сделал небольшое дополнение для firefox, которое форматирует rss + дополнительные поля из jira в виде небольших карточек, удобных для печати.
Буду рад предложениям и замечаниям.
Задачка для собеседования программиста, 2
17.10.2008
Задачка про базы данных, старая и не моя.
Имеется таблица, один из столбцов которой - уникальный целочисленный идентификатор. Каждый новый идентификатор получается инкрементом предыдущего значения (проще говоря - auto_increment в MySQL).
Иногда строки из этой таблицы удаляются и в последовательности идентификаторов возникает пробел. Требуется найти идентификатор, находящийся до или после первого пробела.
Небольшая иллюстрация:
| id | ... | 1 | ... | 2 | ... | 3 | ... | 5 | ... | 7 | ...
phpUnit 3.3.1. Что нового?
10.10.2008
Вчера потратил изрядно времени на восстановление работоспособности тестов, после перехода на новую версию PHPUnit - фреймворка для написания unit-тестов на php.
Изменение, которое попортило немало крови - смена интерфейса у мок-объектов, которые генерируются классом PHPUnit_Framework_MockObject_Mock. Если раньше им можно было пользоваться для генерации моков (например во вспомогагательных классах, для упрощения создания однотипных мок-объектов), то теперь наиболее корректным способом видится использование метода getMock() у TestCase. Разработчики изменили имя метода, проверяющего корректность мока с verify() на __phpunit_verify() (видимо verify() популярное название, и может пересекаться с методом тестируемого класса), тем самым поставив ручную проверку мока вне закона.
Другое изменение, доставившое много хлопот, связанно с backup / restore глобальных переменных между тестами. Разработчики PHPUnit внесли правки, чтобы обойти баг php, связанный с десериализацией объектов. К сожалению, новый код не рассматривает возможность, что суперглобальные массивы могут содержать скалярные величины. Конечно, в реальности такого быть не должно, но в нескольких тестах, проверяющих работу с POST и GET тестовые значения были скалярными.
Задачка для собеседования программиста
07.09.2008
Недавно начал читать SICP (Structure and Interpretation of Computer Programs) в русском переводе. Надо сказать весьма приятная книга, заставляет шевелиться мозги, что уже само по себе полезно. Найти pdf с русским переводом sicp можно здесь, а в блоге Сергея Хенкина - обсуждение решений задач из книги и множество полезных сопутсвующих материалов.
Первые главы навели меня на мысли о простой задачке на собеседовании:
В чем разница между:
// выполняем логическую операцию
function mOr($a, $b) {
return $a || $b;
}
mOr([Операнд1], [Операнд2])
и
// и тут тоже выполняем логическую операцию
[Операнд1] || [Операнд2];
UPD: немного поправил условие задачи
