Показаны сообщения с ярлыком мысли. Показать все сообщения
Показаны сообщения с ярлыком мысли. Показать все сообщения

среда, 7 сентября 2011 г.

Если не strcmp...

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

Давайте посмотрим на следующий код, который я для примера выдрал из ядра linux:
if (!strncmp(name, p, k) && p[k] == '=') {
 	p += k + 1;
	...

вторник, 5 апреля 2011 г.

Понять ветвления

Централизованные системы контроля приучили нас к единому репозиторию. Ветвления осуществляются между каталогами, или депотами, как их не назови. Ну CVS мы за систему контроля (поддерживающую ветвления) вообще не считаем. Во всех остальных, насколько я знаю - деревья.

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

Ветвления в бранче

Все-таки это зло.

Mercurial позволяет двум разработчикам независимо сделать push, что приведет к тому что в бранче на сервере получится ветвление. Но что делать третьему разработчику, который это вытягивает? Заниматься слиянием? Да он вообще не в курсе что там куда.

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

четверг, 26 августа 2010 г.

Допустимая публичность

В C++ традиционным считается использование public методов в начале описания. И сразу слайды:
class foo {
public:
        foo();
        void doSomething();
private:
        ...
};
И это логично. При чтении кода первое, что мы видим, это доступные нам рычаги для воздействия на класс, его интерфейс. Для тех, кто дочитал до private, становятся известны некоторые подробности реализации. Но речь не о том...

среда, 18 августа 2010 г.

Назад, в будущее...

Закоммитил не функционирующие изменения. Причем привык сразу делать hg push, чтобы не забыть это сделать позже. И только потом выяснил что все сломалось, надо выкинуть эти изменения и начать сначала. Но меркуриал немного разочаровал.

hg rollback можно делать только один раз и только до того как ты сделал push, при этом ревизия совершенно исчезает.

hg backout позволяет сделать откат, при этом добавляя еще одну ревизию.

Записал в дневнике: Достаточно переместить хед на одну ревизию назад и дальше пойти уже от нее. Тот хед - пусть болтается как тупиковая ветвь. Вполне естественно. Хотя может быть я что-то не понимаю.

понедельник, 16 августа 2010 г.

Из песни слова не выкинешь

... Но их можно легко забыть.

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

И вот я подумал, чтобы не лазить каждый раз по интернету в поисках нужной песни, все песни нужно собрать в одну базу данных!

пятница, 25 июня 2010 г.

Операторные скобки, египетские и не очень

У нас в проекте не существует Coding Style. Это конечно плохо, но тут вопрос программистского самосознания о том, что считать правильным, а что никогда не применять, потому что плохо.

Вот один из свежих конфликтов связан с операторными скобками для функций.

В коде я предпочитаю использовать египетские скобки, потому что они экономят размер кода по вертикали. Это ведь не справедливо, что стандартный экран имеет 80 символов в ширину и только 25 строк по высоте. :) 80 символов мне хватает почти всегда.

понедельник, 17 мая 2010 г.

Раскладка для телефона

Прочитал статью "Улучшенная раскладка для телефона", задумался...

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

И тут меня осенило...

среда, 3 июня 2009 г.

CVCS мертв?

Было время, когда никто не слышал про бранчи. Собственно и система контроля была одна - cvs. Нет две, еще был rcs, но это помоему совсем уж дедушка систем контроля версий.

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

Несколько дней назад упал savannah.gnu.org. Вследствии отказа RAID-массива содержимое проектных баз было безвозвратно утеряно. Последний нормальный бекап - месячной давности (sic!). Какой же у них рейд, если всеравно все рухнуло?

И вот, бедные владельцы проектов, которых угораздило хранить свои проекты в cvs/svn вынуждены по крохам восстанавливать содержимое баз (буквально с помощью сообщества).

И вот после этого подумаешь - всетаки умные люди не зря придумали DVCS? Скорее бы уже google code поднял меркуриал, я мигрирую.

Собственно для меня история проекта имеет достаточно незначительную ценность. Я просто не знаю зачем она мне может понадобиться. Но прикольно то, что с 2002 года sourceforge бережно хранит мою базу. И только.

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

