From Novosibirsk, Russia? Our tiny company is looking for current or future rock-star developers.

February 15, 2009

ProjectSync 1.2

Мы опубликовали ProjectSync — Eclipse-плагин, который синхронизирует папки на диске с Working Set'ами в Eclipse'е. Он автоматически импортирует недостающие проекты, а также автоматически перемещает вновь созданные проекты в нужную директорию (согласно их Working Set'у).

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

ProjectSync ничего не делает за вашей спиной и не тормозит Eclipse; синхронизация активируется пунктом в меню Project.

Последнюю версию 1.2.1 можно взять со странички www.yoursway.com/free/ProjectSync/. Проверен на Eclipse 3.4 и Eclipse 3.5 M5. На Eclipse 3.3, скорее всего, тоже работает.

Там же есть ссылки на сорцы, баг-трекер, лицензию (EPL) и способы получения техподдержки.

February 04, 2009

Совместимость

Название этой операционной системы, созданной маленькой компанией в конце 80-х и установленной сегодня на 8% компьютеров мира, программисты под Mac и iPhone регулярно вспоминают, набирая префикс NS у названий системных классов.

Nextstep 1.0 появилась в 1989 году после трех лет разработки, имела полностью объектно-ориентированное API с архитектурой model-view-controller, имела ядро Mach и была Unix’ом. Теперь она называется Mac OS X. За прошедшие 20 лет дизайн её API, теперь именующимся Cocoa, мало изменился: всё те же NSApplication, NSView, NSDocument успешно лежат в основе сегодняшних красивых анимированных Mac-приложений. Исходники GNUstep, реализующего Nextstep API 1993 года, можно в наши дни читать вместо (недоступных) исходников Cocoa.

Пользовательский интерфейс Nextstep включал богатый drag’n’drop между приложениями, Dock, инспекторы, общесистемные сервисы, позволяющие приложениям пользоваться услугами друг друга, и «бандлы» — директории, выглядящие как файлы для пользователя и содержащие приложение со всеми зависимостями, которое достаточно просто скопировать на жесткий диск для установки. Всё это знают и любят сегодняшие пользователи маков.

Как относятся в Apple к совместимости? Плохо. Первую революцию они сделали в 2001 году с выходом Mac OS X: старые приложения теперь могли запускаться только в приложенной виртуальной машине, эмулирующей Mac OS 9 (при этом, естественно, выглядели неприглядно и медленно работали). В 2005 году эмулятор почил с выходом OS X 10.4 (итого: 4 года на портирование старых приложений).

Для портирования людям был дан Carbon — C API, почти повторяющее API старой Mac OS 9. Carbon-приложения всегда оставались нежеланными гостями на компьютере: look’n’feel интерфейса OS X, как истинно объектно-ориентированной ОС, реализован в коде Cocoa (да, там можно изменить поведение стандартных элементов управления, просто унаследовавшись от них). Carbon представлял собой еще одну реализацию примерно того же самого интерфейса.

Вторую революцию Apple сделала в 2007 году: Carbon объявлен устаревшим и не будет поддерживать 64-битные приложения. Кадр года: Adobe переписывает Photoshop на Objective C. Называется, а вам слабо такое устроить?

Что приобретено взамен совместимости? Общий уровень приложений платформы: они все обновляются и соответствуют современным стандартам. Это работает по спирали: от более высокого качества приложений увеличиваются ожидания пользователей («никто не запустит программу без большой красивой иконки»), от высокого уровня ожиданий растет качество приложений. Apple создала платформу, в которой качество является более значимым (по сравнению с другими платформами) конкурентным преимуществом, и от этого создатели приложений больше инвестируют в качество.

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

Зато NeXT/Apple серьезно относятся к преемственности навыков пользователя. Метафора пользовательского интерфейса Nextstep/OS X не меняется уже 20 лет. Внешний вид окон OS X не меняется 8 лет. Интерфейс приложений развивается эволюционно; Photoshop переписали, но выглядит и работает он так же; вышла новая версия iWork, но она только местами отличается от старой.

Что происходило всё это время в параллельном мире? 1989 год — релиз Nextstep 1.0 — вышла Windows 2.0 без перекрывающихся окон. 1995 год — вышла Windows 95, прощай, все старые навыки. 2001 год — вышла Window XP, теперь вы не узнаете свою панель управления. 2002 год — Microsoft выпускает .NET Framework 1.0, Desktop-приложения на котором до сих пор никто не пишет. Кстати, писать Desktop-приложения вообще не на чем: MFC — поганое уродство, всё остальное до жути низкоуровневое (Win32 API отличается от Cocoa как ассемблер от Питона).

2007 год — вышла Windows Vista, прощайте, привычки, теперь всё в новом месте. Зато спиздили еще чуть-чуть гуйни мака, сделали мигающий экраном костыль для безопасности приложений (на маке privilege elevation в приложениях к этому моменту уже много лет как нормально ненавязчиво работало). Вышел Office 2007, его нужно изучать заново. 2009 год — Microsoft в Windows 7 меняет Taskbar на Dock и хвалится этим достижением в блоге. Кстати, Office 2007 Ribbon Bar будет доступна всем приложениям, теперь вам придется заново изучать не только офис.

Зато вы всё еще можете запускать DOS-приложения на Windows Vista. Реймонд Чен в своём блоге высоко воспевает культуру совместимости в Microsoft. Но стоит ли она выпуска инвалидских продуктов? Всё дело в крупно-корпоративном рынке, которому его старые приложения ценнее качества ОС. Возможно, во времена Windows 95 совместимость была необходима и для пользователей: графические интерфейсы стали массовыми именно после Windows 95, и имей она проблемы, этого могло просто не произойти.

Мораль раз: знайте, когда устранять совместимость, иначе она помешает конечному пользователю.

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

Мораль три: культура качества — ценнейшая штука для любой платформы; без неё корпорации не способны выпускать хорошие продукты, даже если на рынке есть образцы для подражания.

February 03, 2009

NSCoderNight(Nsk)

Если вы живете в Академгородке Новосибирска и интересуетесь программированием под мак (или вы интересуетесь теми, кто интересуется программированием под мак), присоединяйтесь к хакатону NSCoder Night по вторникам в 19:00 в кофейне на ВЦ.

Требуется: прийти и кодить под мак или iPhone. Кодить что-то своё, или найти на месте близких по духу товарищей и кодить с ними. Если нет мака, но есть желание научиться, предложите кому-нибудь парное программирование. И, разумеется, рядом будут люди, у которых всегда можно спросить совета.

Зачинщик события в Новосибирске — сооснователь нашей компании Михаил Калугин. Я буду тоже. О других местах, где проводится NSCoder Night, читайте на nscodernight.com.

Наконец, посты про NSCoder Night(Nsk) просьба помечать тегом nscodernsk, чтобы их можно было найти в блогосфере.

November 21, 2008

Лирика или музыка?

Пять альбомов в истории Pink Floyd наполнены глубоким смыслом и эмоциями, переданными потрясающей лирикой и выдающейся музыкой. Это Dark Side Of The Moon, Wish You Were Here, Animals, The Wall и The Final Cut.

Появились они благодаря гениальности человека по имени Roger Waters, создавшего их замысел и написавшего к ним лирику. Человека такого же уровня доброты и ума, как Джон Леннон. Человека, которого можно было бы считать великим русским писателем, будь он русским писателем.

Pink Floyd распалась потому, что их музыка держалась на великом гитаристе по имени David Gilmour, идеи Waters'а которому были чужды. Gilmour хотел играть просто красивую мощную музыку в стиле светлых лет Pink Floyd, а Waters всё больше подчинял музыку своей всё более немузыкальной лирике.

The Final Cut — последний альбом Pink Floyd, созданный Waters'ом. Он даже не совсем принадлежит группе; его полное название читается «The Final Cut: A Requiem for the Post-War Dream by Roger Waters, performed by Pink Floyd».

Альбом начал свою жизнь легким завершением The Wall и должен был включать песни из его экранизации, а также некоторые песни, задумывавшиеся для, но не попавшие в «Стенку». Но после войны между Англией и Аргентиной 1982 года альбом стал тем, чем он есть — сложным тематическим завершением The Wall, использующим похожую эмоциональную структуру, но создающим реалистично-светлые чувства к концу.

The Wall — весьма попсовый альбом в смысле сложности его восприятия: он столь пропитан эмоциями, что его сложно не понять. Мелодическая структура Dark Side Of The Moon тоньше, Animals и Wish You Were Here значительно более спокойные. The Final Cut еще более некричащий, и его прослушивание требует примерно столь же развитого вкуса и умения слушать, как классическая музыка.

Тем временем, без Waters'а David Gilmour создал альбом The Devision Bell, название которому придумал Douglas Adams, а мусором который обозвал Waters. The Devision Bell нравится многим, что неудивительно: в нём наблюдается возврат к попсовому — легко воспринимаемому — звучанию. К сожалению, нет и глубокой лирики.

The Devision Bell мне напоминает культ самолётопоклонников, описанный Фейнманом. Красивая музыка, странные слова, всё сделали как надо — почему же получилось не так, как раньше? (Что мне не мешает иногда его слушать, конечно. Гилмор великий гитарист.)

«Music, when combined with a pleasurable idea, is poetry. Music without the idea is simply music.» (Edgar Allan Poe).

Все выдающиеся исполнители, взрослея, уходят от легко воспринимаемого звучания независимо от того, становится ли их музыка более простой или более сложной по структуре. Сравните ранних Beatles, поздних Beatles и сольные записи Леннона. Сравните ранних и поздних Deep Purple, и то, что они сейчас играют на концертах. Наконец, сравните раннего и позднего Waters'а. Что интересно, взросление лирики куда как менее заметно, чем взросление музыки. Быть может, потому, что писать взрослую лирику проще, чем писать немассовую музыку.

Мораль? Breathe, breathe in the air. Don't be afraid to care. Look around, choose your own ground. Long you live and high you fly, and smiles you'll give and tears you'll cry, and all you touch and all you see is all your life will ever be.

November 12, 2008

Всё, что нужно знать про Git

Доказано (опытом), что для успешной работы с Git требуется понимание структуры его объектной базы данных. К счастью, это очень просто. (А про то, чем Git интересен, я уже писал раньше.)

Часть первая из трёх: объекты

Git-репозиторий состоит из набора объектов, лежащих в папке .git/objects. Каждый объект хранится в файле, названном в честь SHA-1 хеша его содержимого. Например, объект 55f6209f867f37598cfb56832adf74bee2921c3f лежит в файле .git/objects/55/f6209f867f37598cfb56832adf74bee2921c3f.

Есть четыре вида объектов (blob, tree, commit и tag), о которых мы сейчас поговорим.

1. Все файлы вашего проекта — это blob'ы. Возьмём каждый файл, припишем к нему в начало тип "blob" и размер, посчитаем SHA-1 и запишем это в репозиторий. (Имя файла в blob не входит, так что одинаковые по содержимому файлы окажутся записанными только один раз.)

2. Каждая директория проекта — это объект tree. Он ссылается на другие деревья и blob'ы, а также указывает их имена и атрибуты. Вот пример содержимого объекта tree:

100644 blob 6fccfdcbd0a1cdbf3bf2a5960e601b369c0a921c    .gitignore
040000 tree 824b4bd4a0df733b5b5106b1b55c3630566759dc    com.yoursway.sadr.core
040000 tree 2406b80d9623067f92db7f60d6eeabfed6966a9f    com.yoursway.sadr.engine
040000 tree d1bae2405388774e484cfd3779adf7e1eda1f5d9    com.yoursway.sadr.python.core
040000 tree f3d282a4b963183fefdca6ff99a5995953a9c33e    com.yoursway.sadr.python.idioms.core
100755 blob 14cf98b8521eb27ae556d9b707290e177b337ff4    propagate-settings-from-core

3. Наконец, объекты commit образуют историю проекта. Коммит ссылается на tree корневой директории проекта, а также имеет родителя или родителей (которых несколько в случае merge'а). Вот пример объекта commit:

tree fdb267652d8d669e86ad0df61afc81b92a7ce680
parent b95b2ca7e9854898d62fb028f2e6135b3439240d
author Andrey Tarantsov  1223355822 +0700
committer Andrey Tarantsov  1223355822 +0700

Huge performance fix: findGoalStateByGoal is now DFS.

findGoalStateByGoal used to traverse every path is the graph and
thus was very slow (as slow as 500 ms travesing 3M goals on every
subgoal creation!) Changed to a real DFS.

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

git cat-file commit c889ffc87048cca59f908d3e48becb59a14ce950,
результат которой вы только что видели выше. Далее, содержимое дерева, на которое указывает коммит, смотрится командой
git ls-tree fdb267652d8d669e86ad0df61afc81b92a7ce680
(деревья хранятся в бинарном формате, поэтому git cat-file tree выдала бы бинарный мусор, а вот вывод ls-tree вы видели выше). Наконец, содержимое файла смотрится, опять же, командой
git cat-file blob 6fccfdcbd0a1cdbf3bf2a5960e601b369c0a921c.

Следует понимать, что вместо команды git cat-file вы можете просто раззиповать нужный файл из .git/objects. (Перед данными файла там окажется префикс из типа объекта и его размера.) Создать объект в репозитории можно командой git hash-object -t тип -w --stdin.

Часть вторая из трёх: ссылки

Как узнать, что коммит c889ff… является последним коммитом проекта? Для этого Git еще хранит так называемые ссылки (references). Например, в файле .git/refs/heads/master в текстовом виде хранится хеш последнего коммита на бранче master.

Ссылки могут ссылаться друг на друга. Например, ссылка .git/HEAD обычно имеет такое содержимое:

ref: refs/heads/master
В этой ссылке хранится, какой коммит лежит в данный момент в вашей рабочей директории. (Напоминаю или сообщаю, что у каждой рабочей директории Git всегда есть свой собственный репозиторий.)

Набрав команду git rev-parse HEAD, можно узнать, на какой именно коммит указывает ссылка с данным именем. Ссылки можно использовать везде вместо названий коммитов, например, можно набрать git cat-file commit refs/heads/master. Имена ссылок можно сокращать, отбрасывая слева куски пути, если это не вызывает неоднозначности. Например, можно написать git cat-file commit master. (Кстати, в мане rev-parse описаны все способы указания коммитов в Git.)

Часть третья из трёх: индекс

Между вашей рабочей директорией и репозиторием есть промежуточное звено, называемое индексом (index). Все изменения, которые вы хотите закоммитить, вам нужно положить в индекс командой git add, а потом по индексу создать коммит командой git commit.

Хозяйке на заметку. На практике я всегда пользуюсь командой git commit --inter -v, которая запускает интерактивный add (git add -i), а потом сразу делает коммит, причем (опция -v) в редакторе показывает мне diff всего, что я собираюсь закоммитить.

Что такое индекс? Индекс похож на дерево (tree), но отличается от него тремя вещами:

Во-первых, индекс хранит ссылки на блобы файлов всех поддиректорий проекта.

Во-вторых, индекс хранит i-node'ы файлов — информацию, позволяющую быстро определять, изменился ли файл в рабочей директории по сравнению с индексом.

В-третьих, при наличии конфликтов merge'а индекс может хранить ссылки на три блоба для каждого файла (базовая версия, "их" версия и "ваша" версия).

Почему вам нужно знать про индекс? Во-первых, потому, что команда commit закоммит не то содержимое файлов, которое лежит в рабочей директории, а то содержимое, которое было добавлено в индекс командой git add. Во-вторых, потому, что при разрешении конфликтов merge'а вам может захотеться вытащить эти альтернативные версии файлов (git ls-files -u покажет вам файлы из индекса, имеющие конфликты, т.е. больше одной версии).

Вот и всё

На манипуляции с объектами, ссылками и индексом строится весь Git. Чаще всего удобно полагаться на неё для выполнения нужных операций, но иногда можно вносить желаемые изменения руками.

Важно понимать, что Git не хранит дельты, метаинформацию о переименованиях файлов или что-либо еще, не описанное выше. Всё, что хранит Git — это копии состояния файлов проекта в разные моменты времени.

Git умеет хранить объекты и ссылки компактно в одном файле (которые называются pack'ами), сжимая их чем-то вроде LZW, причем размещая данные в таком порядке, что получается еще эффективнее, чем хранить дельты. Git умеет восстанавливать данные о переименованиях файлов, перемещениях и копированиях кусков файлов уже во время отображения истории.

Как изучать дальше?

Все команды подробно описаны в man pages, которые можно также читать на сайте. Важно понимать структуру объектной базы данных. Читайте Git tutorial (не забудьте прочесть вторую его часть) и описывающий всё-всё-всё Git user manual. Наконец, естественно, есть видеолекция Linus Torvalds on Git (Линус, объясняющий, что такое мастурбация — смотреть всем!)

Далее я попробую резюмировать то, что вам стоит узнать.

Лучше всего избегать merge'ей, они делают историю версий некрасивой (и не так удобно читаемой). Вместо git merge somebody/somebranch старайтесь по возможности использовать git rebase somebody/somebranch (но требуется хорошо понимать, что при этом происходит и чем вы рискуете; никогда так не делайте, если уже залили куда-то свои изменения). Особенно важно держать историю версий линейной, если вы экспортируете коммиты в какой-нибудь svn с помощью git-svn.

Подружитесь с git reset, который един в трёх лицах (soft, mixed и hard). Все три вам в жизни очень понадобятся. Еще полезная штука git stash.

Git умеет импортировать историю из многих систем контроля версий (например см. git cvsimport, также есть много отдельных импортировальщиков), двусторонне синхронизироваться с Subversion (см. git svn). Что касается импорта из CVS, Git в процессе задействует команду cvsps, которая в официальной версии имеет разные баги. Пропатченная версия имеется и очень рекомендуются к использованию при импорте из CVS.

Git умеет переписывать историю. Вообще-то, вооружившись приведенными сведениями, это можно сделать и руками (или хитрым скриптом), но намного быстрее использовать команды git commit --amend, git rebase (особенно git rebase --interactive) и git filter-branch; последний позволяет сделать буквально всё.

Выше ничего не сказано про теги; они есть, причем двух видов (теги можно делать просто ссылками в refs/tags/, а можно дополнительно к ссылкам создавать полноценные объекты, в которые уже помещается комментарий и цифровая подпись). Не упоминался ref log — локальная история изменений каждой ссылки, позволяющая ответить на вопрос, какая версия была у вас в рабочей директории два дня назад (или какой коммит был у вас последним в бранче master вчера). Если вы сделаете дикий rebase и вся история умрёт, ref log вас спасёт; смотрим его командой git log -g.

Есть GitHub, где хостинг для open source-проектов бесплатный, а для проприетарных просто дешевый. GitHub делает управление репозиториями и отслеживание прогресса других маргинально проще, а заодно избавляет от необходимости регулярно вызывать git gc в репозиториях на сервере. (В ваших локальных репозиториях её всё равно нужно регулярно исполнять.)

Наконец, Git — это не только его команды и система контроля версий. Это база данных, которую можно использовать для автоматической децентрализованной синхронизации файлов. Формат базы данных достаточно прост и позволяет работу с ней реализовать на других языках в вашем проекте. В частности, чтение и запись репозиториев Git уже реализована для Java в проекте jgit (и обрастает интересностями вроде встроенной поддержки Amazon S3). Если вам нужна распределенная база данных объектов, похожих на файлы, вам следует посмотреть в сторону Git.

October 11, 2008

Основной налог (эссе про бизнес)

В нашей стране есть три вида налогообложения для ООО: общая схема, упрощенная схема с объектом «доходы» и упрощенная схема с объектом «доходы минус расходы».

Упрощенная схема, по крайней мере на мой непрофессиональный взгляд, намного выгоднее общей. Её, однако, нельзя применять организациям с оборотом более 20 000 000 руб в год.

Суть: вы платите либо 6% ото всех денег, которые ваша компания зарабатывает (схема «доходы»), либо 15% от денег, которые остаются после вычитания ваших расходов (схема «доходы минус расходы»).

Какие траты можно отнести к расходам? Увы, только те, которые необходимы для вашей основной деятельности. Покупку техники, канцелярию, офис и интернет можно. Еду, велосипеды для сотрудников, посиделки в кафе и многое другое нельзя. Это особенно актуально при 15% схеме (ибо с денег, потраченных на расходы компании, вообще не нужно платить налога), но важно и при 6%.

Деньги, которые вы не отнесёте на расходы, придётся обналичивать либо зарплатой (теряя еще около 30% на налоги), либо дивидендами (теряя еще 9% подоходного налога), либо нелегально (теряя, по слухам, 5-10% и, по стечению обстоятельств, от своего морального спокойствия до всех денег и свободы). О зарплате и дивидендах мы ещё поговорим.

(Естественно, есть детали: например, при 6% схеме этот налог уменьшается на размер налога, выплаченного в пенсионный фонд с заработной платы сотрудников.)

В словарик. УФНС — управление федеральной налоговой службы. Её нужно любить, иначе она полюбит вас. УСН — упрощенная схема налогообложения. Она ваш друг.

В отличие от упрощенной, общая схема налогообложения, как следует из разницы в названиях, сложна. В ней участвуют два налога: 18% налог на добавленную стоимость (НДС) и 24% налог на прибыль (аналогичный 15%-му налогу на прибыль в упрощенной схеме).

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

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

Только что открытая компания находится на общей схеме налогообложения. Для перехода на упрощенную схему нужно по-шустрому подать заявление в налоговую, выбрав объект налогообложения («доходы» или «доходы минус расходы»). Изменить этот выбор нельзя в течение 3-х лет.

Как сосчитать подписчиков?

У моей уютной ЖЖешечки этого блога 72 подписчика. Браузером ежедневно на него заходят около 17 человек, что дает 545 посещений в месяц от 402 уникальных посетителей; 332 посещения дают поисковики, а 125 — ссылки с других сайтов.

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

Регистрируемся на FeedBurner'е, получаем там урль вашего нового фида.

Идем в блоггер, настраиваем в нём редирект фида на новенький урль фидбёрнера.

Во-вторых, нужно использовать Google Analytics, чтобы отслеживать обычных посетителей вашего блога.

Регистрируемся, получаем у гугла JavaScript-код отслеживания посетителей, кидаем этот код в самый конец макета страниц. Блоггер позволяет добавлять произвольные фрагменты HTML/JavaScript, насчет ЖЖ не знаю (кстати, самое время перейти на блоггер).

Дать настояться недельку-другую, статистика готова.

А вы знали, что Google купил FeedBurner? Как водится, про-фичи последнего стали бесплатны.