вторник, 24 ноября 2009 г.

Ошибки и правила оценки программных проектов

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

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

http://www.ozon.ru/context/detail/id/3115179/

Но кому лень искать, покупать или читать - на Хабре встретился кратенький пост, с пересказом - http://habrahabr.ru/blogs/pm/75903/

UPD
Встретилось еще близкое к теме - “Статистические ошибки планирования”. Очень интересное выступление, с примерами, "на пальцах".

среда, 18 ноября 2009 г.

Как нужно делать выступления

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

Стянуто у http://soldatenko.livejournal.com/74040.html
Перевод (удобно открыть в отдельном окне и туда подглядывать) - http://www.subguru.ru/2008/01/blog-post_01.html



Кусочки:

Не бойся поляризовать людей (polarize people). Классные продукты поляризуют людей. Если вы попытаетесь создать продукт, который понравится всем группам клиентов – от 18 до 25, от 25 до 35, от 35 до 50, от 50 до 75, от 75 до смерти – если вы попытаетесь создать такой продукт, получится посредственность.


Большинство предпринимателей верит в то, что им в первую очередь нужно работать на уровне топ-менеджмента. «Мне нужно говорить с исполнительными директорами, директорами по развитию, президентами и председателями компаний (CIO, CTO, CMO или CEO)». За время своей карьеры я понял, что чем выше ты поднимаешься в большой организации, тем разреженнее воздух. А чем разреженнее воздух, тем меньше он дает возможности для поддержания разумной жизни.


Третий важный момент - найти соратников. Концепцию «предпринимателя-одиночки» сильно переоценивают, она неверна. У Стива Джобса был Стив Возняк. У Билла Гейтса – Стив Балмер. Вам нужны соратники – люди, которые будут вас дополнять. Если ты великий инженер, тебе потребуется великий специалист по маркетингу. Если ты совмещаешь в себе то и другое, тебе нужен будет операционный менеджер. Если ты гениальный провидец – тебе понадобится присмотр кого-нибудь взрослого.


...правило 10/20/30. В вашей презентации должно быть 10 слайдов.... И эти десять слайдов вы должны представить за 20 минут. ... И самый маленький размер шрифта, который вы можете использовать в презентации – 30.

четверг, 15 октября 2009 г.

Риски использования распределенных систем управления версиями

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

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

Встретилось вот еще пара интересных статей на эту тему:

Риски распределенного контроля версий
Контроль версий и «правило 80 процентов»

Вкратце: с централизованной системой, людей принуждают взаимодействовать и просматривать работу друг друга; с децентрализованной системой, поведение по умолчанию состоит в скрытом ветвлении проекта каждым разработчиком.

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

Да, я знаю, что DVCS может имитировать работу централизованной системы; но поведение по-умолчанию имеет значение.

А поведение по-умолчанию — «ветвить», а не сотрудничать!

Это поощряет людей забираться в пещеры и кодить там объемные доработки, а затем «сбрасывать» эти «кодовые бомбы» на своих товарищей, причем до момента «сброса» код не может быть кем-либо проверен.

Да, правильные практики возможны с DVCS, но они не поощряются, что заставляет меня беспокоиться о будущем разработки с открытым исходным кодом...

понедельник, 5 октября 2009 г.

Про новую архитектуру Firebird - SuperClassic

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

SuperServer:
  • один процесс ОС на все соединения/базы
  • общий кеш страниц для всех баз
  • централизованный(central) менеджер блокировок
  • блокировки работают на базы, а не соединения - т.е. все операции с базой выстраиваются в одну очередь.
  • для версии <>
  • не поддерживает многопроцессорность, т.к. ОС не может распаралелить один процесс по нескольким процессорам
Classic:
  • отдельный процесс на каждое соединение с БД
  • отдельный кеш страниц на каждое соединение
  • внешний менеджер блокировок(в 2.5. он уже внутренний)
  • хорошая поддержка многопроцессорности
  • накладывает некоторые ограничения в следствие ресурсоемкости процессов, в сравнении с потоками
SuperClassic:
  • один процесс на все соединения (в перспективе - отдельный процесс на каждую базу)
  • используется пул потоков ОС для обработки запросов от соединений - т.о. каждое соединение работает в отдельном потоке управляемом ОС, а неактивные соединения не отъедают ресурсы потоков
  • централизованный менеджер блокировок, который может обрабатывать как внутренние, так и внешние обращения(одна и таже база может быть доступна как посредством СУБД из процесса А, так и через FB Embeded из процессов B, C и т.д.)
  • теоретически этот менеджер блокировок позволяет организовывать кластеризацию используя готовые распределенные движки блокировок
  • кеш страниц на соединение
  • хорошая поддержка многпроцессорности, т.к. потоки ОС легко распараллеливаются