Ценность бранчей пока еще ясна не всем, возможно по причине использования устаревших средств, которые с этими самыми бранчами не особо дружат. Я вот точно не знаю, последние версии SourceSafe научились делать бранчи? Perforce например делает вид что умеет это делать, но при этом историю теряет. То есть новый бранч - новая история. И на вопрос из предыдущего абзаца ответить уже не удается.

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

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

Кроме того я привык вносить изменения понемногу, мне просто жизненно необходима собственная база, из которой я мог бы одним чейнджсетом все перенести в базу perforce. Очень хочется такую систему контроля (конечно распределенную), которая умела бы оперировать с чужеродными репозиториями, как со своими. Многого хочу?

А savannah.gnu.org конечно круто опозорился. Все срочно переходят на hg/git на других площадках.

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

Хронический аудиал

Что касается женщин, то это чувство сугубо интимное...


Есть некоторые идеомы, считающиеся хорошими. Например считается правильным писать константную часть слева в условии, для того чтобы на операцию '=' вместо '==' ругался компилятор а не конечный пользователь.
if (MIN_ELEMENTS == i) ...
Я долго не мог понять почему мне это так не нравится, и наконец сформулировал для себя ответ на этот вопрос.

Писать так в частности рекоммендует Стив Макконел (Steve McConnell) в книге "Совершенный код". Там же рекоммендуется упорядочивании аргументы в соответствии со значениями на числовой прямой.
if (MIN_ELEMENTS <= i && i <= MAX_ELEMENTS) ...
Очень похожая ситуация, хотя меня она коробит меньше.

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

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

Кроме того в предыдущей строке мы вероятно работали с i, почему в условии во главу угла возводится совсем другая сущность? А почему собственно мне кажется что первый идентификатор в выражении возведен во главу угла?
i равно чему-то; если i равно MAX_ELEMENTS...
Все последовательно и логично. Но это если код читать... Если воспринимать код целостно, то, возможно, все воспринимается несколько иначе.

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

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

Я конечно такой человек, что никогда не бываю полностью довольным существующим положением вещей. Но мне бы очень не понравилось, если бы подобные идеомы были бы внесены в соглашение о кодировании. Слишком индивидуальные это вещи.

PS: Новогодние праздники сильно выбивают из колеи. Ленишься и ничего не хочется делать. Приходится себя заставлять, ну хоть сегодня напиши хоть что нибудь. :)

вторник, 30 сентября 2008 г.

Революции нужны?

Я сторонник эволюционного подхода. То есть я верю что любая программа может планомерно мутировать куда нужно. При условии, что совместимость со всем прошлым не стоит как задача. То есть я не отрицаю частичную совместимость. Например KDE 4.0, 4.1, 4.2 должны быть совместимы между собой. Но нету никакой необходимости поддеживать запуск приложений 10-ти летней давности. Это нужно только гнусным проприетарщикам. :)

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

Бесспорно то, что программы должны развиваться. То есть, новый функционал неизбежно появляется, если программа конечно не умерла :). С появлением нового функционала старый функционал должен отмирать, и исключаться.

Это в идеале. В реальности, особенно в мире свободного ПО, активная разработка зачастую скатываеся к наращиванию функционала. А поскольку все это делается еще в свободное время - на чистку времени совершенно не остается, и программа начинает прогибаться под грузом функциональности. А поскольку программа свободна - в какой-то момент это кому-то надоедает и появляется форк.

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

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

Сейчас в gentoo явная проблема например с KDE. Часть команды KDE по политическим разноглаcиям покинула проект, и стабильные пользователи gentoo еще не скоро увидят KDE4 (Кстати не понимаю, почему она не в слоте).

Такая ситуация, видимо, давно уже кому-то надоела и возник проект Exerbo, где переделана сама структура портеджей. А кроме того новые сценарии инициализаци системы и некоторые другие вкусности. Но одна беда - система еще не достаточно наполнена пакетами. Но это быстро проходит. буквально два месяца назад там еще не было даже иксов, но сейчас там уже есть kde4. Пожалуй как нибудь на досуге я посмотрю на не поближе (в плане поставить), Потому что это самый вероятный кандидат на замену моей любимой gentoo.

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

PS: А что творится в недрах Windows - я даже представить боюсь, хотя они тоже иногда забивают на совместимость, но это пока исключение. Совместимость - их хлеб. А Windows еще не умер от груза совместимости? есть ли жизнь после XP? о чем это я...

пятница, 15 августа 2008 г.

Поворчу...

