пятница, декабря 19, 2008

Data about data

Если открыть спецификацию какого-нибудь формата данных, в ней скорее всего обнаружится раздей посвященный метаданным. Иногда, такой раздел превышает остальную спецификацию в несколько раз по объему и по сложности. В то же время, на практике метаданные используют весьма и весьма нечасто. Существуют даже форматы, которые никто так полностью и не имплементировал, по причине невостребованности. Например, тот же ID3v2 (метаданные для MP3) с его несколькими сотнями тегов начиная от автора песни и заканчивая переводами лирики. Или EXIF, которым пользуются ровно потому, что все современные камры пишут в него параметры съемки. Еще ни разу не видел, чтобы из него кто-нибудь использовал разделы описания или копирайта. Или FB2, по поводу метаданных которого регулярно возникают споры на форумах о том, как их заполнять. Или MARC, с правильным заполнением которого проблемы даже у профессиональных библиотекарей, хотя им-то сам бог велел прекрасно разбираться в предметной области. И какой формат ни возьми, с метаданными будет плохо. Или мало, или много, или в самый раз, но совсем не то, что нужно.

Для того чтобы понять почему так происходит, нужно определить, что такое метаданные. Лаконичное определение из заголовка, конечно, прекрасно, но оно ничего не говорит о том, какие это данные. Почти все факты о данных можно представить в виде утверждений <субъект, свойство, значение>. А набор свойств из предметной области и доменов для значений суть онтология. Например, фокусное расстояние это свойство, которое может принимать значение типа длина (а не угол или скорость). В большинстве форматов онтология жестко зафиксирована, так что не бросается в глаза, но она всегда присутствует.

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

Как можно с этой проблемой справиться? Если вы разработчик формата, не пытайтесь думать за пользователей -- все равно не выйдет. Дайте им возможность определять собственные онтологии и снабдите их парой убедительных примеров для конкретных узких областей. Хороший пример движения в нужном направлении Adobe XMP основанный на RDF. Нельзя сказать, что этот формат идеален, но хоть что-то.

пятница, ноября 28, 2008

Time to live

У каждого предмета есть определенное время жизни. Рано или поздно он устареет, износится и потребует замены новым. Или просто исчезнет проблема, ради решения которой этот предмет создавался, как исчезли мундштуки, подстаканники, пресс-папье и буфеты. Это касается не только материальных объектов, но и информации, в том числе и информационных систем. У каждой строчки кода, у каждого килобайта данных есть собственное время жизни. Время жизни есть даже у таких неосязаемых сущностей, как идеи или соглашения. Для того, чтобы научиться оценивать характерное время жизни, нужно хорошо понимать механизмы разрушения объектов. Например, автомобиль может разрушится в результате аварии, физического износа или морального устаревания. Если известно, что автомобиль морально устареет через 10 лет, нецелесообразно обеспечивать его надежную работу в течение большего срока. Все равно к тому времени он уже окажется под прессом. Знание характерного времени жизни позволяет поддерживать качество на необходимом уровне, не больше и не меньше. Зачем делать автомобиль надежным, если через 10 лет он все равно окажется на помойке, где не важно работает он или нет.

Данные

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

Протоколы и стандарты

Две причины, по которым устаревают стандарты и протоколы: они перестают отвечать изменившимся требованиям или появляется способ сделать то же самое проще. Поскольку технологии непрерывно меняются и то, что раньше требовало дестятка PhD, сегодня доступно школьнику, редкий стандарт проживет больше 10 -- 15 лет. Затем, если представится возможность, он отправится на помойку истории. К сожалению это происходит не всегда. Очень часто изменения уже внедренного стандарта, процесс настолько болезненный, что стандарт активно используется не смотря на то, что они окончательно устарели. В качестве вопиющих примеров можно вспомнить Z39.50, SMTP, FTP и HTTP. К проектированию стандартов имеет смысл относиться даже более внимательно, чем к проектированию баз данных. "Внимательно" в данном случае означает не "предусмотреть все возможные случаи", а обеспечить возможность изменений. Все равно предусмотреть все не удастся, а если и удастся, то этим все равно не станут пользоваться из за непомерной сложности.

Код

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

Абстракции и модели данных

Абстракции живут от нескольких минут до тех пор, пока их помнят или пока не придумают что-то получше. Двойная бухгалтерская запись была изобретена в XV веке, а используется по сей день, несмотря на то, что в эпоху компьютеров без нее легко можно обойтись. Даже если абстракция хреновая, она все равно не умирает. Слишком много всего от нее зависит. Тут и код, и привычки людей, и их внутрення картина мира. Если вы предложите бухгатерам отказаться от двойной записи, они вас съедят. Будьте осторожны, если ваша абстракция получит распространение, вы ее уже не остановите.

Пользовательский интерфейс

Пользовательский интерфейс протухает за 3-5 лет. Он подвержен тем же изменениям требований что и код, вдобавок новые интерфейсные технологии появляются ничуть не реже программных. Даже отличный интерфейс пятилетней давности выглядит малость устаревышим, а десятилетним интерфейсом современному человеку пользоваться неудобно, да и глаз режет. Метафоры за 10 лет успели сильно измениться. Если пользователи не могут сбежать, устаревший интерфейс удается сохранить два-три срока. Затем начинаются проблемы уже с поиском операторов, способных работать на таком старье.

четверг, сентября 25, 2008

ICFP Contest '08 Final results

На официальной странице ICFP Contest выложены результаты, которые так долго ждали большевики. Было проведено 11 заездов, в результате которых был определен один победитель (Team Smartass) и 297 неудачников, которым не так повезло. К сожалению финальные карты еще не выложены, поэтому трудно сказать что пошло не так, но финалисты предыдущего чекпойнта "вылетели за ограждение". Как в прошлый раз, я подготовил таблицу с суммарными результатами. Команды отсортированы по количеству раундов, в которых они приняли участие независимо от результата. Команды, прошедшие одинаковое число раундов отсортированы по рейтингу. Напоминаю, чем меньше рейтинг, тем круче. Для каждой команды приведена статистика исходов по всем пяти заездам каждого раунда. В общем, можно меряться. Get it and use it well.