В v3.0 планируются такие доработки:
  • общий кеш страниц на уровне базы
  • кеш подготовленных запросов
  • общий кеш метаданных

Как итог - SuperClassic это промежуточный шаг(насколько я понял изначально родившийся в RedSoft) к следующей основной архитектуре FB, появившийся в следствии крупного рефакторинга внутренностей движка.

Пока для пользователей практический выигрыш лишь в экономии на процессах и, как следствие, чуть более быстрой синхронизации. Хотя если верить документации, то совокупный выигрыш - до 15-20% на TPC-С тестах в сравнении с классиком.

Подробнее можно посмотреть в Firebird 2.5 Release Notes

UPD: Презентация от Дмитрия Еманова - Firebird 2.5 Architecture

пятница, 25 сентября 2009 г.

Динамически загружаемые bpl , их выгрузка и интерфейсы

Очевидная, но съевшая кучу времени ошибка.

Если в проекте используются динамически загружаемые/выгружаемые bpl, следует помнить, что при выгрузке информации о классах, реализованных в этих bpl в памяти не остается.

Предположим есть некий список, в котором регистрируются _интерфейсы_, имплиментирующие классы которых реализованы в динамически загружаемых bpl(к примеру в плагинах). Сам список живет в базовом приложении, которое и загружает эти пакеты.

Если оставить разрушение этих объектов на совести основного кода, что при использовании интерфейсов довольно очевидно, но делать это _после_ выгрузки bpl с кодом класса реализующего интерфейс, например в секции finalization, - будем получать маловразумительные AV.

Интерфейсы должны быть интерфейсами!

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

Есть объект, унаследованный от TComponent и поддерживающий какой-то интерфейс. Временем жизни этого объекта управляет некая фабрика, честно убивающая его при закрытии приложения вручную, как обычный объект - т.е. посредством вызова Free.

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

А при завершении работы - фабрика все честно чистит и умирает сама, выполняется весь пользовательский код. И начинают финализироваться модули, обнуляя интерфейсы и соотв. дергая TComponent._Release у давно умершего объекта...

Обнаружить сию неприятность удалось только благодаря FastMM, который заполняет память под разрушенными объектами по специфическому шаблону:

Q: My program used to work fine, but if I enable "FullDebugMode" and run it I get an access violation at address $8080xxxx. Why?
A: You are attempting to access properties of a freed object. When you free a block in "FullDebugMode", FastMM fills the freed memory area with a pattern of $80 bytes. If there were any pointers, long strings or object references inside the freed object they will now point to $80808080 which is in a reserved address space.

вторник, 15 сентября 2009 г.

Все плохое в FB от Windows :)

Проглядывая презентацию Алексея Пешкова о прошлом, настоящем и будущем безопасности в Firebird наткнулся на интересную информацию:

Тот громкий "зашитый" пароль politically/correct был введен для коннекта сервером к своей базе паролей, которая в свою очередь была введена для порта сервера на .... Win3.X в 92-93г., у которой в то время не было свой подсистемы пользователей.

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

понедельник, 14 сентября 2009 г.

Firebird и база на SSD диске

Встретилось в fb-devel интересное сообщение, о переходе на SSD диск. Если кратко - то значительно увеличилась производительность при большой загрузке дисковой подсистемы, когда основное время тратится на позиционирование головок диска при большом потоке конкурентных обращений.

"Если на обычном 5-то рейде в таких ситуация(более 1000 коннектов) ответ ждали до минуты, то в ssd это время оставалось константным, порядка 4сек."

Естественно не для всяких систем это будет верно, но все же...


Hi Pays,

I can't give you exact figures, but we switched

from
HP 585 4 processor AMD Opteron 850/16GB with raid5 HP SCSI Ultra320 15krpm 8
disk array for the DB

to
HP 385 2 x quad core AMD Opteron 2384 and an FusionIO IODrive, an 80GB SSD
formatted as 40GB so it can continously prepare the remaining 40GB for write
operations which gives it a performance advantage.

The performance gain was noticable. We are btw running FB2.1 classic, AMD 2
x quad core/20GB ram. A "big" query taking around 8 seconds on the SCSI took
only 4 seconds on the FusionIO. Thus the pure performance gain was just
around 2 times faster. It was a query primarily putting load on the disks,
not the CPU, so I guess the new and better server hardware didn't influence
the result too much.