Я часто плююсь на Windows. Да и на Linux иногда тоже поплевываюсь. Не то, чтобы придираюсь, просто стараюсь быть объективным. И ведь не так уж плохо все делается, но почему-то все как-то через задницу.

Не далее как сегодня наткнулся на ерунду... Ради теста стоит у меня центр сертификации, и у него истек корневой сертификат, который ради теста имел минимальный срок службы - 2 дня. И вот я открываю 'Администрировани/Центр сертификации' и получаю жизнерадостную ошибку что дескать 'Не найден сетевой путь, ошибка 0x89423423'. Полчаса ушло на то, чтобы понять что причина находится в просроченном корневом сертификате, и еще час ушел на то, чтобы научиться выпускать новый корневой сертификат. Делается это, как оказалось, тривиально: certutils -renewCert, но только с командной строки, специальной утилитой. Почему нельзя было сделать этого когда я открываю администрирование ЦС??? Ну или хотя бы сообщение об ошибке повменяемее? Я же не многого хочу! :) Хотя насчет ошибок - это вечная неиссякаемая тема.

И еще одна очень странная ерунда. Наверное я что-то не понимаю в инфраструктуре PKI. Но помоему, если у центра сертификации новый сертификат с новым ключем, то он на старом сертификате/ключе уже не должен ничего выпускать. Ан нет, ЦС от Microsoft преспокойненько выпускает новые CRL как на новом сертификате, так и на старом. Хотя может быть в этом и есть смысл?

И еще немного про Linux... mencoder у меня так и не научился кодировать видео в два прохода. Зато научился ffmpeg. Судя по всему разработчики задвинули mencoder в пользу нового и красивого ffmpeg. Хотя ИМХО всем этим программам не хватает одной очень полезной опции -quality, Ну почему я должен сам выбирать все эти усреднители и чередователи? Почему нельзя просто сказать - покачественнее или побыстрее???

entern int i;

Давно не писал что-то, а хочется. Уже накопилось несколько животрепещущих тем. Вот например про области видимости, но не переменных а строк. Ведь при детальном рассмотрении это практически одно и то же. Чем дальше от места использования мы опишем строку - тем более велика вероятность допустить ошибку.

Особенно это актуально при использовании разных форм printf. Самый правильный путь - это указывать строку непосредственно в тексте. При этом в случае с printf мы получаем возможность визуально установить соответствие аргументов и собственно строки без отрыва от данного участка кода. В других случаях это тоже может быть актуально, так как строка обычно содержит в себе какой-то смысл, который вряд ли может быть полноценно передан через какой либо идентификатор.

Но тут есть одна проблема - интернационализация. Очень хочется все строки программы легким движением заменить на соответствующие фразы другого языка. И всеравно наиболее правильным мне кажется указание строки основного языка непосредственно в тексте, пусть в специальных скобках типа QObject::tr(). В этом случае строка на основном языке видна явно, а соответствие интернациональным версиям - отдельная самостоятельная проблема, но самостоятельные проблемы решать проще, чем взаимосвязанные.

И вот тут я буду плеваться на Windows. Хотя он и не виноват вовсе, я и на Linux иногда плююсь. :) Наверное мне просто везет на ужасные проекты, которых в нашей фирме великое множество. И мне постоянно приходится их сопровождать.

LoadResourceString(IDS_STRING136,strTemp);
wsprintfA(szTm, strTemp.c_str(), from.wDay, from.wMonth, from.wYear, to.wDay, to.wMonth, to.wYear);


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

#define IDS_STRING136 136

Даже если бы у этого идентификатора было бы осмысленное имя - это всеравно ничего не дает, потому что строки нету. Да, можно полезть в ресурсы и выискивать эту строку из сотен других. Не знаю сильно ли это облегчит задачу. Это почти то же самое что описать int i в отдельном файле, может даже хуже. Могу себе представить какие сложности испытывают программисты многоязычных приложений.

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

Похожую проблему видел в одной прошивке, но там это более менее можно понять. Всетаки экономия памяти, всякое разное. Но и там теоретически можно было сделать основной язык в тексте, а дополнительные языки - подставлять при компиляции к примеру. На *nix обеспечить такую подстановку - как два байта подменить. написал скриптик в пять строк и все дела. А проект, к сожалению, был под DOS, чтобы так легко все заменить пришлось бы писать специальную программу. Там сделано просто - файл с 'ресурсами' представлял из себя большой массив, в котором производилось сопоставление идентификатора и строки. Файл для нужного языка выбирался на этапе компиляции статически. Идентификаторы, само собой были отдельно, через enum.

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