Моя команда называется Mosquito. Каким чудом она попала на 11 место, оставив позади страшных монстров, сам не понимаю. Видимо, новичкам везет.

#TeamRoundsScoreHomeMartianCraterTimeoutError
1Team Smartass11512510505
2shinh115153704951
3Error 404115419605032
4UBE11546000487
5LazyBear115568705122
6SzM1160863040555
7souris aveugle1161162040123
8frank3241164361039655
9kstm.org1167453040132
10fireinthedisco2116894004582
11Mosquito1173004041851
12Om Nom Nom Nom1174314037153
13Giantslalom1174855038161
14epriestley1176509033175
15intelliarts1060905037814
16cw106170704010
17The B-Team: 25/26ths as good as the A-Team1061928040145
18Blue Iris106268603713
19Spore Sept 7th, only $49.99! Play Bejeweled @ popcap.com!10631580381011
20team_bruno10649780419
21Hands Solo106522004082
22jabber.ru106543103713
23Celestial Dire Badger10659590446
24Side Effects May Include...106607403812
25Apathy Kings10665890361211
26CNaml106728103713
27Cup<'t>1069525036131
28TC2107033104010
29Team Meh107104303812
30Yeahbut10712870437
31td107169504271
32Purple Pointer Eaters107195603515
33TeamDJ1072120036131
34ur 67P1072335032171
35NMSU107327703911
36Actua107390203416
37Eger a Marson1073954035132
38EdFred1074258038102
39Arekuma1074803035132
40little lemon1078496034142
41Order of the Fridge108053103317
42HackerDom_194421503510
43ais5239442380387
44ILL martians94483003411
45Sir Bedevere the Wise94507803492
46Kee9455360369
47Urxae946507034101
48Heklers94657903384
49Malfunctional Programmer94702503510
5042947790033111
51Slow9478020369
52LUHPI94842903672
53tidder948657034101
54elbereth@utmc9487230378
55Wile E.94923003591
5612a094941803114
57PurelyFunctionalInfrastructure95015203411
58RHZ95015703672
59m1-speedygonzalez95151803411
60Five of Six951680030762
61Bobry9543260294111
62a1k0n955337028134
63Team Sampou957250030141
64taxi driver839880029101
65BugbearR84110603451
66Dee Mon8428540346
67ayatuki84333502695
68HackerDom84342102812
69Too Simplicity and Beyond!843892026941
70I-cons-a-lot84487702992
71The Dibbies844886023116
72Hacking in the Rain845433024781
73Altair84625502992
74lazymonkeys846802030631
75'a infvec84712902875
76protocolocon847215031414
77Kharkiv MIND84798102785
78Begot85010702515
79Lazy elf8509630231061
80astsmtl7313950278
81shitamachi no ue73195602771
82kounoike7323950287
83Java Jones and the Kingdom of the Crystal Crater73315202672
84TBD73319802510
85lepidum7333640278
86ktkr-cpp733909026621
87miyu73412203041
88Gcup73415602681
89Epsilon73532502942
90nanndemoiidesu73556702591
91pirapira73572002510
92barry, our driver, is reckless73665102591
93NAU ACM73724902195
94TheRoverers73732102411
95DotWeb74033302096
96SwtPl740343021104
977-15741668022121
98Beer:Thirty626351024321
99Team DumbAss62785302181
100inforfun6278540246
101Team Lolemnity628437021522
102ntua 67P62855002343
103jan nasa62952702352
104Pear Programmers62958502442
105Christoph Breitkopf6297470246
106spotrover629798021351
107cashto62984502253
108The Weyburn Expatriates62999102235
109ORBIT63013202424
110Rhope Burn63018202325
111aruhimorinonaka63020202271
112green_tea63035702442
113Bob's Store63058702226
114WindowMakers 63076002271
115The Blind Hen63079902262
116bmm team63095702424
117Grasshoppers63098602163
118The Tcler632061020361
119ksk63215002127
120MIMUW 406063252602262
121Florida Institute of Technology63254102253
122D&D632740018372
123wjdogs63282601758
124Kerochan63291802073
125The Unchecked Exceptions63299302019
126In dumb we trust63350401974
127Curry On!633519017364
128KFL633554021252
129hibi@utmc.or.jp633664021351
130YBuzz633863020361
131Dragons633921018381
132Q42/Xopus634184018471
133Team Guyford63420301812
134Arsbit63512101857
135one canuck63545101776
136Chouser635591018372
137uguu.org63566901848
138midoj636782019641
139The Tweezer Minstrels63709601578
140bens63730001785
141apple2gs63787902154
142yarunee638188016383
143The Usual Suspects63820802136
144Ramen Holiday638355019461
145The Code Alchemists63847902181
146Team Rocket63893201947
147nekoneko 639315017571
148The Inmates63937702073
149camping gaz international63977902226
150solo r6640265020811
151GRoboCode64033401938
152ktkr-ocaml64119901857
153LazyBottoms644571016671
154spbsunt5176870214
155It's all about the Pentiums.51832901933
156Emory PChem51842701951
157Toasted Monkeys518614019222
158Le club des 551887501942
159suihan_jar519344017431
160Wobbla Team51939802041
161__ufo42520548013264
162Dis Functional52095501546
163POSTECH-PL52100901654
164The Higher Order Of Zeuxis521291017332
165Unary Operator52141701843
166POSCAT@POSTECH522283014254
167suzumiyaharuhiko522405011743
168Hidden Agenda4147770146
169Incompetent Design414821011531
170OCamlCore41530501253
171Knights of Cydonia41590501253
172Marcin Simonides4160540128
173td241606201334
174efg416122013331
175AntiCylonDefenseTeamImpersonator41616501262
176ikon416273010343
177o(ry41644701451
178bucchigiri41652301325
179Dylan Hackers41653101352
180Team Gales416570011252
181The Rover Routers416690013511
182Anairiats416719014321
183Tigerfunk41708406284
184dot-emacs41737807283
185Fly (Yaroslavl)41758001271
186K&R41758401334
187Mostly Harmless41784901271
188AyaCFP4178530137
189putzen along41787401271
190Enoch Root417978011531
191futurelabs41809901244
192Molotov Mocktail41864309722
193Servants of Barsoom4187290128
194NetHack41875501262
195Ruby Team4187930128
196Almaya418813012521
197gassa & toxa41930001172
198(defun friends)31071801032
199The Lone TeXnician31077008232
200hogelog3108370663
201Insane Closure Posse3111800114
202Macrott31133109321
203Blazing Saddles31153709312
204yet another team31155507413
205honey_rooibos311614096
206Evil Geniuses For a Better Tomorrow31173601041
207TeamNewshamBros3117630924
208Illudium Q-36 Explosive Space Modulator31180609411
209Giver3118500924
210rmathew31191205253
211SIMAP31195709321
212eugene_jeff31222406423
213polka31243008421
214Func-n-stein31251407242
215EddieHasNoPreferenceForName 3126480852
216Xebia31281108331
217Bad Science3129430861
218Stern Types 31304007323
219siti31324707611
220panard_groumpf31343805334
221SugarSun3134660861
222mfp31358604515
223NCSU ARC Alums3136960933
224The Bobcat Hackers31389806522
225Knights of the Crescent Moon31402505424
226isobe31406607431
227EarthFusion31443108511
228Epic Fail31467506522
229plai31476205622
230ozy4dm315737078
231wheezards257930811
232Soul Trader2775804213
233404 NOT FOUND2784703151
234WE NEED A TEAM NAME2785406211
235Not a Number2789105212
236Stanfy279440712
237Bloody Camls27950073
238Team Sparrow279740631
239Too much free time280430622
240Linkage Failure28066073
241kt3k28123073
242Suzumiya Haruhiko wo Ooini Shizumeru Fullbocco-dan281960631
243University of Western Australia283980622
244Littlechina2848305311
245Drifter's Revenge2851505212
246Erraen285860631
247cthulhuivore2869402134
248ktkr-java2893904213
249Ocamlman2895005221
250Team Cow290130622
251Rhinos290200118
252Cup<T>292040631
253The Chun Council29234064
254FUN292460451
255ICSkies of Blue and F(P)2925504231
256Felspar292560631
257Happy Camels292670631
258The Teddyborg2928502314
259drunken ants2928605221
260foognostic292950127
261Marti293070631
262StreetMagic294650622
263Cal Poly Pomona Computer Science Society29753064
264nishiohirokazu29851064
265United Coding Team29888055
266KuntbucketsAndKuntrags2100630136
267Turn Right Left210067055
268mazeSolver@UTMC2102330343
269Schwarzschild2107120532
270gpfault id-alex 2107250244
271aalto high school21153201513
272The Dudes2115510352
273Engineers Without Boulders21167104411
274The Al-Gore-Rhythms AKA The Doug Boat21177001315
275Team_XIII 211920055
276The Armstrongs2124310514
277casillero del diablo2125570154
278gzoluble213069055
279Chvex Stucture2148470145
280SATiriker136160131
281The unmoving notogawa1423005
282Monkeyget1423005
283Sim1423005
284P Squared1423005
285gb1423005
286mokehehe 1423005
287ocaml users anonymous1423005
288LISA~HackLab-FI1423005
289zetafish1423005
290Puddingforce1423005
291Chicago Blubs1423005
292Nodal Asymmetry1840005
293incognito1840005
294Monadic Cows1840005
295Late Ocamler1840005
296Rufus21840005
297greedy1840005
298The Shiniest of Heisenbugs1840005

понедельник, сентября 08, 2008

Закон больших чисел

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

На большой выборке даже маловероятные события становятся наблюдаемыми.

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

Ещё одно проявление Закона больших чисел в том, что невозможно построить информационную систему гарантированно не содержащую ошибок в данных. Простой пример: Оператор вводит данные вручную. Оператор не идеален, поэтому он делает одну ошибку на 100 записей. Это означает, что на 1 000 000 введенных записей будет порядка 10 000 ошибок. Поскольку такое количество ошибок нас не устраивает, мы садим поверх оператора контроллера, который будет проверять правильность ввода. Пусть контроллер более внимателен и продуктивен, однако и он не идеален, поэтому допускает одну ошибку на 1000 записей. Тогда вероятность ошибки снижается до 10-5 на запись. Однако, на миллионе записей это даст примерно 10 ошибок. Если количество данных неограниченно растет, а так бывает почти всегда, никаким контролем не добиться гарантированного отсутствия ошибок. Даже оценить вероятность ошибки и то не всегда возможно. Люди не механические приборы, к ним паспортов точности не полагается.

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

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

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

понедельник, августа 11, 2008

ICFP '08 Results

Опубликованы результыты первых восьми заездов. Для удобства фаллометрии свел все в одну табличку. Get it and use it well.

Score — сумма по всем восьми заездам.

Команды не допущенные до девятого заезда в табличку не включены.

UPD: Добавил восьмой заезд. Плюс организаторы вернули еще 16 команд, дисквалифицированных по техническим причинам.

TeamScore
1UBE327090
2td329520
3Celestial Dire Badger330350
4Hands Solo330560
5Blue Iris331800
6Team Meh332900
7shinh333270
8NMSU333390
9team_bruno333590
10Team Smartass334470
11CNaml334680
12Error 404334770
13cw336130
14HackerDom_1336740
15Actua337670
16ILL martians337870
17Yeahbut338630
18fireinthedisco2340290
19ais523340450
20Arekuma341070
21TC2341190
22elbereth@utmc341290
23Spore Sept 7th, only $49.99! Play Bejeweled @ popcap.com!341510
24Apathy Kings342900
25LazyBear347940
26SzM348090
27Wile E.352650
28Sir Bedevere the Wise353750
29TeamDJ353980
30Kee355170
31jabber.ru356170
32frank324356270
33Urxae358030
34Malfunctional Programmer358770
35Heklers359580
36PurelyFunctionalInfrastructure361340
37Cup<'t>362370
38Side Effects May Include...362960
39Purple Pointer Eaters363780
40intelliarts365870
41Slow366260
42EdFred367150
4342367510
44The B-Team: 25/26ths as good as the A-Team371520
45a1k0n373610
46RHZ373950
47souris aveugle374140
48LUHPI374310
49little lemon375620
50kstm.org376070
51m1-speedygonzalez377810
52Team Sampou378210
53Five of Six378920
54Mosquito381240
55Eger a Marson381530
56ur 67P385050
57tidder385790
5812a0389440
59Giantslalom390270
60epriestley408520
61Om Nom Nom Nom409070
62Bobry412030

вторник, июля 29, 2008

Nomen est omen

Представим себе гипотетическую ситуацию: некий юноша-с-косичкой подрядился писать программу. Ну хотя бы учет посетителей в библиотеке. (Ещё ни одной приличной не видел) И вот доходят у него руки до учета пользователей и он радостно создает в базе табличку visitors {firstName, lastName, middleName}. А что, у всех буквально есть фамилия, имя и отчество. Вот у его знакомых в родном Крыжополе точно у всех. Да и девочка-библиотекарь, которая заместо аналитика, говорит что так правильно. И вот поступает такая система в эксплуатацию. А там кого только нет: и Александров-Погорельский, Ли Син Цин, и Хосе Луис Мария Педро Фернандос. И вот мучаются библиотекари, стараясь всунуть чуждые имена в прокрустово ложе программы, сыплются проклятья и летят в сторону незадачливого юноши лучики поноса.

Произошло это потому, что незадачливый программист не разобрался в сути моделируемых явлений. На больших объемах данных такой подход очень редко сходит с рук — всегда найдутся выпадающие данные, даже если на первый взгляд их быть не должно. Хороший пример: тройные фамилии вроде бы как запрещены законодательно, по крайней мере просто так её взять не получится. Возникает соблазн добавить проверку, и соблазн довольно опасный. Вероятность того, что системе попадется человек с тройной фамилией довольно велика на большой выборке. Аллах знает, как у них это получается, но сменить человеку фамилию можно только через суд.

Ещё одна распространенная ошибка — трактовать отчество как middle-name. Мне попадался даже один декан, который подписывался Boris A. Gladkih, видимо, не подозревая, что читается это как Борис Афанасий Гладких, что суть нонсенс. Второе имя это именно самостоятельное имя, которое можно использовать отдельно, пусть даже оно и дается в честь отца или деда. Отчество же без имени употребляется исключительно в качестве прозвища и только отдельно от фамилии: «Кузмич — за пивом пойдет». На эти грабли качественно наступили создатели формата fb2.

В наш век всеобщей глобализации правильнее не задумываться над традициями присвоения имен, а признать, что человек может сам выбрать как ему называться. Технологически, ничего сложного в этом нет, если только вы не хотите поддерживать все возможные традиции именования. Зато, если завтра к вам придет посетитель, у которого в паспорте написано «БОЧ рВФ 260602 Вячеславович Воронин-Фролов» вы будете к этому готовы.

среда, июля 16, 2008

ICFP '08 Contest

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

Preambula

Про ICFP contest я узнал начитавшись отчетов и сразуже захотел попробовать. Этот контест выгодно отличается от ненавистных мне «академических» олимпиад и их идиотскими заданиями, не имеющими ни малейшего отношения к реальности. Поскольку по одним субъективными отчетам трудно достоверно оценить явление было решено потрогать воду лапкой прежде чем готовиться к участвовать всерьез. Что и было проделано с величайшим удовольствием. Однако, некоторую подготовку я все же провел: настроил NetBeans с Ruby, создал необходимую структуру папок для проекта, поднял на всякий случай Linux под виртуальной машиной, скачал и запустил LiveCD

Day 0. Landing

За час до начала вылезаю на канал #icfp-contest и наблюдаю там больше 200 человек. С трудом дожидаюсь публикации задания. Большого смысла в этом нет, но хочется уже прочесть его, составить план штурма и отправится спать. Время из-за разницы во времени довольно позднее. В час «X» вся эта толпа, коей набралось уже за 300 человек радостно тянется качать задание и на несколько минут роняет сервер. Наконец я добираюсь до нужного документа и погружаюсь в чтение. Итак, задача этого года, в моем кратком изложении

Есть квадратное поле заданных размеров, представляющее поверхность Марса. На поверхности имеются:
  1. кратеры, в которые можно упасть, насмерть, много;
  2. валуны, о которые можно стукнуться, больно, тоже много;
  3. марсиане, которые норовят сожрать, самоходные, много;
  4. база, дружественная, одна;
  5. марсоход, свой, один.
На поверхность в произвольной точке высаживают марсоход (с довольно реалистичной физической моделью) для которого нужно написать программу управления (общающуюся с сервером по TCP/IP), приводящую его к базе в обход кратеров, валунов и марсиан. Соревноваться в итоге будут программы между собой, у кого лучше, тот и победитель. В деталях, оригинал на 12 страницах.

Прочитав задание, понимаю, что Ruby тут не при делах. Марсоход — железка глупая, не станет ждать пока досчитается, укатится к черту на рога. Решаю применить запасной вариант и использовать Java. Пока разворачивается IDE, лезу качать симулятор, но его ещё не выложили. Основных проблем в задании видится три: 1) Сетевой протокол; 2) Алгоритм управления; 3) Визуализатор для отладки. За пару часов реализую сетевой протокол, описываю необходимые структуры данных и с чистой совестью отправляюсь спать