But the really interesting part comes under higher load! As there is no
latency in positioning the heads on a SSD, it really doesn't seem to care
about number of connections (at least not in our case). So where the SCSI
raid dramatically dropped performance and went to around one minute for the
above query during heavy load (>1000 connections), the SSD still answered in
4 seconds. That makes all the difference to us - and not least our users :)

I hope you can use the above informations in your research. Only
disadvantage for the IODrive, at least for now, is that it isn't mounted
until the server loads the drivers for it. So you can't really boot from it.

Kind regards

Poul Dige
Tabulex

вторник, 8 сентября 2009 г.

Vista и перенаправление(виртуализация) файловой системы

Когда-то, читая замечательный блог Not a kernel guy, встретил у него описание, как 64-х битные версии новых Windows умеют перенаправлять обращения к реестру и файловой системе.

Почитал, удивился и забыл - в тех системах, которые приходилось писать самому или делалось все так, как хочет Майкрософт(пишем только в профиль пользователя), или намеренно указывалась необходимость иметь права на запись в каталог инсталяции для упрощения системы обновлений.

Но впоследнем проекте получилось сполна опробовать красоту решения от MS - пока у пользователя включен UAC, все обращения на запись в ProgramFiles перенаправляются в профиль пользователя(в нашем случае копировалась 400Мб база, лежащая "под" приложением). Казалось бы, сами себе злобные буратины, что не выполняем рекомендации MS. Но раз уж не выполняем, то МС само заботится о нас и на первый взгляд все ок.

До тех пор, пока пользователь, как это принято, не отключает этот UAC к чертовой матери, и оказывается перед девственно чистой БД :)

Одним из способов решения - создание манифеста, в котором указать необходимый приложению объем прав. Хотя и там, с кешированием этих манифестов и прав весело - единожды запустив приложение информация о необходимых ему правах где-то сохраняется, и как ее сбросить я пока не нашел.

Про UAC - http://msdn.microsoft.com/en-us/library/bb756960.aspx
Про манифест - http://msdn.microsoft.com/en-us/library/bb756929.aspx

вторник, 14 июля 2009 г.

Эмуляция сети с высокой латентностью

Когда-то нужно было для тестов:

It simulate network latency in Linux using Netem. With the tc utility, we can add a delay for outbound traffic. Since I did it for lo interface, it happens that it works for in/out traffic. I set delay to 100ms (that is more or less a value I found doing it in the internet with my horrible Telefonica speedy connection), using this command:
$ sudo tc qdisc add dev lo root handle 1:0 netem delay 100ms

To later remove the delay, the command is:
$ sudo tc qdisc del dev lo root

Источник

вторник, 19 мая 2009 г.

Мысли о роли ТЗ в программном проекте

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

Основная задача ТЗ в программном проекте - не фиксация объема работ, не защита от переработки, не инструмент "заморозки" требований. Нет, это просто возможность заказчику(пусть зачастую и при помощи разработчиков) подумать над тем, что он вообще хочет.

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

Другими словами ТЗ - это "рыба" проекта, которую можно делать сразу, просто и очень дешево менять. А письменный он должен быть потому, что иначе мозг может и не включиться. П%;:ть, как грится, не мешки ворочать.


PS термин "техническое задание" спорный, но выбран как самый простой, для обобщения

PPS да, agile конечно штука, но не каждый заказчик готов по нему работать

UPD: мысль оказалась далеко не новой - Джоэль о том же пишет.

четверг, 19 марта 2009 г.

Указатель на метод интерфейса

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

Но реальность оказалась не столь оптимистичной - на текущий момент Delphi такого функционала не поддерживает:
  • http://groups.google.com.ua/group/borland.public.delphi.objectpascal/browse_thread/thread/4c5dcb094b82522f?pli=1
  • http://qc.embarcadero.com/wc/qcmain.aspx?d=941 (а судя по датам и не будет поддерживать)
Самому раньше в таком функционале необходимости не было - проще передавать весь интерфейс, но если необходимо взаимодействие с чужим кодом, где могут требовать именно указатель на функцию, то прийдется изобретать не очень стройные решения:
  • метод в интерфейсе напрямую возвращающий адрес метода объекта
IAnIntf = interface
function GetPointerToProc: TAnObjectProc:
end
  • объект-обертку над интерфейсом
TWrapObj = class
private
AnIntf: ITheIntf;
protected
procedure AnProc(const Value: string);
end;

procedure TWrapObj.AnProc(const Value: string);
begin
AnIntf.AnProc(Value);
end;
  • возможно как-то можно будет выкрутиться через анонимные функции? нельзя, ибо
    TAnProc = procedure (S: string) of object;
    TAnProc2 = reference to procedure (S: string);
    это разные типы