четверг, 24 июля 2008 г.

Многоблирование информации...

Копипастинг зло... все это знают. Грамотные программисты никогда не копируют код просто так. Но даже без явного копипастинга нас окружают многочисленные дублирования информации.

Где-то у меня была прикольная закладочка.. а, вот она - Copy/Paste detector. Но я хотел написать немного о другом.

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

Но даже если инклюдить сишники достаточно бессмысленно, то можно генерировать инклюды на основе сишников. :) Логика генерации нужна конечно достаточно наворочанная, но ведь компьютеры и должны работать. Вообще при постановке задачи не стоит думать о технических сложностях с реализацией. Это мешает и ограничивает воображение.

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

Ковыряюсь тут с одним старым проектом, ошибки исправляю. Хотя весь этот проект представляет из себя одну большую ошибку, которая собирается полтора часа, а функциональности в ней и на 5 минут не наберется. Хотя то, о чем я хочу написать свойственно многим проектам MSVC. Одна из ошибок очень явно это высветила - в одном месте указан старый телефон компании. Начал выяснять где... Для этого пришлось поставить InstallShield, ибо данная информация хранилась в инсталляторе. Телефон больше нигде не хранился, а вот название компании, версия продукта помимо инсталлятора хранится еще и в ресурсах каждого модуля (как я не люблю ресурсы), в диалогах в виде статического текста, иногда в самом тексте программ. Не удивительно что версии везде указаны разные, а название компании в разных формах.

Любую информацию необходимо указывать единожды. Правда я с трудом представляю как это можно сделать в условиях MSVC.

Вот собственно и все, о чем хотел написать.

четверг, 19 июня 2008 г.

Видеть больше...

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

Все мы конечно выдающиеся мыслители, но проблема в том, что человеческий мозг использует свой потенциал лишь на 5%. И имеющегося в нашем распоряжении потенциала катастрофически не хватает на все. Наша краткосрочная память может запоминать одновременно только семь объектов. Это означает лишь одно - чтобы в голову приходили хорошие мысли нужно стараться не расходовать наш мыслительный потенциал попусту. То есть, не надо думать про то, про что думать не требуется.

В былые времена оперативной памяти постоянно не хватало. Что только не придумывали люди ради этого. Помню были утилиты, позволяющие использовать видеопамять в качестве оперативки - 700 килобайт основной памяти... это было круто. Но это только цветочки.

Программисты напрягались границами сегментов и моделями памяти. Но гораздо сложнее было было программистам, программирующим ресурсоемкие приложения. Существовала когда-то технология оверлеев. Это когда толстый бинарник загружался в память по частям. Причем эта возможность поддерживалась компиляторами. Я к сожалению не знал толком как этим пользоваться, не доводилось. А сейчас это уже практически никому не интересно.

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

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

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

Прошло время, знаний C++ прибавилось, кроме того прибавилось понимания того, что имеющееся железо - это лишь средство функционирования системы. Оно не должно руководить. После чего ядро разделилось на две части. Высокоуровневая часть вообще ничего не знает о железе, а лишь формирует логику взаимодействия объектов ядра. А низкоуровневая часть могла бы по прежнему остаться на ассемблере, но она стала на си, что в принципе несущественно, все равно не переносимо.

Но после этого стало ясно что высокоуровневая часть не просто не зависит от железа, но может вообще работать практически в любых условиях (не иначе как освободившийся потенциал мозга подкинул такую идею), и я могу запускать ее абсолютно в любом окружении (ну где есть C++), естественно при наличии соответствующей этому окружению платформенной части.

Прозрения в принципе случаются в разных областях. Например вот раньше интернет файлохранилища неизбежно обзаводились зеркалами. Взять к примеру Sourceforge.Net, помню времена когда зеркал у него не было (я пользовался им с 2002 года). Но с ростом популярности опенсорс, нагрузка на сервер возросла, и назрела необходимость ее распределять, и появились зеркала. В принципе логично. Но не слишком гибко.