Day 1. Doctrine: Mobility

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

Day 2. Doctrine: Flexibility

Со вчерашнего дня обнаружилась ещё одна проблема: перерегуляция, приводящая к том, что марсоход пролетает мимо базы. Решил сперва побороть её и ввел эвристики, запрещающие крутые повороты вдали от базы для наведения на цель. С предсказанием все плохо, марсоход едет довольно паршиво, часто падает в кратеры и стукается о валуны. Приседания с параметрами дают немного. Это продолжается до тех пор, пока я не начинаю проверять точность предсказаний в реальном времени. Сперва обнаруживается, что я забыл учесть трение и предсказания скорости не слишком точны. Добавив систему оценки трения и ускорения, получаю точность предсказания скорости до четвертого знака. Выглядит хорошо, но точность предсказания расстояния не изменилась. Проверяю расчеты калькулятором и обнаруживаю, что java.lang.Math принимает аргументы синусов и косинусов в радианах, а я считаю углы в градусах. Правлю и точность hgtlcrfpfybq достигает требуемой. Поскольку нет необходимости в играх с параметрами, устанавливаю предсказания на 5 секунд вперед. Все три тестовые карты проходятся, так что я начинаю искать, на чем бы ещё протестировать. Поскольку возможности достать и померяться прямо в процессе организаторы не предусмотрели народ во всю обсуждает результаты и выкладывает собственные карты. Пытаюсь протестировать на чужих картах и обнаруживаю два факта: а) на рандомных картах сходных с тесовыми все работает идеально; б) стенки, «рюмки», «бутылки», лабиринты и прочие непрерывности вводят марсоход в ступор. На этой прекрасной ноте отправляюсь спать.