Хотя и в реализации проблем более чем - вычислять статический адрес, на этапе компиляции, для такого указателя не получится, т.к. один и тот же интерфейс может реализовываться разными объектами.

> Still I think making (procedure of object) and (procedure of Interface) equivalent
> typeswould be the better solution.

Like I said, the semantics for the compiler would be quite different, so
it would make sense to make them different types (even if both
represented internally by a TMethod). Actually, if the interface
instance variable is nil, it is impossible to get the method address.
This is not a problem for objects, since there the static address is
taken.

пятница, 6 февраля 2009 г.

Создание индексов "на ходу" в Firebird

>> А вот с индексами как? Как насчет CREATE INDEX "на ходу"? Да еще и на
>> таблицу, с которой постоянная работа на UPDATE идет?
>
> Если 2.0 и старее, то получишь рассинхронизированный с таблицей индекс.
> Если 2.1 и новее, то все апдейты будут курить, пока индекс не будет создан.

- DDL тр-ция должна быть wait. Иначе - создание индекса обломится с большой вероятностью.
- Отпрепарированные запросы не увидят новый индекс. Это и процедур, и триггеров касается.

> и создание индексов, и ALITER INDEX INACTIVE делал на ходу...
> и что требуется теперь сделать, что бы за БД не переживать?

gfix -v -f

(с) Dmitry Yemanov, Хорсун Влад

пятница, 9 января 2009 г.

Borland, умолчания и поддержка старого

Компания меняет не только названия, но и простым разработчикам не дает скучать.
Вводная - при неизменных внешних условиях перестала выполняться сборка релиза из командной строки при переходе с 2007 на 2009 - упорно попадал туда код дебага. В то время как из среды - все ок.

Проведенное в два этапа(первый был еще на 2007 и текущей проблемы не касался см.) расследование показало, что:

- в импортируемом проектами файле CodeGear.Delphi.Targets дефолтный таргет изменен с Build на Make. А последний при смене конфигурации Debug|Release не пересобирает dcu

- группы проектов, в отличии от проектов, не обновляются до соотв. версии и импортируют $(MSBuildBinPath)\Borland.Group.Targets, который существует только при инсталяции 2007(или когда там msbuild прикрутили?)

- таргет Build для группы проектов не задает таргет для конечных проектов(т.е. используется умолчательный, который теперь Make, да)

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

Delphi 2009 и приведение к PAnsiString

Часть winapi функций требуют передачи себе в кач-ве параметров структур с PAnsiChar строками (например mapi). В предыдущих версиях приведение строк посредством PChar(SomeString) работало, используя область памяти выделенную под SomeString, а в 2009 результат PAnsiString(AnsiString(SomeString)), уже как вычисление обычной строки из юникодной, размещается в локальной области памяти, что чревато тем, что старый код может перестать работать на, казалось бы, ровном месте (хотя конечно прямое приведение к pchar тоже имеет кучу особенностей).

Например код приведенный ниже возвращает разные результаты на 2007 и 2009 Делфи

program array_error_test;

{$APPTYPE CONSOLE}

uses
SysUtils,
StrUtils,
Classes;

procedure DoMain;
const
Count = 5;

type
RecType = record
AnString: PAnsiChar;
end;
var
RecArr: array of RecType;
I: Integer;
SomeStrings: TStringList;
begin

SetLength(RecArr, Count);

SomeStrings := TStringList.Create;
try
for I := 0 to Length(RecArr) - 1 do
begin
SomeStrings.Add(DupeString(IntToStr(I), 10));
RecArr[I].AnString := PAnsiChar(AnsiString(SomeStrings[I]));
end;

for I := 0 to Length(RecArr) - 1 do
WriteLn(RecArr[I].AnString);
finally
SomeStrings.Free;
end;
end;

begin
DoMain;
ReadLn;
end.

четверг, 8 января 2009 г.

Delphi 2009 и InternetQueryOption

Переносится в одном из проектов код на 2009 Делфи и соотвественно кушаются все прелести первопроходчества.

Для получения адреса прокси сервера пользовалась функция InternetQueryOption. После сборки в 2009 стала она возвращать мусор. Ничего криминального замечено не было, замена на InternetQueryOptionW не помогала.

Решение нашлось в
http://akirabbq.spaces.live.com/blog/cns!CEB8A04DC43BCEE9!264.entry
кто виноват не совсем понятно, но неприятно :(

По сути - в структуре INTERNET_PROXY_INFO lpszProxy должно быть не LPCTSTR(которое в 2009 уже PWideChar), а просто LPCSTR, хотя в исходных сишных заголовках она объявлена как LPCTSTR.

Решить проблему можно создав необходимую структуру у себя.