Но вот с некоторых пор я перешел на Google code, мне наскучил SF с его избыточным интерфейсом, люблю лаконичность, а GC необычайно лаконичен. И вот что я думаю. При всей популярности GC, при всей нагрузке на их сервера им вряд ли когда нибудь понадобятся зеркала в традиционном понимании этого слова, у них и так достаточно распределенная структура. И уж конечно они не будут каждый раз спрашивать у пользователей с какого зеркала они предпочитают скачивать (они сами все лучше нас знают :D SkyNet блин).

И вот думаю, в юниксе традиционно приложения имеют стандартный ввод, и два стандартных вывода (по большому счету один). И хоть при дальнейшей работе они могут использовать произвольное количество вводов-выводов, но это все равно накладывает ограничения на их использование. Какие перспективы открылись бы перед приложениями если бы количество потоков было бы неограниченным? Может быть именно из за этого и придумали контейнеры, типа avi? Как в свое время придумали оверлеи ради преодоления ограничений памяти? Хотя надо было просто придумать линейную память. :)

Где-то я уже слышал (в NTFS кажется) про файловые потоки. Файловые метаданные тоже что-то никак не найдут себе достойного применения. Идеи витают в воздухе... где же прорыв?

Или вот еще про приложения думаю. В юниксе традиционная мелкозадачность. То есть для каждой конкретной задачи свое приложение, скрипты кишмя кишат в наших системах и постоянно десятки приложений запускаются и останавливаются. На что мы тратим свои гигагерцы? Альтернативой могло бы стать сервисное взаимодействие, то есть не библиотеки и не приложения, а некие службы. Гибкости в этом варианте гораздо больше но почему-то опять таки пробивается плохо. COM еще жив? Может быть нафиг объекты, да здравствует HTTP-like? как там все просто и гибко. Может быть именно это стремление обуславливает нынешнее развитие SAAS?

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

понедельник, 12 мая 2008 г.

Производительность VCS

Читая новости OpenNet, наткнулся на несколько ссылок: bzr, git, and hg performance on the Linux tree, git/bzr historical performance comparison, и несколько более косвенно Distributed Version Control Systems: A Not-So-Quick Guide Through. У меня так и не дошли руки до полноценного исследования производительности. В данных обзорах немного расстраивает лишь отсутствие monotone.

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

Но чтобы оценить изменение рабочего каталога относительно HEAD репозитория, необходимо сравнить содержимое файлов, ну это в идеальном варианте, все остальные варианты оставляют шансы на ошибку. Причем нам главное знать факт изменения файла. Изменение длины явно говорит о том, что файл изменился, так же как и изменение хеша. Но с другой стороны изменение времени вообще ни о чем не говорит, а совпадение хеша вовсе не говорит о том, что файлы идентичны. Может быть именно последний момент подталкивает некоторые системы контроля оперировать не хешами а номерами?

Но раз уж системы оперируют хешами как версиями файлов, видимо приходится принять условие, что совпадение хеша подтверждает совпадение файла. Но проблема в том, что рассчет хеша всех файлов дерева linux занимает порядка минуты, ну если соптимизировать - ну 40 секунд к примеру. И становится непонятным, как git, bzr и hg умудряются показывать статус за считанные секунды (1-5 сек).

Вероятно, они всетаки доверяют времени, и файлы с неизменным временем автоматически считаются неизмененными. Вообще я не склонен доверять времени, время может съехать, ИМХО Makefile работают совсем не правильно. :) Ну это наверное мое извечное всеотрицание. А если рассуждать трезво, то меня вовсе не радует перспектива ждать по 40 секунд для просмотра статуса изменений. Поэтому использование таймстампов файлов - это меньшее из зол.

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

четверг, 10 апреля 2008 г.

Ответственность за изменения...

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

Начнем с глобальных мотивов. Если взять большой открытый проект типа linux, то там ситуация такова, что конкретные изменения вносят тысячи людей, Линус не обязан им доверять и может вообще не подозревать об их существовании (нет необходимости импортировать ключи), потому, что эти изменения попадают к нему через доверенных лиц, которые, как бы, берут на себя ответственность за эти изменения. Собственно git и не поддерживает (во всяком случае в стандартной поставке) подписывания каждого изменения, там есть только подписывание меток.

В более ограниченных проектах ситуация с доверием возможна, если бы не несколько но. При единственной ветви разработки никаких проблем нету. (CVCS?) Проблемы начинаются при ветвлениях.