Day 3. Doctrine: Initiative

Пенедельник — день рабочий, поэтому за марсоход удается приняться только к вечеру. Проверять на каждом шаге полноценное дерево решений чтобы выбрать оптимальное мне влом. Судя по отзывам не меньше половины участников этим не заморачивались, уповая на отсутствие в реальных тестах стенок. Так что я решаю посвятить оставшееся время отладке и доводке. На марсинан также решено забить. Мой марсоход едет быстро и непредсказуемо, так, что даже я не всегда могу предполагать куда он свернет. Перехватить его марсианином, задача гораздо менее тривиальная, чем объезд препятствий, так что с марсианином он может столкнуться только по чистой случайности. Вычисление радиуса поворота в эвристиках для определения необходимого положения руля значительно помогло. Теперь марсоход едет быстро, оптимально и опасно. Решаю оставить как есть в надежде, что он не свалится в кратер больше двух раз. Пробую ещё пару идей, но они не работают. Сперва пытаюсь объединить пересекающиеся препятствия в одно большое, но точности это не увеличивает, зато существенно замедляет работу. Затем пытаюсь настроить москитный маневр (вместо движения прямо, рулить попеременно влево-вправо для затруднения перехвата), но это ухудшает точность предсказаний, которые на него не рассчитаны. Допиливать предсказания не хочется, поэтому сабмичу, как есть. Выложат результаты, будет видно насколько мои предположения оправдались. 