Предположим что существует некая ветвь разработки a. от нее создается ветвь b, и обе ветви некоторое время развиваются независимо... a1 -> a2 -> ... an, b1 -> b2 -> ... bn. Естественно, что каждый набор изменений подписан кем-то.

Теперь ветвь b сливается с ветвью a.

Первый путь (mercurial вроде так поступал), Это когда изменения сливаются в рабочей копии и формируется версия a(n+1), которая потом коммитится в ветви a. Но в этом случае получается что ни подписанные истории изменений, не авторство их не попадает в ветвь a. И этическая сторона в этом месте такова, что нельзя ссылаться на автора изменений (annotate, log), потому что его подписи нигде нету. То есть ситуация ровно как в ядре линукс, автор слияния берет на себя ответственность за все вносимые изменения.

Я, как человек сведующий в криптографии понимаю что любое изменение подписанных данных автоматически приводит к недействительности подписи. Но теоретически, если изменения ветви b производились в файлах не изменяемых в ветви a, то историю изменений можно перенести из b, при этом новая версия (дерево файлов) всеравно подписывается автором слияния, но изменения по конкретным файлам имеют изначальное авторство. Но любой конфликт нарушает эту идиллию коренным образом, поскольку любое постороннее изменение файла исключает возможность применения вливаемых изменений, и ситуация сводится к предыдущей.

файл1: a -> b1 -> ... bn (HEAD of a)
файл2: a -> a1 -> ... an (HEAD of a)

Это справедливо только для бинарных дельт, diff'ы можно было бы накатывать и на посторонние изменения, если не учитывать тот факт что при подписывании изменений стоит обращать внимание и на содержимое исходного файла, иначе как можно дать гарантию, что изменение не деструктивное?

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

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

В случае децентрализованных систем контроля (особенно таких где репозиторий и рабочая копия неразрывно связаны) правильнее будет строить доверительность на уровне взаимосвязи репозиториев. Подписывание отдельных изменений тоже допустимо, но по большому счету оно ничего не дает. Авторство будет сохраняться только при экспорте (всмысле при раздаче изменений от центрального узла к переферийным, ну при паутинообразной организации типа linux ядра :) ), При слиянии изменений подписи перестают работать.

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

Может я опять чего-то не учитываю? Что-то еще хотел написать да забыл. завтра вспомню.

PS: Вот, спустя неделю, кое что вспомнил. Подписывать надо не наборы изменений, а состояние версии. Но это требует от системы контроля целостности состояний, то есть версия должна фиксировать содержимое всех файлов проекта (как в monotone). Что касается git, то его изменения ИМХО кумулятивны, и вообще не понимаю каким боком туда прикручивают цифровые подписи, а ведь прикручивают же, или я опять ошибаюсь?

среда, 9 апреля 2008 г.

Идеальная система контроля версий...

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

А сам я все написать тоже не могу, но мне ничего не мешает думать об этом.

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

Но в то же время git имеет явное ориентирование на патчи. У меня даже сложилось впечатление что версии в git - это патчеобразные наборы изменений, то есть одна ревизия git описывает изменения только в ограниченном количестве файлов. В то время как мое скромное мнение на этот счет таково, что версия должна характеризоваться полным состоянием дерева файлов. В принципе, в своем мнении я не одинок, так делает к примеру monotone.

Но у monotone есть один серьезный недостаток, о котором я уже упоминал - он медленный. Постановка на контроль 24.5к файлов (ядро линукс - мой любимый тестовый набор) занимает В общей сложности 3 минуты. Хм... что-то изменилось, кажется раньше он был значительно медленнее.

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

И самое гавное - бранчи - это легковесное ветвление. Создание бранчей должно быть возможно даже для минимальных изменений. С последующим слиянием и удалением бранча. Вот какраз с последним у некоторых систем наблюдаются проблемы. Удаление бранчей поддерживают далеко не все. Monotone, mercurial вообще не умеют удалять бранчи (тяжеловесные бранчи?), bazaar вообще всю поддержку бранчей сводит к клонированию - иногда это удобно, иметь доступ к двум ветвям одновременно, но иногда и не нужно. git в этом плане более гибок, только не совсем понимаю зачем при клонировании он создает origin бранчи? Логика разработчиков такая наверное.

Гораздо проще клонировать базу как есть, обратный слив изменений в любом случае должен осуществляться в отдельные ветви (как в monotone)... Можно даже, например, при клонировании указывать название ветви, и клонировать только ее.

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

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

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