Conclusions

Участвовать в этом можно, но одному не это делать не слишком приятно. Кучу побочных задач я пропустил, так, а они могли существенно улучшить результат. Если бы у меня был собственный рендерер выводящий внутренне представление, ошибка с предсказаниями была бы отловлена сразу же и хватило бы времени на более изощренный алгоритм. Генератор карт существенно облегчил бы отладку. Даже ознакомиться с достижениями конкурентов не хватило времени. В следующий раз, я планирую собрать команду и подойти к делу серьезно.

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

Date, Time, Interval, and Duration

С представлением времени в большинстве систем творится полный бардак. Ладно, RDF с OWL’ем, там и без этого все плохо, но даже в стандартных библиотеках самых что ни на есть мейнстримных языков полный бардак. Ну что нужно курить чтобы в стандартный класс Date добавить преобразование к Юлианскому календарю? Ни разу не встречал человека, которому бы это потребовалось. Зато вычислять интервал между двумя событиями приходится вручную. Давайте попробуем спроектировать библиотеку для работы со временем правильно. Может хоть кому-нибудь живой пример вправит мозги.

Итак, что такое время для программиста? Это одна координатная прямая, на которой определена выделенная точка «сейчас», делящая прямую на «прошлое» и «будущее». Примитивные племена на этом и останавливаются, оперируя тремя понятиями: «было», «есть» и «будет». Современному человеку требуется больше: время должно быть измеримо. Это позволит производить вычисления (до сеанса осталось полчаса) и учитывать порядок событий ([сначала]он мне в глаз, а [затем] я ему в ухо) от которого и до причинно-следственной связи недалеко. Для того чтобы сделать время измеримым на прямую произвольным образом добавляют фиксированную выделенную точку «0». Исторически сложилось так, что в разных культурах эту точку добавляли по-своему. Это мог быть день коронования императора, начало определенного года, произвольно выбранный момент времени и даже время «сотворения мира». В мире UNIX, например, это полночь 1 января 1970 года.

С другой стороны люди привыкли к довольно неудобной для вычислений системе предстваления времени, связанной с циклами вращения Земли. Опять же, в разных культурах к этой проблеме подходили по разному. В результате год начинается в разное время и по разному делится на месяцы в зависимости от культуры. Более того, в разных культурах привычные способы записи времени сильно отличаются, даже если системы счисления времени совпадают. Та же американская ММ/ДД/ГГ и русская ДД.ММ.ГГ.

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

Поскольку продолжительность суток растет, каждые несколько лет к UTC добавляют секунду, чтобы компенсировать замедление. Это тоже усложняет точные расчеты, однако, пока не вызывает проблем, поскольку единой системы точного времени затрагивающую все — от GPS приемников до кофеварок не создано.

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

Первое, что нам требуется, это момент времени (Timestamp) заданный с максимальной возможной точностью в некоторой системе отсчета, хоть UNIX time. Этот класс является платформозависимым, поскольку умеет работать с системным таймером. Никаких преобразований или вычислений этот класс делать не должен. Очень часто требуется работать с моментами времени с точностью до минуты, дня или года, в этом случае максимальное разрешение тут только мешает. Для некоторой частых случаев можно определить классы Date и DateTime и точностью, соответственно, до дня и до секунды. Timestamp должен корректно поддерживать сравнение отметок времени с максимальной и ограниченной точностью.

Второе — интервал между двумя моментами времени (Interval) Интервал можно представить двумя моментами времени: начало интервала и конец интервала. Интервал должен уметь вычислять свою продолжительность. Кроме того, нужна возможность зная начало или конец интервала и продолжительность, получить интервал.

Третье — продолжительносить (Duration) Внутри продолжительность хранится в максимально возможной системной точностью.

Для каждой из трех сущностей потребуется два интерфейса: *Parser и *Formatter имплементации которых служат для преобразования сущностей из строки и к строке (или прочим типам). Кроме форматирования, их зона ответственности — преобразование к другим системам представления времени, например к тому же юлианскому календарю.

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

duration = Duration.measure do
...
end

вторник, июня 24, 2008

RuPyRu 2008. Конференция

Пару слов о самой конференции. В целом RuPyRu оправдала мои ожидания: хорошая, добротная провинциальная конференция.

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

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

Познать механизм деления докладов на «общий» и «специальный» потоки мне не удалось. Интересные доклады были и там и там. Я бы предложил деление на «пользовательский» и «авторский» потоки. В первом — краткие обзорные доклады, посвященные чужим технологиями, во втором — доклады авторов о собственных разработках и доклады экспертов. Понравилось, что Ruby и Python не были разнесены на отдельные потоки, что позволило познакомиться с конкурентными технологиями.

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

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

Из интересного для меня оказались совершенно не раскрыты темы развертывания Rails и Django приложений, использования динамических языков для кодогенерации, использования Ruby и Python в качестве скриптовых языков внутри приложения и создания DSL на базе динамических языков.

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

RuPyRu 2008. Омск

памятник Ленину

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

памятник Оленям

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

памятник Сантехнику

В центре города нам встретился памятник Говночерпию Сантехнику, из вечно актуальной серии памятников рабочему классу (памятники Электрику и Дворнику в Томске) Расположенный прямо на тротуаре, он символизирует близость рыцаря труб и задвижек к народу, а умиротворенное выражение лица убеждает в чистоте его намерений.

граффити

Из современных форм искусства нам встретилось вот такое трафаретное граффити в стиле Fallout. Сложно сказать, что оно должно означать, но прикольно. Я всегда считал, что за трафаретным граффити будущее уличной живописи.

мотоцикл

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

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

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

среда, июня 18, 2008

Just few photos