PS: Я вот наивно подумал, что git с помощью rebase мог бы позволить внести в историю предыдущие версии проекта, как бы не так. С удалениями/добавлениями он разобраться не в силах - просит ручками разбирать. Хотя как просто - одно состояние, другое состояние - сделай diff. Ан нет.

PPS: тот же git по умолчанию считает что каждый файлик на коммит надо добавлять индивидуально (логика ориентирована на патчи, опять таки). Хотя мне что-то подсказывает что если я говорю commit - все изменения надо вносить, если мне что-то не надо вносить, я исключу руками. но это конечно определяется подходом.

PPS: Как в git посмотреть список игнорируемых файлов? 'git ls-files --ignored' требует exclude pattern... не понимаю смысла.

Хотя может быть я просто что-то не понимаю? :)

четверг, 13 марта 2008 г.

Извращенное usability...

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

Но начну издалека...

У меня дома сейчас проходит ремонт, в связи с чем я довольно частый гости на строительных рынках, но это не имеет отношения к делу. На одном московском рынке, названий говорить не буду, хотя это Люблинское поле, есть туалет. Туалет хороший, приятно зайти. Везде фотодатчики, или как их там называют, смывает само, воду включает само. Сушилки правда нету, вместо нее бумажные полотенца...

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

Недавно в руки ко мне попал ноутбук, ну кое что настроить там нужно, не важно, с Windows Vista... Всем, конечно, известна моя нелюбовь к продуктам Майкрософт, но я стараюсь быть корректным. В какой то момент, глядя на качающийся из стороны в сторону прогрессбар, я подумал: "Вероятно первое появление прогрессбаров было весьма революционным - как удобно, сразу видно сколько осталось до конца". Потом, видимо, кто-то решил добавить немного динамики, или просто степень завершения работы была неизвестна и придумали прогрессбар, который никогда не кончается. В данном случае он качается из стороны в сторону, бывают варианты что он, дойдя до края, начинается сначала (вот облом..), но результат один.



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

вторник, 11 марта 2008 г.

Есть ли жизнь без MMU...

Последнее время, с тех пор как занялся с LPC2468, много думаю на эту тему.

Сперва я думал об этом, как о чем-то весьма далеком от меня, полностью пропитанного идеями x86. Но в какой-то момент я подумал, что если не использовать страничное преобразование, то и x86 становится вполне себе MMUless архитектурой. Остается только придумать как в этой ситуации сможет работать система...

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

Код приложений должен быть безопасен. Безопасности можно достичь использованием типобезопасного языка. Cразу вспоминаются системы с единой памятью, типа Bluebottle, Singularity... Которые собственно и создаются без учета MMU как такового. При демократии (использовании любых языков) с безопасностью дела обстоят гораздо сложнее. Всмысле никто не может гарантировать безопасность данных приложений.

Кроме того, без MMU немаловажным является и объем памяти. Своппинг исключается, и это тоже ограничивает возможности системы. Для серьезной системы даже 4 гигабайта линейной памяти не кажутся слишком большим объемом. EM64T спасет серьезные системы, если они без MMU всетаки возникнут.

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

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

Во первых это привязка приложения к положению в памяти. Конечно, при ограниченном количестве приложения их положение в памяти можно согласовать, но это слишком не гибко и не позволит приложениям использовать больше чем предначертано, не смотря на то, что остальная память может быть просто свободна. Самым правильным подходом будет перемещаемость приложений. Здесь тоже два варианта поведения. Либо PIC, либо перемещаемый формат. первый расходует больше памяти, второй больше времени. Если платформа маломощная - и то и другое может быть существенно. Но чтобы не изобретать велосипед, я думаю логичным было бы взять тот же ELF, и в перемещаемом формате загружать (и не изобретать BFLT).

Динамическое распределение памяти могло бы осуществляться ядром, на общих основаниях. Как бы, большой-пребольшой хип, размером со всю доступную память. Последней проблемой остается стек. Потребности приложений зачастую непредсказуемы ИМХО (возможно, именно поэтому некоторые приложения у меня на LPC2468 падают), выделять много - расточительно (если система маломощная), выделять мало - нельзя.

Пока меня платформы без MMU не воодушевляют, есть дела поинтереснее, но не стоит зарекаться...