Вернулись со сплава по Средней Катуни. Выяснилось несколько забавных вещей:
  • Камера µ 770 SW + запасной аккумулятор + 2Гб флешка категорически рулят. Мочить камеру водой не страшно, поэтому вдохновившись радостно наснимали 1.5Гб фотографий, из которых, правда, половина — чье-то весло или каска.
  • С каждым годом количество крупных вещей уменьшается, а мелких — растет приближаясь к стандарту «все необходимое можно распихать по карманам»
  • В следующий раз в качестве полезной вещи нужно брать термос с горячим чаем. Правильно зафиксированный, он, скорее всего, не разобьется.
  • Свой котелок и горелку мы совершенно напрасно не взяли, понадеявшись на общественный. В результате, большую часть времени обходились без чая потому, как дождавщись когда он согреется, уже никакого чая не хочется.
  • После Алтая воняет даже Академгородок:-(
Несколько пейзажей без сюжета:

среда, июня 11, 2008

Declarative interface

Gineer, попросил меня описать, что я понимаю под декларативным интерфейсом. Признаться, идея пришла мне в голову прямо здесь, но я попытаюсь оформить ее в разумную форму. Любой прибой, по сути своей является черным ящиком для пользователя. Разговаривая по телефону, можно ничего не знать о модуляции, СВЧ технике или принципах маршрутизации голосового траффика. Декларативным я называю интерфейс, построенный в терминах потребностей пользователя, а не средств их достижения. По идее, любой интерфейс любого прибора может быть декларативным, однако, на практике это не так. Например, мой телефон требует для установки будильника следующей последовательности команд: Меню > Развлечения > Будильники > Выбор одного из трех возможных > Включение > Установка времени > Установка режима "повторять ежедневно/по будням/никогда" > Выбор мелодии > Подтверждение. Это идиотский интерфейс, потому что он заставляет меня думать не об исходной потребности, а о деталях реализации. Мне нужно, чтобы телефон разбудил меня в указанное время. Все остальное лишь опции. Для чего мне знать, сколько у телефона будильников (готов спорить, их три, только для того, чтобы влезли на один экран в интерфейсе), которые из них включены и как именно он меня собирается будить. Декларативным будет примерно такой интерфейс: разбуди_меня вермя|интервал [периодичность] [способ], где вермя может быть в любом формате от "в 1130" до "завтра в 8", а то и вовсе интервал: "через 2 часа". Конечно, это потребует продвинутого date/time picker, но изваять такой уже давно не проблема. Еще понадобятся две функции: покажи_список_будильников и отмени_будильник > выбор будильника Может показаться, что приведенный синтаксис относится только к CLI, однако это не так. Аргументы команды вполне могут выбираться самостоятельным диалогом. В GUI команду можно представить в качестве мастера, опциональные параметры которого легко пропустить или установить в любом порядке. Из идеи декларативного интерфейса есть одно интересное следствие, которое стоит обдумать. Если более строго описать синтаксис UNIX команд с учетом зависимостей, типов и связей параметров, возможно, удастся помирить GUI с CLI. Хотя бы посредством автогенерации интерфейсов.

четверг, мая 01, 2008

What do you need to know

Как вести проектную документацию? Оставим в стороне ГОСТы, RUP, фантазии некомпетентных и прочую фигню и сосредоточимся на одном вопросе: "Какая документация вам нужна в проекте, рассчитанном на несколько лет?" Проекты в стиле "Сделал и забыл" (а это большая часть аутсорсинга) в документации не нуждаются и останутся за скобками. Итак, поехали:

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

Как именно работать с требованиями много говорили и без меня. Единственное, что стоит отметить: чем глубже проанализированы требования, тем легче. Требование "заказчик хочет зеленую кнопку" менее ценно чем "интерфейс должен, по возможности, соответствовать программе X с которой у пользователей есть опыт работы". В случае, если кнопку не удастся сделать зеленой, хотя бы понятно с какой стороны начинать переговоры по поиску компромисса.

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

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

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

Geoid

Земля имеет форму шара, Забавно видеть хуй омара. Азбука
А вот хрен — возвопят просвещенные — не шара, а геоида. Эта феерическая глупость передается из уст в уста. Не исключено, что она уже просочилась даже в школьные учебники. По крайней мере в русскую википедию просочилась:
Геоид- фигура, отражающая форму Земли, важное понятие в геодезии.
Помилуйте, геоид не имеет решительно никакого отношения к форме Земли. Более того, изобретать просто так фигуру «описывающую форму Земли» бессмысленно. Однако, математики давно прослыли чудаками и эта бессмысленность не бросается обывателю в глаза. Если вы приглядитесь к картинке, геоид довольно слабо напоминает форму Земли. Откуда же он взялся? На самом деле геоид имеет вполне практическое применение. Как вы все наверняка знаете, географические координаты (те которые широта и долгота) суть координаты сферические. Однако, поскольку земля не сфера и не эллипс, возникает вопрос: относительно какой сферы задаются географические координаты? Математики давно предложили работающее решение: использовать мнимый эллипсоид вращения как-то худо-бедно совпадающий с земной поверхностью. Для вычислений идеально, однако, стоя в чистом поле довольно трудно этот эллипсоид обнаружить. Он же математическая абстракция. Мудрые математики и тут не сплошали. Они расположили эллипсоид так, чтобы короткая ось его совпадала с осью вращения земли, в центр его совпадал с центром масс Земли или был смещен относительно него на какое-то расстояние. Из физики мы знаем, что ось вращения проходит через центр масс. Осталась малость, вычислить его положение относительно поверхности. Для это была проведена гравиразведка все поверхности земли и построен геоид — фигура на поверхности которой сила тяжести постоянна и совпадает со средней силой тяжести на поверхности моря. Этого достаточно чтобы определить центр масс геоида, который совпадает с центром масс Земли. Зная, где находится центр масс, мы можем поместить в центр земли эллипсоид (умозрительно, конечно) и использовать его для определения координат.

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

Half-life

Период полураспада для большинства нововведений составляет две недели. Вне зависимости от того в чем состоит идея: вести документацию в wiki или штрафовать за неположенное распитие пива. Каждый может припомнить несколько довольно хороших (или ужасных) идей, которые «не пошли». Связано ли это с тем, что идеи плохие? Нет, распадаются и вполне хорошие начинания. Со стороны видно, что внедрить что-то сложнее чем кажется. Любая система обладает некоторым запасом инерции и социальные системы не исключение. После того как программистам наказали указывать номер бага при коммите обязательно придется некоторое время следить чтобы это правило выполнялось. И лишь через какое-то время оно перейдет в разряд «здесь так принято». Никогда, ни одно правило не будет выполняться только потому, что оно есть. Время принятия зависит от того, насколько нововведение выгодно конкретным исполнителям. Дневные отчеты могут быть офигенно полезными для проекта и для компании в целом, но если программисты не видят в них смысла, они будут забрасываться при каждом удобном случае. В идеальном случае, когда все без исключения исполнители понимают, какую пользу им принесет нововведение, они способны сами его внедрить. На практике это случается довольно редко. Итак, несколько практических рекомендаций:
  • Продумывая любое изменение обязательно оцените ресурсы потребные на его внедрение;
  • Назначьте ответственных за внедрение;
  • Донесите до исполнителей выгоды, которые им сулит нововведение;
  • Если нововведение не сулит ничего хорошего исполнителям, обеспечьте им выгоду искусственно;

среда, апреля 09, 2008

Alone

Принято считать, что в современном мире для любой серьезной вещи нужна команда. Поговорки-пословицы всякие: «один в поле, волкам на потеху», «семеро одного не боятся», «команда — все, остальное — волшебные пузырьки». Вроде бы, как само собой разумеется, что производительности одного человека ни для каких серьезных задач недостаточно, а вот команда это сила. Ещё бы, на один только чай команда тратит в день больше времени, чем один человек может удалить работе в неделю. Доходит до того, что привычный к командной работе программист смотрит на индивидуальную задачу и изрекает: «да тут мне одному на полгода». И действительно, провозится с задачей 6 месяцев. В то же время, за стенкой может сидеть человек, стабильно решающий подобные задачи за месяц каждая. Производительность лучших и худших программистов отличается примерно на порядок. Всякий имеющий доступ к метрикам может получить эти данные самостоятельно. Вопрос в том, за счет чего так получается и какую выгоду можно извлечь, если работать в одиночку. Самое очевидное, это работа с постановкой задач. Любую задачу можно решать разными способами. К тому моменту, как задача доходит до программиста через кучу промежуточных звеньев, она обрастает коркой фантазий, зачастую не имеющих никакого отношения к исходной проблеме. Например, клиент хочет, чтобы работающие с программой менеджеры не забывали о назначенных встречах. Можно реализовать управление встречами в программе, а можно обратить внимание, что в компании уже используется для этого Outlook с которым довольно легко интегрироваться. Аналогичные ситуации возникают и при внутреннем взаимодействии. Быстродействующий программист не станет ничего делать пока не выяснит, какую именно проблему он должен решить. Второе, это правильное использование готовых средств. Если собственное решение занимает три недели, а применение готового — несколько часов на чтение документации и пару дней на исправление багов в чужом решении, это сэкономит две недели. В другом случае, частное решение пишется за неделю, а на использование существующего могут уйти недели. Умение верно оценить, сколько времени займет переиспользование, а с сколько собственное решение и есть искусство быстрой сборки из кубиков. У быстродействующего программиста нет времени изобретать все свои велосипеды самостоятельно. На третьем месте — острая пила. Инструмент должен быть адекватен решаемым задачам. Это касается как языков и библиотек, так и окружения. В эту бочку и владение инструментами (от IDE до shell) и DSL, и метапрограммирование с кодогенерацией. Отдельные аспекты «заточки пил» освещены изрядно. Пилы быстродействующего программиста всегда острые. Если хотите готового чеклиста:
  • Может ли исходная проблема быть решена более простым способом?
  • Можно ли изменить условия задачи так, чтобы она решлась существенно проще?
  • Есть ли для задачи готовое решение?
  • Существует ли инструмент, позволяющий решить данную задачу быстрее?

среда, марта 26, 2008

Meeting

-Пойдем с нами, помитингуем. -Надолго? -Да нет, часа на полтора.
Знакомо? Митинги — хороший способ осознать какова сила командной работы. За полтора часа разговоров команда тратит столько времени, сколько тебе в одиночку не потратить за неделю. На первый взгляд, кажется что время тратится с пользой. Люди говорят, спорят, обсуждают, но стоит поймать выходящего из комнаты для совещаний и спросить, что, собственно, обсуждалось, и что было решено, как будет получен ответ в стиле: «Ну взаимодействие системы, А с подсистемой B. Петро будет спеку на интерфейс писать." Помилуйте, что тут можно было обсуждать полтора часа? А ведь существуют компании где на подобные совещания тратится больше половины рабочего времени, а большая часть «митингующих» рисует чертиков. Между тем способ сделать собрания эффективными давно известен всем желающим. Нужно лишь соблюдать несколько простых правил:
  • Прежде чем назначить совещание нужно составить план, в котором будут перечислены вопросы вынесенные на обсуждение и предполагаемое время обсуждения каждого. Это позволит определить список заинтересованных лиц и оценить время необходимое на совещание. С планом необходимо ознакомить всех участников заранее, а не прямо на месте. Лучше, если участники будут пропускать несущественные для себя вопросы, чем рисовать чертиков.
  • Если в процессе обсуждения поднимается новый вопрос, план ни в коем случае не меняется на лету. Вместо этого назначается отдельное обсуждение с собственным планом и отдельными участниками. Если участники будут уверены в том, что план не изменят на лету, они смогут пропустить несущественные для них вопросы.
  • На любом совещании должен быть председатель. Его задача следить за соблюдением регламента, прерывать затянувшиеся обсуждения и вести протокол. По окончании совещания протокол выдается всем участникам или публикуется. Протокол нужен обязательно. Иначе уже через полчаса непонятно почему было принято какие-то решения, а на следующий день забываются и сами решения.
  • Любой участник может поручить любому другому участнику говорить от своего имени. Это позволит сэкономить время самым продуктивным сотрудникам, способным сделать за время совещания что-то более полезное.
  • Если кто-то из приглашенных счел возможным не придти, и не доверил свой голос другим участникам, это автоматически означает его согласие с любым принятым решением. 
Более подробно этот подход описан у ДеМарко в «Deadline». Там же есть и примеры удачно проведенных совещаний.

понедельник, марта 17, 2008

Code conventions

Через пару недель проекта, особенно если оный был расчитан на достаточно долгий срок, всегда находится гаврик, считающий, что для успешного существования проекта необходимо немедленно, пока не слишком поздно, написать code conventions. Не будучи вовремя остановленным, он за один присест порождает страниц, эдак, двадцать, заполненных беспорядочными правилами, вроде:
Имена переменных должны удовлетворять camelCase; Недопустимо обращение через две точки, во имя закона Деметры; Бинарные операторы должны быть отделены пробелами с обоих сторон; В сеттерах нужно использовать this; Забытая в микроволновке еда считается общей; и т.д.
Обычно такой документ живет ровно две недели, затем перемещается в архив, извлекаемый оттуда только для того чтобы продемонстрировать его новичкам. Поскольку документ изначально не соблюдался и разительно отличается от негласных соглашений принятых в коде, новички тоже откладывают его в сторону. От проекта к проекту такая ситуация повторяется с завидной регулярностью. Причина в том, что любая дополнительная активность, как написание комментариев, проверка кода на соответствие соглашениям, комментарии к коммиту в VCS требует дополнительных затрат. Если преимущества от этих действий неочевидны человек склонен «забывать» их делать. Поэтому введение в проекте code conventions автоматически означает появление роли следящего за их соблюдением. Для того чтобы решить проблему недостаточно опубликовать документ, каким бы хорошим он ни был. Нужна постоянная активность,  это везде так. Отлично, но следить за соблюдением правил, описанных на двадцати страницах, отнимает прорву времени. И это вторая причина, по которой затея с code conventions проваливается. Теперь, когда мы добрались до сути, мы можем сформулировать рекомендации для написания соглашений. Но, сперва, давайте обозначим проблему, которую мы собираемся решать. Разные программисты предпочитают разные стили написания кода. Если несколько разных стилей смешиваются в одном файле, этот файл становится трудным для чтения. Разнобой в стиле выглядит неряшливо и поощряет неряшливость уже в самом коде. Соглашения о коде призваны устранять неоднозначности в выборе несущественных деталей оформления, в идеале сужая пространство вариантов до одного. Как же писать code conventions? Определите кто ваши программисты. Кто сказал: «Они все здесь»? А как же библиотеки, которыми вы пользуетесь. Их интерфейсы должны вашим соглашениям. Естественно, вы не в силах заставить сторонних разработчиков соблюдать ваши стандарты, но вы всегда можете подогнать стандарты под них. В противном случае использование библиотек будет выбиваться из общего стиля и увеличивать энтропию проекта. Все соглашения можно разделить на две части: поддающиеся автоматическому переформатированию и не поддающиеся. Переформатированию поддаются такие вещи как количество пробелов, формирование отступов, расположение скобок, длина строк и т.п. Лучший способ их публикации, это положить в VCS файл настроек для IDE. Можно также настроить VCS сервер на вызов автоформаттера перед каждым коммитом и забыть о них навсегда. Описывать их в документе совершенно не обязательно. Не стоит поручать человеку делать то, что сумеет машина. Не поддаются переформатированию такие вещи, как имена файлов, переменных, пакетов и классов, стиль работы с исключениями, расположение файлов. Продвинутые автоформаттеры умеют отлавливать ошибки, но исправлять из автоматически невозможно. Поэтому все что не поддается автоформатированию придется описать в документе явно. Документ содержащий code conventions не должен быть большим. Четырех страниц более чем достаточно. По крайней мере ограничение объема избавит вас от соблазна включать в документ правила пользования микроволновкой. Если есть возможность, не изобретайте велосипедов. Почти всегда можно взять готовые документы у разработчиков языка или людей в нем авторитетных. Вот несколько таких примеров: Утилиты для автоформатирования кода: