Как стать программистом: краткий, исчерпывающий и субъективный ответ Как стать программистом: краткий, исчерпывающий и субъективный ответ Роберт Л. Рид Copyright © 2002, 2003 Robert L. Read Copyright Copyright © 2002, 2003 Robert L. Read Разрешается копировать, распространять и/или изменять этот документ в соответствии с условиями лицензии GNU Free Documentation License (GNU FDL) версии 1.2 или любой более поздней версии, опубликованной фондом Free Software Foundation, с одним неизменяемым разделом "История (на февраль 2003)", без текста на передней обложке и со следующим текстом на задней обложке: "Исходная версия этого документа написана Робертом Л. Ридом безвозмездно и посвящается программистам компании Hire.com". Текст лицензии приведен в разделе "GNU Free Documentation License". 2002 --------------------------------------------------------------------- Посвящение Посвящается программистам компании Hire.com Содержание 1. Введение 2. Начинающий Индивидуальные навыки Учитесь отлаживать Отладка методом разбиения проблемы Устранение ошибки Отладка с помощью журнала Понимание проблем, связанных с производительностью Как исправлять проблемы производительности Как оптимизировать циклы Как работать с издержками ввода-вывода Как управлять памятью Как бороться с нерегулярными ошибками Как научиться проектировать Как проводить эксперименты Командные навыки Почему важна оценка Как оценить время на реализацию Как находить информацию Как использовать людей в качестве источника информации Как разумно вести документацию Как работать с плохим кодом Как использовать системы контроля версий Как использовать юнит-тесты Отдыхайте, если зашли в тупик Как понять, что пора идти домой Как взаимодействать с непростыми людьми 3. Опытный Личные навыки Как не потерять мотивацию Как быть всесторонне надежным? Как находить компромисс между временем и памятью Как проводить стресс тесты Как сохранить баланс между краткостью и абстрактностью Как научиться новым навыкам? Учитесь печати Как проводить интеграционное тестирование? Языки описания данных Сложные инструменты Как анализировать данные Командные навыки Как управлять временем разработки Как управлять рисками, связанными с программным обеспечением третьих лиц Как взаимодействовать с консультантами Как сообщить достаточное количество информации Как честно не соглашаться и не пострадать от этого Оценка Как балансировать между качеством и временем разработки Как управлять зависимостями программы Как определить, что программа еще не готова Как выбрать между покупкой или разработкой Как расти дальше Как оценивать соискателей Как узнать, когда применять модные компьютерные знания Как разговаривать с не-инженерами 4. Более сложные темы Техническая оценка Как отличить сложное от невозможного Как использовать встраиваемые языки Выбор языков программирования Разумные компромиссы Как бороться с прессом планирования Как понимать пользователя Как получить продвижение Обслуживая свою команду Как развивать таланты Как выбирать, над чем работать Как получать все от вашей команды Как разделять проблемы Как справляться со скучными задачами Как находить поддержку для проекта Как развивать систему Как правильно общаться Как говорить людям вещи, которые они не хотят слышать Как обращаться с мифами менеджмента Как обращаться с организационным хаосом Глоссарий А. Б. История (к февралю, 2003) В. Лицензия свободной документации GNU ПРЕАМБУЛА СФЕРА ДЕЙСТВИЯ, ТЕРМИНЫ И ИХ ОПРЕДЕЛЕНИЯ КОПИРОВАНИЕ БЕЗ ВНЕСЕНИЯ ИЗМЕНЕНИЙ ТИРАЖИРОВАНИЕ ВНЕСЕНИЕ ИЗМЕНЕНИЙ ОБЪЕДИНЕНИЕ ДОКУМЕНТОВ СБОРНИКИ ДОКУМЕНТОВ ПОДБОРКА ДОКУМЕНТА И САМОСТОЯТЕЛЬНЫХ ПРОИЗВЕДЕНИЙ ПЕРЕВОД РАСТОРЖЕНИЕ ЛИЦЕНЗИИ ПЕРЕСМОТР УСЛОВИЙ ЛИЦЕНЗИИ ПРИЛОЖЕНИЕ: Порядок применения условий настоящей Лицензии к вашей документации Глава 1. Введение Содержание Быть хорошим программистом сложно и почетно. Самое сложное при работе над программным проектом, это достичь взаимопонимания между вами, вашими коллегами и заказчиком. Написание компьютерных программ имеет важное значение и требует высоких умственных способностей и навыков. Но это просто детский лепет по сравнению со всем остальным, что хороший программист обязан сделать, чтобы программная система стала успешной как для заказчика, так и коллег, за которых программист частично тоже в ответе. В этом эссе я попытаюсь резюмировать, как можно более кратко, те вещи, которые я хотел бы, чтобы кто-нибудь объяснил мне, когда мне был 21 год. Эти вещи очень субъективны и, следовательно, это эссе обречено быть личным и слегка самоуверенным. Я ограничусь проблемами, с которыми программисту, очень вероятно, придётся столкнуться в своей работе. Нередко эти проблемы и их решения имеют настолько общечеловеческий характер, что мои слова будут звучать как нравоучение. Я надеюсь, что несмотря на это эссе будет полезно. Компьютерное программирование преподают на курсах. Замечательные книги "The Pragmatic Programmer" [Prag99], "Code Complete" [CodeC93], "Rapid Development" [RDev96] и "Extreme Programming Explained" [XP99] обучают программированию и дают основы понимания того, как стать хорошим программистом. Перед чтением этой статьи или параллельно с ним следует, безусловно, прочесть статьи Пола Грэма (Paul Graham)[PGSite] и Эрика Реймонда (Eric Raymond)[Hacker]. В отличие от этих замечательных трудов в данной статье подчеркиваются социальные проблемы и дается всесторонний обзор всех тех навыков, которые я считаю необходимыми. В этом эссе термин Начальник - это человек, который назначает работу. Я использую слова бизнес, компания и сообщество, как синонимы, за исключением тех случаев, где бизнес - это создание денег, компания - это современное место работы, и сообщество - это в основном люди, которые делят с вами преданность Добро пожаловать в сообщество. Глава 2. Начинающий Оглавление Индивидуальные навыки Учитесь отлаживать Отладка методом разбиения проблемы Устранение ошибки Отладка с помощью журнала Понимание проблем, связанных с производительностью Как исправлять проблемы производительности Как оптимизировать циклы Как работать с издержками ввода-вывода Как управлять памятью Как бороться с нерегулярными ошибками Как научиться проектировать Как проводить эксперименты Командные навыки Почему важна оценка Как оценить время на реализацию Как находить информацию Как использовать людей в качестве источника информации Как разумно вести документацию Как работать с плохим кодом Как использовать системы контроля версий Как использовать юнит-тесты Отдыхайте, если зашли в тупик Как понять, что пора идти домой Как взаимодействать с непростыми людьми Индивидуальные навыки Учитесь отлаживать Отладка – краеугольный камень в фундаменте программирования. Первоначально этим словом обозначалось удаление ошибок, но на практике важнее другой его смысл – исследование хода выполнения программы. Программист, не владеющий навыками эффективной отладки, подобен слепцу. Идеалистов, которые считают более значимыми проектирование, анализ, теорию сложности или что-то еще, программистами-практиками не назовешь. Практики живут в несовершенном мире. Даже гений вынужден иметь дело с кодом, созданным во внешнем мире крупными компаниями-разработчиками, организациями вроде GNU и его собственными коллегами. Этот код по большей части неидеален, да и документирован посредственно. Тот, кто не умеет зрительно представить выполнение такого кода, рискует вылететь из седла на малейшем ухабе. Зрительное же представление зачастую можно получить только путем эксперимента, то есть отладки. Предмет отладки – выполнение программы, а не программа как таковая. При покупке продукта у крупной компании-разработчика видеть саму программу обычно незачем. И все же возникают случаи, когда код ведет себя не так, как описано в документации (типовой, но очень эффектный пример – падение всей системы), либо когда документация о чем-то умалчивает. Еще чаще бывает, что пользователь, допустивший ошибку, не в состоянии понять, в чем же она заключается. Это неизбежно означает, что либо не вполне верны какие-то предположения, либо возникла некая непредвиденная ситуация. Бывает, что код удается волшебным образом заставить работать, внимательно его просмотрев. Если не вышло, придется заняться отладкой. Чтобы зрительно представить ход выполнения программы, нужно иметь возможность запускать код и производить некоторые наблюдения. Этот процесс может быть наглядным, если наблюдения касаются, например, изображения на дисплее или промежутка времени между двумя событиями. Но во многих других случаях наблюдать приходится за тем, что обычно скрыто – например, за состоянием переменных внутри кода, за выполняющимися в данный момент строками кода, за тем, верны ли определенные утверждения в отношении сложной структуры данных. Скрытое должно стать явным. Типовые приемы исследования «внутренностей» выполняемой программы можно распределить по следующим категориям: отладка при помощи специализированных средств; отладочная печать, то есть внесение в программу временных изменений для вывода информации; а также ведение журнала, то есть создание постоянного представления хода выполнения программы в виде журнала событий. Средства отладки (если они надежны и доступны) – это замечательно, но отладочная печать и ведение журнала даже полезнее. Средства отладки обычно отстают в развитии от языка, поэтому могут в некоторый момент оказаться недоступными. Кроме того, использовать их не всегда целесообразно, поскольку при этом слегка меняется ход выполнения программы. Наконец, для некоторых видов отладки, таких как проверка истинности определенных утверждений в отношении громоздкой структуры данных, написание кода и изменение хода выполнения программы необходимо по определению. Полезно разбираться в отладочных средствах (если они надежны), но крайне важно уметь применять и другие два метода. Начинающие иногда боятся отладки, если она связана с изменением кода. Их можно понять, ведь это напоминает хирургическое вмешательство. Но необходимо научиться задавать коду встряску. Экспериментируйте, отдавая себе отчет в том, что от этих временных изменений код в любом случае не ухудшится. Тот, кто испытывает подобные страхи, должен найти себе наставника – споткнувшись на них, многие так и не вырастают в хороших программистов. Отладка методом разбиения проблемы Отладка – увлекательный процесс, ведь все начинается с загадки. По задумке код должен делать что-то одно, но делает нечто совершенно другое. Не всегда все так просто – реальность иногда превосходит плоды самого смелого воображения. Отладка требует творческого подхода и изобретательности. Если и существует единый принцип отладки, то он заключается в применении к загадке метода «разделяй и властвуй». Рассмотрим для примера программу, которая должна последовательно выполнить десять действий. При запуске происходит сбой. Запрограммирован он не был, а значит, мы столкнулись с загадкой. Изучая выходные данные, мы обнаруживаем, что первые семь последовательных действий были выполнены успешно. Три последних действия в выходных данных не отражены, и загадка, таким образом, упростилась: «сбой произошел на 8-м, 9-м или 10-м действии». Можно ли поставить опыт, который позволит найти действие, вызвавшее сбой? Конечно. Для этого можно прибегнуть к помощи отладчика или добавить инструкции отладочной печати, имеющиеся в используемом языке после 8-го и 9-го действия. После повторного запуска программы загадка вновь упрощается и звучит, например, так: «сбой произошел на 9-м действии». Я считаю, что надо ни на минуту не выпускать из вида, в чем именно заключается загадка – это помогает сосредоточиться. Когда над решением проблемы напряженно трудится сразу несколько человек, легко позабыть о том, какая из загадок наиболее важна. Отладка по принципу «разделяй и властвуй», так же как и разработка алгоритма, имеет важную особенность: если загадку всякий раз удается разбить примерно посередине, понадобится не слишком много разбиений, и отладка не затянется. Но как найти середину загадки? Здесь-то и понадобятся подлинно творческий подход и опыт. Необстрелянному новичку представляется, что пространство потенциальных ошибок включает каждую строчку исходного кода. Его пока еще недостаточно проницательный взгляд не способен охватить другие программные аспекты: пространство исполняемого кода, структуру данных, систему управления памятью, взаимодействие с внешним кодом, чреватый ошибками код и код тривиальный. В глазах опытного программиста эти дополнительные аспекты формируют несовершенную, но очень полезную умозрительную модель, которая подсказывает, что может пойти не так. Такая модель и помогает в эффективном поиске середины загадки. Разбив пространство потенциальных проблем на равные части, нужно попытаться решить, в какой из них содержится ошибка. В простейшем случае загадка формулируется так: «Какая одиночная неизвестная строка кода вызывает сбой программы?» В этом случае следует задаться вопросом: «Выполняется ли эта неизвестная строка до или после строки, которая должна выполняться примерно посередине программы?» Ошибка не всегда ограничена одной строкой или даже одним блоком кода, на такую удачу обычно рассчитывать не приходится. Часто загадка звучит скорее так: «Либо в графе имеется указатель на неверный узел, либо не работает алгоритм добавления переменных». Чтобы исключить одну из частей проблемы в этом случае, может потребоваться написать небольшую программу для проверки корректности всех указателей в графе. Устранение ошибки Я намеренно отделяю процесс исследования хода выполнения программы от процесса исправления ошибки. Но слово «отладка» означает, конечно, и устранение ошибки. В идеальном случае можно досконально разобраться в коде, и тогда наступит момент озарения, когда ошибка и способ ее исправления станут очевидными. Но так бывает не всегда, поскольку программа нередко задействует недостаточно документированные системы, внутрь которых не заглянешь. В других случаях код настолько сложен, что досконально разобраться в нем не представляется возможным. При исправлении ошибки желательно сокращать объем изменений до минимума. Не исключено, что улучшения требует и еще что-нибудь, но не пытайтесь исправить сразу все. Старайтесь придерживаться научного подхода и изменять за один раз одну и только одну деталь. Лучше всего найти способ легко воспроизводить ошибку, внести исправление и, запустив программу еще раз, убедиться, что ошибка устранена. Разумеется, иногда приходится менять больше одной строки, но на концептуальном уровне следует по-прежнему вносить одно атомарное изменение, необходимое для исправления ошибки. Бывает, что в коде имеется на самом деле не одна, а несколько ошибок. Вам придется решить самостоятельно, как выделить ошибки, и исправить их по одной. Иногда неясно, что должна делать программа, или, в чем состоял исходный замысел ее автора. В этом случае призовите на помощь опыт и здравый смысл и придайте коду смысл по собственному разумению. Решите, что он должен делать, прокомментируйте его или уточните его назначение другими способами, а потом заставьте его соответствовать новому назначению. Для этого нужны навыки среднего или высокого уровня, и выполнить такую задачу иногда сложнее, чем переписать функцию «с нуля». Но реальному миру часто недостает порядка. Если систему нельзя переписать, ее может потребоваться исправить. Отладка с помощью журнала Ведение журнала – это практика создания системы, которая порождает последовательность информативных записей, называемую журналом. Отладочная печать, по сути, тоже порождает простой (как правило, временный) журнал. Абсолютных новичков вынуждает использовать журналы ограниченность их познаний в программировании. Системных архитекторов вынуждает использовать журналы сложность системы. Объем информации, которая содержится в журнале, может допускать настройку. В идеале – прямо по ходу выполнения программы. Вообще говоря, журналы предоставляют три основных преимущества. Журналы могут содержать полезную информацию о трудновоспроизводимых ошибках (например, когда ошибки, возникающие в производственной среде, не удается воспроизвести в тестовой). Журналы могут использоваться в качестве источника статистических данных, относящихся к производительности, таких как промежуток времени между двумя инструкциями. Настраиваемые журналы позволяют собирать информацию общего вида, которую можно использовать для устранения непредвиденных специфических проблем без модификации и повторного развертывания кода в процессе отладки. Количество записываемых в журнал данных – это всегда компромисс между информативностью и лаконичностью. Слишком большой объем информации удорожает журнал и создает эффект «замыленного глаза», по вине которого трудно найти то, что нужно. Если информации слишком мало, она может просто не содержать необходимых сведений. Вот почему так полезно предоставлять возможность настройки. Запись журнала содержит обычно указание на соответствующее место в исходном коде, выполняемый поток (если это имеет смысл), точное время выполнения и, как правило, дополнительные полезные сведения, такие как значение какой-либо переменной, объем свободной памяти, число объектов данных и т. д. Инструкции, выводящие сведения в журнал, разбросаны по всему исходному коду, но особенно много их в важных функциональных узлах и в местах, чреватых ошибками. Каждой инструкции можно назначить определенный уровень и создавать запись в журнале только в том случае, если система настроена для вывода информации этого уровня. Журнальные инструкции нужно проектировать так, чтобы они помогали в устранении ожидаемых проблем. Нужно учитывать потенциальную необходимость измерения производительности. При наличии постоянного журнала отладочную печать можно также реализовать в форме журнальных записей, и некоторые отладочные инструкции могут впоследствии быть добавлены в систему ведения журнала на постоянной основе. Понимание проблем, связанных с производительностью Учиться разбираться в производительности работающей системы придется неизбежно и по той же причине, что и учиться отладке. Даже если стоимость собственноручно написанного кода известна точно и отчетливо, он обращается к другим программным системам, наблюдение и контроль над которыми заметно осложнены. Как бы то ни было, на практике решение проблем, связанных с производительностью, слегка отличается от типичных задач отладки и несколько проще. Предположим, вам или вашим заказчикам кажется, что система или подсистема работает слишком медленно. Прежде чем пытаться ускорить ее, нужно мысленно смоделировать причины ее невысокого быстродействия. Чтобы определить, на что реально уходит время или другие ресурсы, можно воспользоваться профилировщиком или хорошим журналом. Известный афоризм утверждает, что 90 % времени затрачивается на выполнение 10 % кода. К этому я бы добавил, что производительность серьезно зависит от затрат на выполнение операций ввода-вывода. Зачастую на ввод-вывод в той или иной форме затрачивается большая часть времени. Полезно как раз и начать построение мысленной модели с поиска дорогостоящих операций ввода-вывода и пресловутых 10 % кода. Производительность компьютерной системы зависит от многих факторов и определяется потреблением многих ресурсов. Первое, что нужно измерить – реальное время, то есть общее время, затрачиваемое на вычисления. Внесение в журналы реального времени особенно ценно тем, что может пролить свет на непредвиденное обстоятельство в ситуациях, когда профилирование других типов неприменимо. Однако, при этом не всегда можно увидеть картину в целом. Иногда в конкретной среде, с которой приходится иметь дело, гораздо предпочтительнее оказывается процесс, выполняющийся несколько дольше, но не съедающий так много процессорного времени. Аналогично, гораздо ценнее процессорного времени могут оказаться другие потребляемые ресурсы, такие как память, пропускная способность сети или емкость базы данных. Борьба за право доступа к нескольким синхронизируемым общим ресурсам чревата взаимоблокировкой и информационным голодом. Взаимоблокировка состоит в невозможности продолжения работы в связи с некорректной синхронизацией или завышенными требованиями к ресурсам. Информационный голод не позволяет правильно спланировать работу компонента. Желательно с самого начала реализации проекта сдерживать такого рода соперничество, если оно может возникнуть. Даже если и нет, полезно иметь возможность утверждать это с полной ответственностью. Как исправлять проблемы производительности Большинство программных продуктов могут быть ускорены на порядок-другой с приложением относительно небольших усилий. Под давлением времени и рынка мудро и эффективно выбирать решения, делающие работу быстрее и проще, но менее рационально, чем какое-нибудь другое решение. Тем не менее, производительность является частью юзабилити, и часто должна рассматриваться более внимательно. Ключевым моментом в улучшении производительности очень сложных систем является тщательный их анализ, достаточный для обнаружения "узких мест", или мест, где потребляется большая часть ресурсов. Немного смысла в оптимизации функции, которая занимает лишь 1% от общего времени вычислений. Запомните, что можно смело браться за оптимизацию если она обеспечит всей системе или значительной её части как минимум удвоенную производительность. В остальных случаях необходимо хорошенько подумать о её необходимости. Обычно, способ двухкратного увеличения производительности cуществует. Вообразите себе затраты на тестирование и QA, вызванные вашими частыми изменениями. Каждое изменение влечет "тучу" тестов за собой, поэтому гораздо лучше иметь всего несколько изменений, но значительных. После того, как вы сделали существенное двукратное улучшение, вам нужно хотя бы прикинуть, а возможно, и проанализировать еще раз, где можно обнаружить следующее наиболее дорогое "узкое место" и где можно добиться следующего двукратного ускорения. Зачастую, узкие места в производительности будут похожи на такой способ подсчета коров в стаде, когда считают ноги и делят на четыре вместо того, чтобы считать по головам. Например, у меня были ошибки типа: я не сделал столбец в реляционной базе данных ключевым, а делал поиск по нему очень часто, что, вероятно, ухудшило производительность раз в двадцать. Другие примеры включают: ненужные операции ввода-вывода во вложенных циклах, отладочные операторы в рабочей системе, где они уже не нужны, ненужное выделение памяти и, в особенности, неумелое использование библиотек и других подсистем, которые очень часто плохо документированы в плане производительности. Подобные улучшения иногда называются низко висящие фрукты [low-hanging fruit], что значит получение выгоды с минимумом усилий. Что Вы делаете, когда перестаете доставать до низко висящих фруктов? Ну, вы можете пытаться дотянуться выше или срубить дерево. Вы можете продолжать делать небольшие улучшения, или выполнить серьёзный редизайн системы или подсистемы. (Это прекрасная возможность применить свои способности программиста, не только проектируя "с чистого листа", но также и в убеждении босса, что перепроектировать все является хорошей идеей). Тем не менее, перед тем, как выступать за перепроектирование, Вам следет спросить самого себя, в самом ли деле это сделает систему в пять-десять раз лучше или нет. Как оптимизировать циклы Иногда Вы натыкаетесь на циклы или рекурсивные функции, которые требуют много времени для своего исполнения и являются узкими местами в вашем продукте. Перед тем, как Вы попробуете сделать цикл немного быстрее, сядьте и потратьте несколько минут на размышления, нет ли способа выкинуть такой цикл полностью. Сможет ли это сделать другой алгоритм? Можно ли это сделать заодно с подсчетом чего-нибудь еще? Если Вы не находите обходного пути, можете оптимизировать этот цикл. Это просто - вынесите всё что только возможно за его пределы. В конце концов, это требует не только мастерства и умения, но и понимания удельной стоимости каждого типа операторов и выражений. Вот несколько предположений, от которых стоит отталкиваться: Избавьтесь от операций с плавающей точкой Не выделяйте новую память в хипе без необходимости Держите все константы вместе Используйте буферизацию при операциях ввода/вывода Постарайтесь не использовать деление Старайтесь не выполнять дорогостоящие приведения типов Передвигайте указатель вместо перевычисления индексов Стоимость каждой из этих операций зависит от специфики Вашей системы. На некоторых системах компилятор и "железо" делают эти вещи за Вас. Чистый, эффективный код лучше кода, который требует понимания особенностей отдельно взятой платформы. Как работать с издержками ввода-вывода В большинстве случаев, стоимость процессорного времени низка, по сравнению с затратами на коммуникацию с аппаратным устройством. Стоимость ввода-вывода может складываться из затрат на сетевые коммуникации, дискового ввода/вывода, запросов к базе данных, файлового ввода/вывода и других операций с "железом", более или менее удаленным от процессора. Поэтому при построении "быстрых" систем вопрос оптимизации ввода/вывода стоит более остро, чем оптимизация "трудных" циклов или даже всего алгоритма. Существует два основных подхода к оптимизации ввода-вывода: кэширование и изменение представления. Кэширование заключается в замене операции ввода-вывода (в общем случае, операции получения некоторого произвольного значения) на обращение к локальной копии значения. Ключевым моментом является чёткое понимание того, какие данные оригинальны, а какие – копии. Здесь надо обращать внимание лишь на время жизни. Кэширование опасно тем, что изменения в источнике не сразу попадают в копию. Изменение представления – это подход, позволяющий сделать ввод-вывод более дешевым, применив более эффективное представление данных. Этот подход часто вступает в противоречие с другими требованиями, например, с читабельностью или переносимостью. Изменением представления можно поднять производительность вдвое или втрое, по сравнению с исходной реализацией. Для этого можно, например, использовать двоичное представление вместо текстового (которое может прочитать человек), передавать словарь символов вместе с данными (чтобы не использовать в коде длинные символы) или, в крайнем случае, применять что-то вроде кодов Хаффмена. Третий подход, который иногда применим, заключается в локализации вычислений, то есть, в выполнении вычисления как можно ближе к данным. Например, если вы читаете некоторые данные из базы и проводите с ними некоторые несложные вычисления вроде суммирования, то попробуйте задействовать для этого сервер баз данных. Этот подход очень сильно зависит от типа системы, с которой вы работаете, но вам стоит изучить ее возможности. Как управлять памятью Память является ценным ресурсом, допустить исчерпания которого нельзя. Вы можете не обращать на нее внимания какое-то время, но, в конце концов, вам придется выработать стратегию управления памятью. Пространство (память), которое должно сохраняться между вызовами отдельных подпрограмм, часто называется динамически выделяемой памятью (кучей). Если ничто не ссылается на участок (динамической) памяти, то такой участок становится бесполезным, мусором. В зависимости от используемой вами системы, вам, возможно, понадобится вручную, явным образом, освобождать память, после того как она становится ненужной. Зачастую, у вас есть возможность использовать систему с автоматической сборкой мусора. Сборщик мусора находит и освобождает неиспользуемые участки памяти (мусор) без какого-либо вмешательства со стороны программиста. Сборка мусора -- это замечательно: она уменьшает количество ошибок, сокращает размер кода и делает его более выразительным, не требуя при этом больших затрат. Пользуйтесь этим, если есть такая возможность. Но, даже используя сборку мусора, можно умудриться заполнить всю память мусором. Например, используя хэш-таблицу в качестве кэша, классической ошибкой будет забыть удалить из нее ссылки. Участки памяти, на которые указывают такие неудаленные ссылки, являются бесполезными и, в то же время, неосвобождаемыми. Эта ситуация называется "утечки памяти". Нужно стараться обнаруживать и исправлять утечки памяти как можно раньше. При разработке систем с продолжительным временем работы может получиться так, что, во время тестирования память никогда не исчерпается, а в готовой системе пользователь сможет этого добиться. На всех системах создание объекта является относительно дорогостоящей операцией. В то же время, выделение памяти под локальные переменные непосредственно внутри подпрограммы стоит дешево, так как для ее освобождения не требуется сложных действий. Старайтесь избегать лишних операций создания объектов. Есть один важный случай, который реализуется, если можно ограничить сверху количество объектов, требуемых в одно и то же время. Если все эти объекты используют одинаковое количество памяти, то можно выделить один участок памяти или буфер для размещения всех объектов. Память для объектов может выделяться и освобождаться внутри буфера по мере необходимости по схеме"set rotation", или так называемый кольцевой буфер. Как правило, такой подход получается намного более быстрым, чем обычное динамическое выделение памяти. Иногда требуется освобождать выделенную память для повторного выделения [reallocation] вместо того, чтобы полагаться на сборку мусора. В этом случае, нужно внимательно следить за каждым участком выделенной памяти и разработать способ их освобождения в подходящее время. Для разных типов создаваемых объектов методы освобождения могут отличаться. Каждая операция выделения памяти в обязательном порядке должна сопровождаться соответствующей операцией освобождения. Выполнить это требование достаточно трудно, поэтому программисты часто реализуют простейшие формы сборки мусора, например, подсчет ссылок, для контроля за соответствием операций выделения-освобождения. Как бороться с нерегулярными ошибками Трудноуловимые ошибки похожи на появления призраков. Этот кошмар случается, с одной стороны, достаточно редко, чтобы его можно было рассмотреть, а с другой стороны, достаточно часто, чтобы невозможно было его игнорировать. Вы не можете отладить эту ошибку просто потому, что не можете найти ее. Нерегулярные (трудноуловимые) ошибки подчиняются тем же законам, что и обычные, хотя, проведя 8 часов в поиске, можно в этом усомниться. Вся трудность заключается в том, что условия проявления ошибки неизвестны. Попробуйте зафиксировать все обстоятельства, при которых происходит ошибка. Это поможет догадаться, в чем именно заключается нестабильность. Появление ошибки может зависеть от значений данных, например: "это происходит только тогда, когда мы вводим Вайоминг". Если же источником нестабильности не являются данные, то следующим подозреваемым следует считать неправильную синхронизацию доступа [к разделяемым ресурсам]. Изо всех сил постарайтесь управляемо воспроизвести ошибку. Если не получается воспроизвести, отловите её с помощью системы журналирования, может быть даже специально для этого написанной, которая позволит записать все, что вам нужно при появлении ошибки. Будьте готовы к тому, что процесс может затянуться, если ошибка появляется только на рабочей системе, а не когда вы хотите. Информации, которую можно выудить из журнала, может оказаться недостаточно для исправления ошибки, зато, используя ее, можно будет уточнить, что выводить в следующий раз. Может потребоваться какое-то время, чтобы внедрить новую версию системы журналирования в работающий продукт. Затем нужно будет подождать повторного появления ошибки, чтобы собрать дополнительную информацию. Этот цикл может продолжаться некоторое время. Самая глупая из трудноуловимых ошибок, которые я когда-либо совершил, была в многопоточной реализации функционального языка программирования для учебного проекта. Я весьма тщательно обеспечил правильное распараллеливание выполнения функциональной программы, добившись хорошей загрузки всех доступных процессоров (восьми, в том случае). Единственное, что я забыл, -- это синхронизировать сборщик мусора. Система могла проработать достаточно долго, обычно выполнив любую из заданных мною задач прежде, чем можно было заметить, что что-то пошло не так. Мне стыдно в этом признаваться, но я сначала начал обвинять во всем оборудование прежде, чем мне стала ясна моя ошибка. Недавно на работе мы столкнулись с одной трудноуловимой ошибкой, поиск которой занял у нас несколько недель. Мы занимаемся многопоточными серверами приложений на Java, запускаемыми через веб-сервера Apache. Чтобы добиться быстрого отображения страниц, весь ввод-вывод осуществляется не в тех потоках, которые отвечают за генерирование страниц, а в четырех отдельных потоках. Каждый из этих четырех потоков иногда подвисал и переставал делать что-либо полезное, причем, судя по логам, это могло продолжаться несколько часов. Это само по себе не было такой уж большой проблемой -- у нас было четыре потока, но только до тех пор, пока не зависали все четыре одновременно. После этого, поскольку потоки переставали забирать данные из очередей, последние очень быстро заполняли всю доступную память и роняли сервер. Потратив примерно неделю на поиск возможной причины, мы так и не смогли разобраться, из-за чего это происходило, когда, и чем собственно потоки занимались в подвисшем состоянии. Это является примером риска, связанного с ПО сторонних производителей. Мы использовали фрагмент [licensed] кода, который убирал HTML теги из текста. Между собой мы его ласково называли "the French stripper" [стрипризерша?], намекая на страну, где его написали. Несмотря на то, что у нас был исходный код (слава богу!), мы внимательно его не разбирали до тех пор, пока не включили журналирование на наших серверах и не обнаружили, что [email] потоки [а были вроде как ввода-вывода] зависали как раз на стриптизерше. Стриптизерша работала нормально, кроме некоторых длинных и редких типов текста. На них код становился квадратичным или даже хуже. Это значит, что время обработки было пропорционально квадрату длины текста. Если бы подобные тексты встречались постоянно, мы бы сразу же обнаружили ошибку. Если бы таки тексты не попадались никогда, проблемы бы вообще не было. А в нашем случае, пришлось потратить несколько недель, чтобы наконец-то понять, в чем проблема, и исправить ее. Как научиться проектировать Чтобы научиться проектировать ПО, нужно наблюдать за проектирующим наставником. Затем, изучить хорошо написанные программы. После этого, можно прочитать книги о новых методах проектирования. Затем придется учиться самостоятельно. Начните с небольшого проекта. Когда вы его закончите, оцените насколько было удачно или неудачно выполнено проектирование [дизайн] и насколько пришлось отклониться от первоначального замысла. Потом займитесь проектами покрупнее, лучше всего объединившись с другими людьми. Проектирование -- это такая вещь, на достижение высот в которой могут потребоваться годы. Толковый программист может изучить основы в достаточной мере за пару месяцев, а затем совершенствоваться дальше. Естественно и полезно разработать свой собственный стиль, но помните, что проектирование -- это искусство, а не наука. Люди, которые пишут книги на эту тему, имеют определенную заинтересованность в том, чтобы проектирование казалось научным. Не становитесь категоричными по отношению к отдельным стилям проектирования. Как проводить эксперименты Великий Эдгар Дейкстра, ныне покойный, красноречиво доказывал, что информатика не является экспериментальной наукой [ExpCS] и не привязана к электронным вычислительным машинам. Говоря о 60-х годах, он пишет [Knife]: ...зло было уже содеяно: информатику стали называть «наукой о компьютерах» – а ведь это все равно, что хирургию назвать «наукой о скальпелях» – и в мозгу у людей прочно укоренилось представление об информатике как о чем-то относящемся к машинам и их периферийному оборудованию. Программирование не должно быть экспериментальной наукой, но большинство работающих программистов не имеют такой роскоши заниматься тем, что Дейкстра в действительности понимал под информатикой. Нам приходится работать в мире экспериментов, как некоторым (но не всем) физикам. Если, вдруг, через тридцать лет, можно будет программировать без экспериментирования, то это будет огромным достижением. Вам придется проводить следующие типы экспериментов: тестировать системы на небольших примерах, чтобы проверить их соответствие документации или разобраться, как они себя ведут, если документация отсутствует; тестировать небольшие изменения в коде, чтобы убедиться, что они действительно исправляют ошибку; измерять производительность системы в разных условиях, потому что недостаточно информации о производительности; проверять целостность данных; собирать статистику, которая может помочь найти решение для трудных или трудновоспроизводимых ошибок. Я не думаю, что смогу объяснить в этой статье, как нужно строить (планировать) эксперименты. Вам придется учить и упражняться в этом самостоятельно. Тем не менее, я могу дать пару советов. Во-первых, постарайтесь четко формулировать гипотезу или утверждение, которые нужно проверить. Также полезно записать гипотезу, особенно, если вы чувствуете, что запутались, или работаете с кем-нибудь еще. Часто оказывается, что нужно спланировать последовательность экспериментов, каждый следующий из которых требует знаний, полученных из предыдущего. Следовательно, вы должны разрабатывать эксперименты так, чтобы получить из них как можно больше информации. К сожалению, это противоречит тому, что каждый эксперимент должен быть простым. Вам придется научиться определять баланс между полнотой и простотой опытным путем. Командные навыки Почему важна оценка Для того, чтобы как можно быстрее запустить программную систему в активное использование, требуется не только планирование разработки, но еще и планирование документирования, внедрения, маркетинга. Для коммерческих проектов дополнительно нужен учет продаж и финансов. Не имея возможности спрогнозировать время разработки, невозможно эффективно спланировать и все остальное. Хорошие оценки обеспечивают предсказуемость. Менеджеры любят предсказуемость, да и профессия их к этому обязывает. Однако, тот факт, что невозможно, ни теоретически, ни практически, точно предсказать сколько времени нужно потратить на разработку ПО, они часто забывают. Нас постоянно просят выполнить это невозможное требование, и мы должны быть искренне готовы к этому. Тем не менее, было бы нечестно не признавать невозможность этой задачи, и, если это необходимо, доходчиво объяснить это. Часто случаются разночтения в разговорах об оценке сроков разработки из-за ужасающей человеческой склонности во что бы то ни стало угодить заказчику. Например, эту фразу: Я рассчитываю, что если я действительно понял, в чем проблема, то с вероятностью 50% мы решим ее в течение пяти недель (если нас не будут отвлекать). заказчик поймет как: Я обещаю, что все будет готово через пять недель. Такая часто встречающаяся ошибка интерпретации оценки требует, чтобы вы явным образом и простым языком разъяснили начальнику или клиенту, что именно значит эта оценка. Переформулируйте свои предположения, независимо от того, насколько они вам кажутся очевидными. Как оценить время на реализацию Оценки требуют практики. Ещё они требуют усилий. Усилий настолько значительных, что, может быть, будет лучше сначала оценить, сколько потребуется времени на проведение оценки, особенно если требуется оценить что-нибудь объемное. Если вас попросили оценить что-нибудь большое, самым правильным будет увильнуть. Большинство разработчиков полны энтузиазма и рады угодить, а приостановка не понравится заказчикам. Но оценка, сделанная на ходу, вероятно, не будет точной и честной. Увильнув и выиграв таким образом для себя какое-то время, можно обдумать решение задачи или даже набросать прототип будущей системы. Если позволяет обстановка, это наиболее точный метод получения оценки, и он позволяет реально продвинуться вперёд. Если невозможно выделить время на исследование, то, первым делом, нужно очень четко установить значение оценки. Оформляя свою оценку в письменном виде, представьте это значение как самую важную часть документа. Подготавливая его, разбейте задачу на меньшие задачи, те, в свою очередь, на еще более мелкие, до тех пор, пока каждая из мелких задач займет не больше одного дня; в идеале — максимум день. Самое главное — ничего не забыть. Например, документирование, тестирование, время на планирование, время на обсуждения с другими группами, время на отпуска — все это очень важно. Если каждый день вам приходится какое-то время взаимодействовать с дятлами, добавьте это время в оценку. Это позволит вашему начальнику увидеть, как минимум, на что тратится ваше время, и, возможно, выделить больше времени. Я знаю хороших разработчиков, которые неявно завышают оценку, но я не рекомендую так делать. Постоянно завышая оценку, вы можете потерять доверие к себе. Например, разработчица может оценить задачу на три дня, на самом деле, думая, что справится за один. Может быть, она планирует документировать эту задачу два дня, а, может быть, хочет поработать эти два дня над другим нужным проектом. Но будет видно, что задача была сделана за один день, и вот, пожалуйста, готовы оценки «с недолётом» или «перелётом». Будет гораздо лучше, дать возможность получше взглянуть на то, чем вы действительно занимаетесь. Если документирование требует вдвое больше времени, чем кодирование, и это отражено в оценке, то будет огромным преимуществом предоставить эту информацию менеджеру. Вместо этого явно добавляйте. Например задача, по-видимому, займёт один день, но она может занять и десять дней, если ваш подход не сработает, учитывайте это так или иначе в своей оценке, если это возможно, если же нет, то используйте среднее взвешенное своих оценок вероятностей. Любой фактор риска, который вы в состоянии определить и использовать в своей оценке, должен быть в плане. Кто-то может оказаться больным в любую из недель. Но в большом проекте с большим количеством участников будет иметь место затрата некоторого времени на болезни, равно как и на отпуск. А как насчет вероятности принудительного корпоративного семинара-тренинга? Если это можно оценить, воткните и это. Конечно же, есть и так называемые неизвестные неопределённости. Они по определению не могут быть оценены индивидуально. Вы можете попытаться создать глобальный линейный элемент для них, или справиться с ними другим способом, который вы сообщите своему боссу. Однако вы не вправе позволить боссу забыть, что неизвестные неопределённости имеют место, и планирование без их учета будет опрометчиво с точки зрения оценки времени. В групповом окружении вы можете попытаться заставить выполнить оценку людей, которые будут делать работу, или же вы можете попытаться отыскать общий для всех консенсус по поводу оценки. Люди сильно разнятся в своих навыках, опыте, подготовке и уверенности. Проблемы возникают в том случае, когда сильный программист делает оценку исходя из своего уровня, а более слабые программисты вынуждены придерживаться этой оценки. Наличие взаимного согласия всей команды по поводу последовательной пошаговой оценки обуславливает взаимопонимание в команде равно как и открытие возможности для тактического перераспределения ресурсов (например, смещение нагрузки от более слабых членов команды к более сильным). Если существуют большие риски, которые нельзя оценить, то это ваша обязанность настоять на том, чтобы ваш менеджер отнесся к ним серьезно [вроде так] и не растерялся, если вдруг этот риск реализуется. Надо надеяться, что все необходимые меры будут приняты, чтобы уменьшить этот риск. Если вы убедите вашу компанию использовать экстремальное программирование, то вам нужно будет оценивать относительно небольшие задачи. Это намного более продуктивно и весело одновременно. Как находить информацию Как искать, зависит от того, что ищешь. Если вам нужна информация о чем-то объективном, что можно легко проверить, например о последнем патче программного продукта, можно порасспрашивать людей в Интернет или на каких-нибудь форумах. Не ищите в Интернет то, что является мнением или субъективной интерпретацией: отношение бреда к истине может быть слишком высоким. Если вам нужны общие знания о чем-то субъективном, истории или что люди думают об этом, сходите в библиотеку (это такое здание, где хранятся книги). Например, чтобы узнать о математике, или о грибах, или о мистике, идите в библиотеку. Если вам нужно узнать нечто нетривиальное, прочитайте пару книг на эту тему. Простые вещи, например, как установить ПО, можно узнать в Интернет. Можно изучить многие важные вещи, например, хорошие приемы программирования, но при этом можно легко потратить больше времени на поиск, сбор результатов поиска и на попытки определить актуальность этих результатов, чем на чтение соответствующей части увесистой книги. Если вам нужна информация, которой никто не обладает, например, "работает ли этот новый софт с огромными массивами данных?", то вам, по-прежнему, нужно сначала поискать в Интернет или в библиотеке. Лишь после того, как эти возможности полностью исчерпаны, вам нужно поставить эксперимент, который это определит. Если вам нужно мнение или оценка, которые учитывают некоторые особые обстоятельства, поговорите с экспертом. Например, если вы хотите знать, стоит ли делать современную СУБД на Лиспе, вам нужно поговорить с экспертом по Лиспу и с экспертом по базам данных. Если вы хотите знать, насколько вероятно, что для некоторого приложения существует более быстрый алгоритм, и он еще не опубликован, поговорите с кем-нибудь, кто работает в этой области. Если вы хотите принять решение, которое касается вас лично, например, стоит ли начинать собственный бизнес или нет, попробуйте составить список аргументов «за» и «против». Если не получается, попробуйте угадать. Предположим, вы уже рассмотрели вопрос со всех сторон, сделали всё что могли, проработали все выводы, все «за» и »против», но все еще колеблетесь. Теперь вам нужно послушаться своего сердца и попросить свои мозги заткнуться. Многие доступные методы предсказывания очень полезны для определения ваших собственных подсознательных желаний, так каждое из них представляется полным неясных и случайных образов, так что ваше подсознание будет нацелено на присваивание им значения. Как использовать людей в качестве источника информации Цените время других людей и сопоставляйте его со своим. Задавая кому-нибудь вопрос, вы получаете, на самом деле, намного больше, чем просто ответ. Человек узнает о вас нечто новое, просто наслаждаясь вашим обществом и выслушивая конкретный вопрос. А вы, таким образом, узнаете что-то новое о вашем собеседнике, а также можете получить нужный вам ответ . Обычно это намного более существенно, чем ваш изначальный вопрос. Однако, чем дальше, тем меньше вы получаете с каждым разом. В конце концов, вы потребляете самый ценный ресурс других людей — их время. Преимущества общения должны быть уравновешены затратами. К тому же, затраты и выгода у разных людей отличаются. Я серьезно считаю, что директор, у которого в подчинении 100 человек, должен поговорить с каждым по пять минут в месяц, это займет примерно 5% его [а тут почему-то "их"] времени. Но десять минут — это перебор. Даже пять минут будет много, если в организации работает тысяча человек. Количество времени, которое вы тратите на общение, зависит от роли (в большей степени, чем от должности), которую занимает человек в организации. Разговаривать с вашим непосредственным начальником вы можете чаще, чем с начальником вашего начальника. Но вы должны поговорить немного и с начальником начальника. Это может показаться неудобным, но я думаю, что вы обязаны немного поговорить со всем вашим начальством, каждый месяц, неважно о чем. Основное правило здесь: все получают выгоду от общения с вами, и чем больше вы общаетесь, тем меньше выгода. Это ваша обязанность предоставить им выгоду и, заодно, получить выгоду от общения с ними, сопоставляя ее с затраченным временем. Важно ценить свое собственное время. Если, поговорив с кем-нибудь, вы сэкономите себе массу времени, то это стоит сделать, если только вы не считаете, что время этого человека намного важнее вашего для команды. Удивительный пример тому – практиканты. От практикантов на технической должности не ждут выдающихся результатов. Ожидается, что они будут всех чертовски доставать. Как можно терпеть подобное? Потому что, те, кого достают, получают нечто важное от практикантов. У них появляется возможность чуток похвастаться. Может быть, услышать новые мысли, увидеть вещи с другой стороны. Они также могут попробовать нанять практиканта, но, даже если это не так, все равно можно из всего этого много извлечь. Если вы искренне верите, что людям есть, что вам сказать, вам стоит попросить их поделиться своей мудростью и рассудительностью. Это льстит им, а вы научитесь чему-нибудь и научите их. Хорошему программисту не часто нужен совет от замначальника отдела продаж, но если вдруг понадобится, обязательно спросите. Однажды я попросил прослушать несколько звонков отдела продаж, чтобы лучше понять, чем же они занимаются. Это заняло не более 30 минут, но я думаю, что то небольшое усилие произвело впечатление на сотрудников отдела. Как разумно вести документацию Жизнь слишком коротка, чтобы писать чушь, которую никто не будет читать; если вы пишете чушь, никто ее читать не станет. В связи с чем небольшое количество качественной документации является лучшим вариантом. Менеджеры частенько этого не понимают, так как даже некачественная документация даёт им ложное чувство безопасности в плане их независимости от программистов. Если кто-то твердо настаивает на том, чтобы вы писали в действительности бесполезную документацию, скажите «да» и спокойно начинайте искать более хорошую работу. Нет ничего эффективнее, чем использование аккуратной оценки времени, необходимого для написания хорошей документации, для оценки уменьшения необходимости документирования. Это горькая и грубая истина: документирование, как тестирование, занимает гораздо больше времени, чем разработка самого кода. Сочинять хорошую документацию — это прежде всего хорошо писать. Я надеюсь вы найдете книги о писательском деле, изучите их и примените на практике. Даже если вы слабый писатель, или ничего не знаете о языке документирования, всё, что вам нужно, это золотое правило: «Делайте другим так, как если бы хотели, чтобы другие делали по отношению к вам». Потратьте время на размышления о тех, кто действительно будет читать вашу документацию, что они должны будут увидеть в ней, и как вы можете помочь им понять код. Если вы сделаете это, вы будете техническим писателем «выше среднего», и хорошим программистом. В отличие от написания документов, которые, возможно, будут читать непрограммисты, когда дело доходит до документации самого кода, лучшие программисты, которых я когда-либо знал, сходятся в общем мнении: пишите говорящий за себя код и документируйте лишь те места, которые не смогли сделать достаточно ясными. На это есть две причины. Первая: любой, кому потребуется читать документацию в коде, в большинстве случаев сможет и предпочтёт читать сам код. Следует признать, что это больше относится к опытному программисту, чем новичку. Более важным является тот факт, что код и документация не будут расходиться, если документации просто не существует. В худшем случае исходный код может быть некорректным и путанным. Неидеально написанная документация может врать, а это в тысячу раз хуже. Это не облечает участь ответственных программистов. Как же написать говорящий за себя код? Что бы вообще это могло значить? Это значит: Пишите код, думая о том, что кто-то будет его читать потом; Применяйте золотое правило; Выбирайте наиболее простое решение, даже если оно уступает другим решениям в скорости; Избегайте мелких оптимизаций, которые будут запутывать код; Подумайте о читателе и потратьте немного вашего драгоценного времени, заботясь о нем; Никогда не используте “foo”, “bar” или “doIt” в именах функций! Как работать с плохим кодом Очень часто приходится работать с кодом низкого качества, написанным другими людьми. Однако, не думайте о них плохо, пока вы не побывали на их месте. Возможно, их специально попросили быстро что-нибудь сделать, чтобы уложиться в график. Несмотря на это, чтобы работать с неясным кодом, нужно сначала его понять. А на то, чтобы разобраться, нужно время. И это время нужно будет выкроить из графика, причем вы должны будете настоять на этом. Для того, чтобы понять код, вам придется его прочитать. Может быть, нужно будет поэкспериментировать с ним. Это подходящее время, чтобы задокументировать код, даже если вы сделаете это для себя. Попытка задокументировать код заставит вас рассмотреть его с разных сторон, с которых вы, возможно, еще его не рассматривали, поэтому итоговая документация может оказаться полезной. Во время документирования [или понимания] подумайте, сколько времени понадобится, чтобы переписать код полностью или частично. Можно ли сэкономить время, переписав какие-то куски кода? Будете ли вы больше доверять коду, если вы его перепишете? Не будьте самонадеянными. Если вы перепишете код, вам будет легче в дальнейшем с ним работать, но будет ли легче следующему человеку, которому придется читать его? Не перевесит ли необходимость заново протестировать код возможные преимущества? Для каждой оценки, которую вы сделаете относительно работы над написанным не вами кодом, качество этого кода должно повлиять на ваше восприятие возможных проблем и [неопределенностей]. Важно помнить, что абстракция (абстрагирование) и инкапсуляция — одни из лучших инструментов программиста — применимы к быдлокоду. Может быть, у вас не будет возможности переделать большой кусок кода, но, добавив определенное количество [уровень] абстракции, можно получить кое-какие выгоды от хорошего дизайна без необходимости окунаться в полный беспорядок. В частности, можно попробовать отгородить друг от друга особенно плохие части таким образом, что их можно будет независимо переделать (перепроектировать). Как использовать системы контроля версий Системы управления исходным кодом позволяют эффективно работать над проектами. Они весьма полезны для одиночек и незаменимы для команд. Они отслеживают все изменения в различных версиях, чтобы не потерять ни кусочка кода и иметь возможность определить назначение каждого изменения. Временный или отладочный код также может быть доверен системе управления исходным кодом, потому что измененный вами код будет храниться отдельно от официальной ветки кода, который доступен остальным членами команды или может быть выпущен в релиз. Я опоздал, чтобы оценить преимущества систем контроля версий, но сейчас я бы не прожил без них даже в личных (индивидуальных) проектах. В общем, они необходимы для команды, работающей над одним и тем же кодом. Кроме того, у них есть еще одно большое преимущество: они заставляют думать о коде как о живом развивающимся организме. Поскольку каждое изменение помечается как новая ревизия (версия) с новым именем или номером, можно начать воспринимать софт как последовательность постоянных улучшений. Думаю, что это особенно полезно для новичков. Система управления исходным кодом позволяет в любой момент времени поддерживать код в актуальном состоянии [в смысле содержать все изменения, за исключением, может быть последних нескольких дней]. Если для кодирования требуется больше нескольких дней, то код сохраняется в системе, но таким способом, что он является неактивным, его нельзя вызвать, он не создает проблем для других программистов. Большой ошибкой будет сохранение ошибочного кода, который задержит коллег. Это обычно запрещено. Как использовать юнит-тесты Модульное тестирование, то есть тестирование отдельных фрагментов программной функциональности силами создавшей ее команды - это часть процесса кодирования, а не какой-то отдельный процесс. Часть процесса разработки кода состоит в разработке способа его тестирования. Вы должны написать план тестирования, даже если он состоит из одного предложения. Иногда тестирование будет простым: "Кнопка выглядит хорошо?" Иногда оно может быть сложным: "Точно ли алгоритм поиска совпадений вернул верные совпадения?" Используйте проверку утверждений и тест-драйверы везде, где только можно. Это не только поможет найти ошибки на ранней стадии, но и окажется очень полезным впоследствии, устраняя возможность появления таинственных проблем. Разработчики в стиле «экстремального программирования» много пишут про эффективное модульное тестирование. Все, что я могу сделать — порекомендовать почитать их статьи. Отдыхайте, если зашли в тупик Если зашли в тупик — сделайте перерыв. Я в этом случае, иногда, медитирую в течение 15 минут. После того, как я возвращаюсь к решению задачи, она волшебным образом распутывается сама. Ночной сон действует аналогично, но в большем масштабе. Также может помочь временное переключение на какую-нибудь другую деятельность. Как понять, что пора домой Программирование -- это не только деятельность, но еще и культура. К сожалению, это не та культура, которая ценит здоровье, в том числе и душевное. По культурным и историческим причинам (например, необходимости работать по ночам на ненагруженных компьютерах), из-за жестких требований по срокам выпуска ПО и нехватки программистов, последние обычно перерабатывают. Я не думаю, что можно верить всем байкам, но считаю, что 60 часов в неделю — это обычная ситуация, а 50 — это почти что минимум. В смысле, работают чаще всего намного больше, чем нужно. Это серьезная проблема для хорошего программиста, который несет ответственность не только за себя, но и за членов своей команды. Вам нужно определять, когда пора идти домой, и иногда советовать сделать это другим людям. Для решения этой задачи нет четких правил, как нет четких правил по воспитанию детей, по одной и той же причине — все люди разные. Для меня больше 60 часов в неделю — это подвиг, который я могу совершить только на короткое время (около одной недели), но иногда приходится. Я не знаю, будет ли честным ожидать от человека работать 60 часов в неделю. Я даже не уверен насчет 40. Зато, я точно знаю, что глупо много работать и при этом получать незначительные результаты в эти дополнительные часы. Лично для меня, это значит больше чем 60 часов в неделю. Я считаю, что программист должен упражняться в благородстве и взваливать на себя тяжелую ношу. Тем не менее, это не значит, что программист должен быть лопухом. Печально то, что программистов часто просят побыть лопухами, чтобы пустить пыль в глаза кому-нибудь, например, по просьбе менеджера, который старается впечатлить директора. Программисты часто поддаются этому, потому что они стремятся угодить и расстраиваются, отказывая. Есть четыре способа противостоять этому: Как можно больше общаться с сотрудниками компании, чтобы никто не смог ввести в заблуждение руководство о том, что же происходит на самом деле. Научиться делать оценки, планировать прозрачно и с запасом, чтобы все видели, что нужно сделать по плану и в какой стадии он находится. Научиться говорить «нет», если нужно, причем, не только за себя, но и за весь отдел (команду). В крайнем случае, уволиться. Большинство программистов являются хорошими программистами, а хорошие программисты хотят [стараются] сделать все [и побольше]. Чтобы добиться этого, они должны эффективно управлять своим временем. Существует определенная психическая инерция, связанная с вниканием и глубоким погружением в задачу. Многие программисты обнаруживают, что они лучше всего работают в течение длительных непрерывных интервалов времени, которые позволяют сосредоточиться и сконцентрироваться. Однако, людям нужно спать и заниматься другими делами. Каждый человек должен найти баланс между своим рабочим ритмом и личной жизнью. Каждый программист должен [сделать все возможное], чтобы раздобыть продуктивное время, например, планируя определенные дни, во время которых участвовать только в самых важных совещаниях. Поскольку у меня есть дети, я стараюсь проводить вечера с ними, иногда. Наилучший ритм для меня — это проработать очень длинный день, переночевать на работе или недалеко от офиса (мне очень далеко добираться от дома до работы), а на следующий день уйти домой пораньше, чтобы провести время с детьми до того, как они лягут спать. Мне это не очень удобно, но это наилучший компромисс, которого мне удалось достигнуть. Идите домой, если вы заболели, чтобы не распространять заразу. Вам лучше пойти домой, если вас одолевают мысли о самоубийстве. Также поступайте, если появилось устойчивое желание убить другого человека. Если кто-нибудь из окружающих демонстрирует признаки серьезного нервного срыва или расстройства на грани легкой депрессии, лучше отправить этого человека домой. Если вы чувствуете соблазн быть небрежным или приврать, что вам несвойственно, потому что вы устали, лучше сделать перерыв. Не употребляйте кокаин или амфетамины, чтобы побороть усталость. Не злоупотребляйте кофеином. Как взаимодействать с непростыми людьми Вам, возможно, придётся иметь дело с трудными людьми. Возможно, вы сам трудный человек. Если вы относитесь к людям, которые много конфликтуют с коллегами и властями, то, лелея получаемую посредством этого независимость, вам всё же следует поработать над своими навыками межличностных отношений, не жертвуя, однако, своим рассудком или принципами. Это может быть очень неприятно для некоторых, неискушённых в подобного рода вещах, программистов, чей жизненый опыт выработал шаблоны поведения неприменимые на рабочем месте. Конфликтные люди привыкли к спорам, и склонны к компромиссам менее остальных. Уважайте их в достаточной мере, в большей, чем вам хочется, но не так сильно, как они того желают. Программисты должны работать вместе как одна команда. Когда возникают разногласия, они должны быть как-то решены и не могут откладываться на долго. Конфликтные люди часто чрезвычайно умны и у них есть что сказать. Это крайне необходимо, чтобы вы слушали и понимали их без предвзятости к личности. Недостаточное понимание друг друга часто является причиной разногласий, но иногда это может быть устранено при большом терпении. Старайтесь поддерживать отношения спокойными и искренними и не поддавайтесь искушению на больший конфликт, чем предложен. После разумного срока обдумывания, принимайте решение. Не применяйте грубую силу, чтобы сделать то, с чем вы не согласны. Если вы лидер, поступайте так, как по вашему мнению будет лучше. Не принимайте решения на основе личных причин и будьте готовы объяснить основания своего решения. Если вы в одной команде с конфликтным человеком, не допускайте, чтобы решение лидера имело какие-либо личные последствия. Если оно не совпадает с вашим, выполняйте его искренне. Конфликтные люди вносят изменения и улучшения. Я видел это собственными глазами, но это очень редко. Впрочем, каждый имеет временные взлеты и падения. Одна из наиболее сложных задач состоит в том, чтобы каждый программист, а особенно руководство держали конфликтного человека заинтересованным. Они более склонны к уклонению от работы и пассивному сопротивлению, чем остальные. 3. Опытный Содержание Личные навыки Как не потерять мотивацию Как быть всесторонне надежным? Как находить компромисс между временем и памятью Как проводить стресс тесты Как сохранить баланс между краткостью и абстрактностью Как научиться новым навыкам? Учитесь печати Как проводить интеграционное тестирование? Языки описания данных Сложные инструменты Как анализировать данные Коммандные навыки Как управлять временем разработки Как управлять рисками, связанными с программным обеспечением третьих лиц Как взаимодействовать с консультантами Как сообщить достаточное количество информации Как честно не соглашаться и не пострадать от этого Оценка Как балансировать между качеством и временем разработки Как управлять зависимостями программы Как определить, что программа еще не готова Как выбрать между покупкой или разработкой Как расти дальше Как оценивать соискателей Как узнать, когда применять модные компьютерные знания Как разговаривать с не-инженерами Личные навыки Как не потерять мотивацию Замечательно и удивительно, что программисты сильно мотивированы желанием создавать прекрасные, полезные и изящные продукты. Это желание не уникально для программистов и не всеобще, но оно настолько сильное и широко распространенное среди программистов, что отличает их от других. Это имеет важные практические выводы. Если программистов попросить сделать что-нибудь, что не будет красивым, полезным или стильным, их моральных дух упадет ниже плинтуса. Можно хорошо зарабатывать, занимаясь уродливыми, тупыми и скучными вещами. Однако, в конце концов, только интересная работа принесет компании гораздо больше прибыли. Очевидно, существуют целые отрасли, организованные вокруг мотивационных методов (техник), некоторые из которых применяются здесь. Я могу назвать следующие присущие программированию вещи: Используйте наилучший язык для работы. Ищите возможность применить новые методы, языки и технологии. Старайтесь в каждом проекте научиться чему-нибудь или научить кого-нибудь, пусть даже немного. Наконец, если возможно, измеряйте результат вашей работы в чем-то, что мотивирует лично вас. Например, подсчет количества исправленных ошибок совсем не мотивирует меня, потому что это количество не зависит от количества еще неисправленных. К тому же, оно слабо влияет на пользу, приносимую мной клиентам моей компании. И наоборот, меня мотивирует сопоставление каждой исправленной ошибки с довольным клиентом. Как быть всесторонне надежным? Чтобы вам доверяли, вы должны заслуживать доверия. Вы также должны быть видимым. Если вас знать никто не знает, никто не будет доверять вам. С теми, кто рядом с вами, например, с членами команды (отдела), проблем быть не должно. Вы зарабатываете доверие, будучи отзывчивым по отношению к коллегам вне вашей команды или отдела. Время от времени кто-то будет злоупотреблять этим доверием и просить о неразумных одолжениях. Не нужно этого бояться, просто объясните, чем вам придется пожертвовать, чтобы выполнить просьбу. Не притворяйтесь, что вы что-то знаете, если это не так. С людьми, которые не являются членами команды, вам, возможно, надо четко различать «не знаю, потому что не вник в суть» и «вообще не понимаю (ниасилил).» Как находить компромисс между временем и памятью Вы можете быть хорошим программистом, не обучаясь в колледже, но вы не будете хорошим [программистом] без знания основ теории сложности вычислений. Вам не нужно знать, что такое «О большое», однако, лично я считаю, что вы должны понимать разницу между «константным временем», «n log n» и «n в квадрате». Возможно, вы интуитивно понимаете, как найти компромисс между временем (выполнения) и (используемой) памятью и без этого знания, но это лишает вас твердого фундамента для общения с вашими коллегами. При разработке или разборе алгоритма, время его выполнения иногда является функцией от размера входных данных. Если это так, мы можем сказать, что время выполнения алгоритма в худшем/среднем/лучшем случае равно «n log n», если оно пропорционально размеру (n), умноженному на логарифм от размера (входных данных). Эти же обозначения [и рассуждения] можно применить и к количеству памяти, занимаемому структурами данных [данными]. На мой взгляд, теория сложности вычислений так же красива и глубока, как и физика — и, двигаясь неспеша, она далеко пойдет. Время (процессорные такты) и пространство (память) взаимозаменяемы. Проектирование это компромис, и это хороший пример. Этот процесс не всегда методичен. В общем случае, можно сэкономить память упаковав данные более плотно за счет дополнительного времени, требуемого на их декодирование (распаковку). Можно сэкономить время с помощью кэширования, то есть, затрачивая дополнительное место на локальную копию данных и за счет дополнительных усилий на поддержание целостности кэша. Иногда можно сэкономить время за счет размещения дополнительной информации в структуре данных. Обычно, это требует немного места, но может усложнить алгоритм. Меняя (улучшая) баланс времени и памяти, часто можно заметным образом изменить одно или другое. Однако, прежде чем вы займетесь этим, вы должны спросить себя, является ли то, что вы улучшаете, тем, что действительно требует улучшения. Интересно [продолжать] работать над алгоритмом, но это не должно скрыть от вас неопровержимый факт, что усовершенствование чего-либо, что не является проблемой, не приведет к каким-либо заметным преимуществам, а только принесет дополнительные расходы [на тестирование]. В современных компьютерах память выглядит дешевой, потому что, в отличие от процессорного времени, невозможно отследить ее использование, пока не будет слишком поздно, причем сбой будет фатальным. Есть и другие скрытые затраты, связанные с использованием памяти, например, [ваше влияние на другие программы, выполняющиеся одновременно с вашими], и время ее на выделение и освобождение. Принимайте это во внимание прежде, чем вы потратите место (память) для того, чтобы получить прирост в скорости. Как проверить отказоустойчивость? Проверка отказоустойчивости забавна. Сперва кажется что цель проверки отказоустойчивости — выяснить, что система работает под нагрузкой. В действительности,— и это общеизвестно — система может работать под нагрузкой, но начинает сбоить, когда нагрузка предельно высока. Я называю это — «удариться о стену» или «врезаться». Возможны исключения, но это почти всегда стена. Цель теста на отказоустойчивость — вычислить, где находится стена, а затем понять, как отодвинуть стену как можно дальше. План такой проверки должен быть разработан в начале проекта, поскольку это часто помогает понять точнее, что ожидается. Две секунды для запроса веб-страницы, это ужасный провал или оглушительный успех? Достаточно ли этого пятистам параллельных пользователей? Это конечно зависит от многих факторов, но проектировщик должен ответить себе на эти вопросы когда разрабатывает систему которая отвечает на запросы. Тест на отказоустойчивость должен быть смоделирован максимально приближенным к реальности, чтобы быть полезным. В действительности, невозможно изобразить пятьсот ошибающихся и непредсказуемых людей, легко, одновременно пользующихся системой, но можно по меньшей мере создать пятьсот виртуальных пользователей и попробовать смоделировать часть того, что они могли бы сделать. Во время проверки отказоустойчивости, стоит начать с лёгкой нагрузки и нагружать систему до некоего предела, такого как входная скорость или размер вводимых данных, прежде чем упрётесь в стену. Если стена не позволяет вам достичь необходимого результата, определите слабое звено (обычно это является главным). Может ли это быть память, процессор, система ввода-вывода, пропускная способность сети или соединение? Затем решите, как вы можете отодвинуть стену. Заметьте, что «отодвигание стены», то есть увеличение максимальной нагрузки, которую в состоянии обрабатывать система, может не помочь или может снизить производительность ненагруженной системы. Обычно, производительность под нагрузкой важнее производительности без нагрузки. Вы, возможно, должны получить визуализацию различных замеров, чтобы построить интеллектуальную модель. Одна методика недостаточна. Например, ведение журнала событий часто даёт представление о затраченном времени между двумя событиями в системе, но без тщательной доработки не даёт представления об использовании памяти или даже о размере массива данных. Так же, в современной системе, несколько компьютеров и различных приложений могут быть объединены. Особенно, когда вы упёрлись в стену (например, производительность нелинейна размеру ввода), эти сторонние приложения могут оказаться слабым звеном. Визуализация процесса в таких системах, даже если это только измерение загрузки процессора на каждой из участвующих машин, может быть очень полезна. Знать о том, где находится стена важно не только для ее отодвигания, но и также для предоставления предсказуемости, так чтобы можно было эффективно управлять бизнесом Как найти баланс между краткостью и абстрактностью Обобщение – основа программирования. Выбирать степень обобщения нужно очень осторожно. Начинающие программисты-энтузиасты зачастую стараются создать более общий код, чем нужно на самом деле. Один из признаков этого – классы, которые не содержат осмысленных функций и не служат ни для чего кроме обобщения. Привлекательно, конечно. Но нужно сопоставлять краткость кода с ценностью такой общности. Иногда идеалистическая ошибка очевидна: в самом начале проекта удается определить массу замечательно общих классов, и возникает искушение заявить, что они описывают практически все, что может встретиться на практике. Но по мере того, как проект развивается, его создатели устают, а код становится все более путанным. Функции становятся длиннее, чем нужно. Пустые классы становится все труднее документировать, и этим пренебрегают под давлением сроков. В конечном итоге становится ясно, что силы лучше было бы потратить не на обобщение, а на сокращение и упрощение кода. Это разновидность спекулятивного программирования. Горячо рекомендую статью Пола Грэма (Paul Graham) «Сила в краткости» [PGSite]. Такие в целом полезные методики, как сокрытие информации и объектно-ориентированное программирование, часто воспринимаются слишком догматично. Да, эти методы дают возможность создавать обобщенный код, устойчивый к изменениям задачи. Но лично я считаю, что писать подобный умозрительный код большими объемами не стоит. Например, общепринята практика скрывать целочисленное значение модификаторами и методами доступа, в результате чего видна не сама переменная, а лишь небольшой интерфейс для обращения к ней. Это позволяет изменять реализацию такой переменной, не затрагивая вызывающий ее код. Такой подход хорош для автора библиотеки, который должен представить как можно более стабильный программный интерфейс. Но мне кажется, что преимущества подобной избыточности кода неоправданны, если команде доступен вызывающий код, а следовательно, переписать его можно с той же легкостью. Четыре-пять лишних строк кода – слишком дорогая плата за умозрительное преимущество. Портируемость ставит еще одну проблему. Должен ли код переноситься на другой компьютер, компилятор, программную систему или платформу, или, просто-напросто, портирован? Я думаю, что не-портируемые, маленькие-и-легко-портируемые кусочки кода всё же лучше чем такие же но большие. Это неплохая и сравнительно простая идея: ограничиваться с непортируемым кодом в объявляемых области, таких как класс, который создает базу данных запросов в особенности отправляемые DBMS. Как осваивать новые навыки Приобретение новых навыков, особенно нетехнических, это очень весело. Большинство компаний могли бы иметь более высокий боевой дух, если бы они понимали как это мотивирует программистов. Люди учатся в процессе работы. Чтение книг и занятия в группах полезны. Однако, можете ли вы уважать программиста, который не написал ни одной программы? Для получения навыка, вы должны поставить себя в щадящие условия, когда вы можете отработать этот навык. При изучении нового языка программирования, попытайтесь сделать небольшой проект перед тем, как делать крупный. При изучении управления программным проектом, попробуйте сначала на небольшом. Хороший наставник это не замена самостоятельной работы, но это гораздо лучше, чем книга. Что вы можете предложить ему в замен на его знания? Как минимум, усердное обучение, чтобы его время не тратилось впустую. Попробуйте уговорить шефа на формальное обучение, но помните, что часто это не намного лучше, чем провести то же время просто играя с навыком, который вы хотите приобрести. Тем не менее, в нашем несовершенном мире легче просить время на обучение, а не на игры, пусть даже на большей части лекций вы будете дремать в ожидании обеденного перерыва. Если вы возглавляете людей, относитесь с пониманием к их учебе и содействуйте им, поручая проекты не слишком большого размера, на которых они смогут опробовать интересующие их навыки. Не забывайте, что наиболее важные навыки для программиста - нетехнические. Давайте людям возможность играть и учиться быть храбрыми, честными и общительными. Учитесь печатать Учитесь печатать вслепую. Это вспомогательный навык, ведь написание кода настолько сложно, что скорость печати несущественна и не слишком сказывается на времени, необходимом для написания кода, даже если вы в этом очень сильны. Однако, став программистом среднего уровня, вы, вероятно, будете тратить много времени на переписку с коллегами и знакомыми. Это своего рода тест на заинтересованность: изучение такого рода вещей занимает определенное время и само по себе удовольствия не приносит. Легенда утверждает, что когда Майкл Тиман (Michael Tiemann)[2] работал в корпорации MCC (Microelectronic and Computer Technology, Corp), люди часто останавливались у его дверей, чтобы послушать сливающийся в непрерывное жужжание стук нажимаемых им клавиш. Как проводить тестирование интеграции? Интеграционное тестирование - это тестирование интеграции различных компонентов, которые [уже] были протестированы помодульно. Интеграция является дорогой, и [обычно] она выпадает из процесса тестирования. Вы должны включить время для этого при своих оценках и в план. В идеале, вам следует организовать проект таким образом, что фаза интеграции не должна присутствовать в явном виде. Намного лучше постепенно интегрировать вещи по мере их завершения в течение развития проекта. Если интеграционное тестирование неизбежно, оценивайте его внимательно. Языки описания данных Есть несколько языков (т.е. формально определенных синтаксических систем), которые не являются языками программирования, а служат для описания данных - они используются для облегчения обмена информацией через стандартизацию. В 2003 году самыми важными из таких языков были UML, XML и SQL. Вы должны быть знакомы с каждым из них, чтобы иметь возможность сводобно общаться и понимать когда их можно использовать. UML это эффективная система для создания схем, описывающих дизайн. Его красота в том, что он, будучи одновременно формальным и визуальным, способен передать значительный объем информации, если автор и зрители знают UML. Вам следует его знать потому что информацией о дизайне часто обмениваются в этой форме. Есть очень полезные инструменты для создания профессионально выглядящих XML диаграмм. Однако XML слишком формален, и я часто обнаруживаю себя использующим более простой стиль форм и стрелок при описании архитектуры. Тем не менее я уверен, что UML будет для Вас даже полезнее изучения латыни. XML это стандарт для описания стандартов. Это не решение проблемы обмена данными, как его часто пытаются представить. Зато это долгожданное средство автоматизации самой нудной части такого обмена - перевода из структуры в последовательное представление и назад. XML также обеспечивает удобные проверки типов и правильности структуры, но опять же - лишь часть от того что обычно надо на практике. SQL это очень мощный язык запросов и обработки данных, не являющийся полноценным языком программирования. У него много вариантов, в основном привязанных к конктерному продукту, и потому менее важных чем стандартная основа. SQL это лигва-франка реляционных БД. Вы можете и не работать в области, где знание реляционных БД полезно, но базовые понятия о них и SQL у Вас должны быть. Сложные инструменты По мере развития технологической культуры, программное обеспечение так же двигается от чего-то непостижимо сложного к новым, стандартизированным, доступным и дешевым продуктам. Появляются и инструменты, которые могут взять на себя значительую часть работы, но они могут также быть пугающе сложными и требовать значительных усилий для освоения. Рядовой программист должен знать как использовать их, и понимать в каких ситуациях они могут пригодиться. На мой взгляд среди лучших таких инструментов можно отметить: - Реляционные БД, - Системы полнотекстового поиска, - Математические библиотеки, - OpenGL, - XML парсеры, - Табличные редакторы. Как анализировать данные -- Анализ данных производится на начальном этапе разработки ПО, когда Вы изучаете бизнес-процессы с целью выявления требований к будущей программе. Таково формальное определение, которое может подтолкнуть Вас к мысли что анализ данных лучше оставить системным аналитикам, а Вы, как разработчик, займётесь кодированием по предоставленным спецификациям. И это может оказаться правдой, если строго следовать методике разработки ПО. Опытные программисты становятся архитекторами, выдающиеся архитекторы становятся бизнес-аналитиками - и берут на себя задачу превращения потоков данных в конкретную задачу для Вас. И все же это не совсем точно, ведь что бы Вы не делали в своих программах, Вы либо используете данные, либо их изменяете. Аналитик изучает потребности в целом, в большом масштабе; архитектор уменьшает масштаб так, что когда задача оказывается у Вас на столе, кажется остается только применить умные алгоритмы и начинать "жонглировать" данными. Это не так. Не важно на каком этапе Вы находитесь, данные - вот главная забота хорошо спроектированной программы. Если Вы поинтересуетесь как именно аналитик выводит требования из запросов пользователей, Вы поймете что данные играют важнейшую роль. Аналитики создают так называемые "схемы потоков данных" (Data Flow Diagrams), где обозначены источники и направления движения информации. Точно определив какие данные должны быть в системе, архитектор приведет источники данных к понятиям реляционных БД, протоколов обмена и форматов файлов, так что задачу можно будет передавать программисту. Однако процесс еще не завершен - Вам, как разработчику, даже после всего этого процесса обработки данных, все равно надо анализировать их чтобы решить задачу наилучшим способом. Основной элемент Вашей задачи сформулирован Никлаусом Виртом, создателем нескольких языков программирования. "Алгоритмы + структуры данных = программы". Алгоритм сам по себе никогда ничего не делает. Каждый алгоритм должен что-то делать хотя бы с небольшой частью данных. Таким образом, поскольку алгоритмы обитают не в безвоздушном пространстве, следует проанализировать не только уже определенные кем-то данные, но и данные, которые требуются для написания кода. Поясним это на простом примере. Вы создаете процедуру поиска в библиотеке. Согласно спецификациям пользователь может выбирать книги по их жанру, автору, заголовку, издателю, году выпуска и числу страниц в любых комбинациях. Конечная цель процедуры – порождение работоспособной инструкции SQL для поиска в исходной базе данных. Руководствуясь этими требованиями, можно пойти несколькими путями: проверять элементы управления последовательно, используя инструкцию "switch" или несколько инструкций "if"; создать массив элементов управления, проверяя, задан ли каждый из них; создать (или использовать готовый) абстрактный объект элемента управления, унаследовать от него все реальные элементы и подключить их к механизму, управляемому событиями. Если, кроме того, требуется повысить производительность запроса путем проверки элементов в заданном порядке, то при конструировании инструкции SQL можно воспользоваться и деревом компонентов. Как видите, выбор алгоритма зависит от того, какие данные решено использовать или создавать. Такие решения могут определить, будет ли алгоритм эффективным или совершенно непригодным. Однако, принимать во внимание нужно не только эффективность. Можно использовать в коде десяток именованных переменных и сделать его настолько эффективным, насколько это вообще возможно. Но вот поддерживать этот фрагмент кода может оказаться нелегко. Не исключено, что при подходящем выборе контейнера для переменных удастся сохранить ту же скорость и в то же время облегчить жизнь тому, кто попробует разобраться в нем через год. Более того, выбор продуманной структуры данных может позволить расширять функциональность кода, не переписывая его. В конечном счете, выбор представления данных определит срок жизни кода после окончания работы над ним. Позвольте предложить в качестве дополнительной пищи для размышления еще один пример. Предположим, что необходимо найти в словаре все слова, имеющие более трех анаграмм, также содержащихся в этом словаре. Если для решения этой задачи выбран вычислительный подход, дело кончится бесконечным перебором всех комбинаций каждого слова и сравнением их с другими словами в списке. Однако, если проанализировать имеющиеся данные, станет ясно, что каждое слово можно представить в виде записи, содержащей само слово и отсортированный массив его букв в качестве идентификатора. При таком подходе найти анаграмму означает всего лишь отсортировать список по дополнительному полю и выбрать элементы с одинаковым идентификатором. "Лобовому" алгоритму потребуется для выполнения несколько дней, в то время как "умному" алгоритму будет достаточно нескольких секунд. Вспомните этот пример в следующий раз, когда столкнетесь с неподатливой проблемой. Командные навыки Как управлять временем разработки Для управления временем разработки, поддерживайте (соблюдайте) краткий и актуальный план проекта. План проекта - это оценка, график, набор этапов для отметок хода выполнения и присвоение каждому заданию времени вашей команды или вашего личного времени. Он также должен включать другие вещи, а которых вы должны помнить, такие как собрания с [тестировщиками (QA, ответственными за качество людьми)], подготовку документации или приведение в порядок оборудования. Если вы работаете в команде, план проекта должен быть согласован вначале и в процессе выполнения. План проекта существует для того, чтобы помогать принимать решения, а не для того чтобы показывать насколько вы организованны. Если план проекта слишком длинный или не актуальный, он будет бесполезным для принятия решений. Фактически, эти решения об отдельных людях. План и ваша рассудительность позволяют вам решать, следует ли перекладывать задания с одного человека на другого. Этапы для отметок хода выполнения. Если вы используете модный инструмент для планирования проектов, не поддавайтесь соблазну создавать BDUF-план (Big Design Up Front) для проекта, а используйте его для поддержания краткости и актуальности. Если вы пропустите этап, вам следует немедленно оповестить своего шефа о том, что запланированное завершение проекта сдвинуто на определенный срок. Оценка и планирование никогда не могут быть совершенными с самого начала; это создает иллюзию, что вы можете возместить пропущенные дни в оставшейся части проекта. Возможно. Но это всего лишь возможно, что вы недооценили ту часть так же, как переоценили эту. Поэтому запланированное завершение проекта уже сдвинулось, нравится вам это или нет. Убедитесь, что ваш план включает в себя время на: внутрикомандные собрания, демонстрации, документацию, запланированные периодические мероприятия, тестирование интеграции, работу с аутсайдерами, болезни, отпуска, поддержку существующих продуктов и процесса разработки. План проекта может служить способом получения аутсайдерами или вашим шефом представления о том, чем сейчас занимаетесь вы и ваша команда. По этой причине, он должен быть кратким и актуальным. Как управлять риском, связанным с использованием чужого программного обеспечения Нередко проект зависит от программного обеспечения, производимого неподконтрольными организациями. Каждый участник проекта должен осознавать, что с использованием чужого программного обеспечения связан серьезный риск. Никогда не возлагайте надежд на пустышку. Пустышка – это программное обеспечение, которое заявлено, но пока недоступно. Надеяться на него – наивернейший способ покинуть бизнес. Недостаточно просто скептически относиться к обещаниям компании выпустить определенный продукт к определенной дате. Гораздо умнее игнорировать такие обещания, забыть о них вообще. Они не должны упоминаться ни в одном документе, с которым имеет дело компания. Если чужое программное обеспечение не пустышка, риск остается, но с этим риском хотя бы можно иметь дело. Если предполагается использовать чужое программное обеспечение, посвятить время его оценке нужно заранее. Может быть, кому-то не понравится услышать, что оценка пригодности каждого из трех продуктов займет две недели или два месяца, но сделать это нужно как можно раньше. Без правильной оценки этих продуктов нельзя будет точно оценить затраты на их интеграцию. Определить, подходит ли чужое программное обеспечение для достижения конкретной цели, могут лишь немногие избранные. Это очень субъективная задача, обычно подвластная только знатокам. Найти таких знатоков – значит, сэкономить много времени. Очень часто зависимость проекта от чужой программной системы настолько глубока, что возникновение проблем с интеграцией будет означать провал всего проекта. Риск такого рода должен быть описан в плане работ явно и недвусмысленно. Если его нельзя исключить заранее, постарайтесь придумать запасной план, предполагающий, к примеру, использование другой системы или самостоятельную разработку необходимой функциональности. План работ никогда не должен зависеть от пустышки. Как управлять консультантами Пользуйтесь услугами консультантов, но не полагайтесь на них. Это замечательные люди, которые заслуживают огромного уважения. Поскольку им доводится видеть множество различных проектов, они нередко знают больше и о конкретных технологиях, и даже о технике программирования. Лучше всего использовать их как домашних учителей, которые могут учить на примерах. Однако, обычно им не удается стать частью команды в той же мере, что и штатные сотрудники, хотя бы потому, что просто нет времени изучить их сильные и слабые стороны. Их обязательства финансового рода намного ниже. Им намного легче уйти. Возможно, они меньше выигрывают от того, что компания преуспевает. Одни окажутся хорошими, другие средними, а третьи плохими, но надо надеяться, что выбор консультантов проводится менее тщательно, чем выбор сотрудников, так что плохих будет больше. Если консультанты собираются писать код, его необходимо внимательно просматривать, прежде чем принимать. Нельзя подходить к концу проекта с риском, что большой массив кода не был просмотрен. На самом деле, это справедливо в отношении всех участников команды, но те, что ближе, обычно знакомы лучше. Как правильно проводить совещания Тщательно взвесьте затраты на проведение совещания. Они равны его продолжительности, умноженной на число участников. Совещания иногда необходимы, но обычно чем меньше в них участников, тем лучше. Качество общения в узком кругу выше, да и времени в целом теряется меньше. Если хоть кто-то на совещании скучает, это признак того, что число участников нужно сократить. Нужно сделать все возможное для того, чтобы общение было как можно менее формальным. Больше, чем в любое другое время, удается сделать во время обеда с коллегами. Жаль, что в большинстве компаний этого не понимают и не признают. Как возражать против принятого решения и не наживать проблем Выразить несогласие с решением – хорошая возможность поспособствовать принятию правильного решения, но делать это необходимо деликатно. Надеемся, вы чувствуете, что адекватно выразили свои соображения и были услышаны перед принятием решения. В этом случае сказать больше нечего и нужно решить, будете ли вы поддерживать решение, хотя и не согласны с ним. Если вы можете поддержать решение, хотя и не согласны с ним, скажите об этом. Это покажет вашу ценность как независимого и не склонного поддакивать человека, который, тем не менее, уважает принятые решения и остается командным игроком. Иногда решение, с которым вы не согласны, бывает принято потому, что принимавшие его не вникли до конца в вашу точку зрения. В этом случае нужно решить, стоит ли поднимать вопрос, основываясь на выгоде для компании или команды. Если вы считаете, что ошибка невелика, вряд ли что-то стоит пересматривать. Если вы считаете, что это серьезная ошибка, то конечно, следует представить свои доводы. Обычно это не составляет проблемы. Иногда в нервной обстановке люди определенного типа могут воспринять это близко к сердцу. Например, некоторым очень хорошим программистам недостает уверенности для того, чтобы поставить решение под сомнение, даже если у них есть основания считать его неверным. В самом худшем случае сомневается тот, от кого зависит принятие решения, и воспринимает возражения как попытку подорвать его авторитет. Необходимо помнить, что в таких обстоятельствах у людей могут срабатывать самые низменные инстинкты. Вы должны представить свои доводы с глазу на глаз и попытаться доказать, что новые обстоятельства меняют основания для принятого решения. Независимо от того, будет ли изменено решение, нужно помнить, что вам уже не удастся воскликнуть "Я же говорил!", потому что альтернативное решение было полностью изучено. Принятие решений Как поступаться качеством в пользу времени разработки Разработка программного обеспечения – это всегда компромисс между возможностями проекта и возможностями его завершения. Но вас могут попросить поступиться качеством для ускорения развертывания проекта, что неприятно заденет вас как разработчика или как бизнесмена. Например, то, о чем вас просят, может считаться дурным тоном при разработке программного обеспечения и потенциально приведет к появлению множества проблем при сопровождении проекта. Если это произойдет, первым делом необходимо проинформировать команду и четко объяснить, во что обойдется снижение качества. В конце концов, вы наверняка понимаете это гораздо лучше, чем ваш шеф. Разъясните, что будет потеряно и что получено, и какой ценой потерянное будет восстановлено в следующем цикле разработки. Дать наглядное представление этого поможет хороший план проекта. Если снижение качества затронет работу службы QA, укажите на это (как шефу, так и персоналу службы QA). Если снижение качества приведет к появлению большего числа ошибок по завершении периода проверки качества, укажите и на это. Если шеф все же настаивает, нужно попробовать ограничить халтурный код несколькими конкретными компонентами и запланировать переписать или улучшить их в следующем цикле разработки. Объясните это команде, чтобы она была к этому готова. NinjaProgrammer из Slashdot приводит мудрое изречение: Помни, что хороший дизайн устойчив к плохим программным реализациям. Если в коде используются хорошие интерфейсы и абстракции, переписывать его при необходимости будет гораздо менее болезненно. Если трудно написать ясный код, который трудно исправить, подумай, в чем состоит недостаток базового дизайна, который создает эту проблему. Как управлять зависимостями программной системы Современные программные системы, как правило, зависят от большого числа компонентов, не все из которых непосредственно подконтрольны вам. Синергизм и повторное использование повышают продуктивность. Однако, каждый компонент привносит определенные проблемы: Как исправлять ошибки в этом компоненте? Не ограничено ли применение компонента определенными аппаратными или программными системами? Что делать, если компонент полностью выйдет из строя? В любом случае лучший выход – инкапсулировать компонент тем или иным способом, изолировав его и обеспечив возможность замены. Если компонент оказывается совершенно неработоспособным, иногда удается найти другой аналог, но может быть, потребуется написать собственный. Инкапсуляция – это еще не мобильность, но она облегчает перенос, что почти так же хорошо. Наличие исходного текста компонента снижает риск в четыре раза. Если доступен исходный текст, его проще оценить, проще отладить, проще обойти проблемы и проще исправить ошибки. Если вы исправляете ошибки, необходимо предоставить исправления владельцу компонента, чтобы он мог включить их в официальный выпуск. В противном случае вы столкнетесь со всеми неудобствами, связанными с поддержкой неофициальной версии. Как определить, достаточно ли зрело программное обеспечение Использование программного обеспечения других разработчиков – один из самых эффективных путей быстрого создания серьезной системы. Не стоит этому препятствовать, но нужно изучить свойственный такому подходу риск. Один из наиболее рискованных периодов – период незрелости программного обеспечения, когда оно еще не выросло в процессе применения в полезный продукт, полно ошибок и почти непригодно для использования. Прежде чем решиться интегрировать такой продукт в программную систему – как собственной разработки, так и другого производителя – важно определить, достаточно ли он зрел. Вот десять вопросов на эту тему, которые нужно себе задать: Не "пустышка" ли это? (Обещания очень незрелы.) Доступен ли кто-нибудь, профессионально разбирающийся в этом продукте? Вы первый пользователь? Имеется ли устойчивый стимул для развития продукта? Производится ли поддержка продукта? Выживет ли продукт в отсутствие тех, кто его сейчас поддерживает? Имеется ли испытанная альтернатива, которая хотя бы вполовину так же хороша? Знаком ли продукт вашей команде или компании? Желает ли ваша команда или компания иметь с ним дело? Можете ли вы нанять людей для работы с продуктом, даже если он плох? Если поразмыслить над этими критериями, становится ясно, что заметно снизить риск для заказчика может использование общепризнанного бесплатного ПО и ПО с открытым исходным текстом. Как выбрать между покупкой и разработкой Компания или проект заказчика, которые пытаются добиться чего-то с программным обеспечением, вынуждены постоянно принимать решения, обычно называемые решениями "купить или разработать". Этот оборот неудачен в двух аспектах: во-первых, он игнорирует ПО с открытым исходным текстом и бесплатное ПО, которое не обязательно покупают. Во-вторых, что еще важнее, следовало бы говорить "приобрести и интегрировать или разработать на месте и интегрировать", поскольку нужно учитывать затраты и на интеграцию. Для такого выбора требуется комбинация деловой, управленческой и конструкторской смекалки. Насколько ваши нужды соответствуют тем нуждам, для удовлетворения которых был разработан продукт? Какая часть приобретаемого вам реально потребуется? Каковы затраты на оценку интеграции? Каковы затраты на интеграцию? Каковы затраты на оценку интеграции? Повысит или понизит покупка затраты на поддержку в долгосрочной перспективе? Не поставит ли вас разработка в положение, в котором вы не хотели бы оказаться? Следует подумать дважды, прежде чем приниматься за разработку системы, достаточно большой, чтобы служить основой всего остального бизнеса. Такие идеи часто предлагают блестящие оптимисты, которые могут стать ценным приобретением для вашей команды. У вас может появиться непреодолимый соблазн изменить бизнес-план. Но не вкладывайте, не поразмыслив как следует, средства в решение, которое превышает по размеру весь ваш собственный бизнес. После рассмотрения этих вопросов нужно, вероятно, подготовить два черновых плана проекта – один на случай разработки и один на случай покупки. При этом придется рассмотреть и затраты на интеграцию. Кроме того, нужно будет рассмотреть затраты на поддержку обоих решений в долгосрочной перспективе. Чтобы оценить затраты на интеграцию, необходимо будет произвести тщательную оценку программного обеспечения перед его приобретением. Если оценка невозможна, следует считать риск, связанный с покупкой этого конкретного продукта, неоправданным и воздержаться от нее. Если рассматривается несколько вариантов покупки, необходимо потратить силы на оценку каждого из них. Как добиваться профессионального роста Принимайте на себя ответственность, превышающую ваши полномочия. Играйте ту роль, которую хотите играть. Выражайте людям благодарность за их вклад в успех всей организации, а также в ваш личный успех. Если вы хотите стать лидером команды, старайтесь сформировать единодушное мнение. Если вы хотите стать менеджером, берите на себя ответственность за план работ. Обычно это можно с успехом делать, работая в сотрудничестве с лидером или менеджером, и тем самым освобождая их для принятия еще большей ответственности. Если этого многовато для одного раза, делайте это понемногу. Оцените себя. Если вы хотите быть более хорошим программистом, спросите у тех, кем восхищаетесь, как стать похожим на них. Можете спросить об этом и у шефа – пусть он и знает меньше, зато от него в большей степени зависит ваша карьера. Планируйте освоение нового, начиная от тривиальных технических задач, таких как изучение новых программных систем, и заканчивая сложными социальными навыками, такими как написание хорошего кода. Интегрируйте полученные знания в свою работу. Как оценивать соискателей Оценке потенциальных сотрудников не уделяется столько внимания, сколько она заслуживает. Неудачный наем так же ужасен, как неудачный брак. Вербовке кадров должна быть посвящена значительная часть энергии каждого члена команды, хотя делается это и редко. Существуют различные стили собеседования. Некоторые из них мучительны для кандидата и приводят его в состояние серьезного стресса. Это дает очень хорошую возможность обнаружить слабости и недостатки характера в стрессовой ситуации. Кандидаты ведут себя с интервьюерами уж никак не честнее, чем с самими собой, а человеческие возможности в плане самообмана поражают воображение. Как минимум, необходимо предложить кандидату эквивалент двухчасового устного экзамена по техническим навыкам. С опытом вы научитесь быстро пробегать темы, которые они знают и быстро отказываться от дальнейших вопросов на темы, которые они не знают, чтобы очертить границу. Соискатели оценят это. Несколько раз я слышал от соискателей, что качество собеседования стало для них одним из мотивов выбора компании. Хорошие работники хотят, чтобы их нанимали за их умения, а не в зависимости от последнего места работы, имеющихся дипломов или еще каких-то несущественных деталей. В процессе собеседования нужно оценить и их способность обучаться, что гораздо важнее, чем то, что они уже знают. Необходимо также следить, не припахивает ли соискатель горящей серой, что свойственно трудным людям. Все это можно определить, просматривая заметки после собеседования, если в разгар собеседования сделать это непросто. Насколько хорошо люди умеют общаться и сотрудничать с другими, важнее, чем владеют ли они новейшим языком программирования. Один из моих читателей успешно использует "домашний" тест для соискателей. Преимущество этого подхода в том, что он позволяет обнаружить соискателей, которые могут произвести благоприятное впечатление, но не умеют на самом деле программировать, а подобных людей много. Лично я не пробовал такой метод, но звучит это разумно. Наконец, собеседование – еще и аналог торговли. Вы как бы продаете кандидату свою компанию или проект. Однако, поскольку вы говорите с программистом, не пытайтесь приукрасить действительность. Начните с плохого, затем уверенно закончите на хорошем. Как решить, стоит ли применять необычные компьютерные технологии Существует определенное множество знаний об алгоритмах, структурах данных, математических методах и других занимательных вещах, о которых большинство программистов слышало, но редко использует. На практике эти замечательные вещи слишком сложны и обычно не нужны. Нет смысла улучшать алгоритм, если большая часть времени тратится, например, на неэффективные запросы к базе данных. Прискорбно много сил уходит у программиста на организацию диалога между системами и создание красивого пользовательского интерфейса с использованием очень простых структур данных. Когда же подходящей оказывается высокая технология? Когда нужно раскрыть книжку и найти в ней нечто посложнее рутинного алгоритма? Иногда это бывает полезно, но необходима тщательная оценка. Вот три наиболее важных соображения, касающихся потенциального использования компьютерной технологии: Достаточно ли хорошо ли она инкапсулирована, чтобы гарантировать малый риск для других систем и малое общее повышение сложности и затрат на поддержку? Впечатляют ли преимущества (например, повышение производительности вдвое для зрелой системы или вдесятеро для новой системы)? Сможете ли вы обеспечить ее эффективное тестирование и оценку? Если хорошо изолированный модуль, использующий несколько вычурный алгоритм, может снизить затраты на оборудование или повысить производительность всей системы вдвое, было бы преступлением не рассмотреть такую возможность. Ключевым аргументом в пользу такого подхода будет доказательство того, что риск действительно довольно мал, поскольку предлагаемая технология была, вероятно, хорошо изучена. Проблему составляет только риск интеграции. При этом облегчить интеграцию необычной технологии могут опыт и мудрость программиста. Как разговаривать с не-инженерами В массовом сознании инженеры и особенно программисты воспринимаются обычно как люди, отличающиеся от других. В свою очередь это означает, что другие люди отличаются от нас. Полезно держать этот факт в голове, общаясь с не-инженерами. Важно всегда понимать собеседника. Не-инженеры не глупы, но не так глубоко разбираются в технических вещах, как мы. Мы создаем вещи. Они продают вещи, используют вещи, считают вещи и управляют вещами, но не разбираются в создании вещей. Они не настолько хорошо работают в команде, как инженеры (хотя, конечно, есть и исключения). Их социальные навыки в некомандной среде обычно не хуже, если не лучше, чем у инженеров, но их работа, в отличие от нашей, не всегда требует навыков близкого и скрупулезного общения, а также тщательного разделения задач. Не-инженеры могут желать угодить вам или просто испытывать перед вами робость. Как и мы, они могут сказать "да", не имея этого в виду на самом деле, просто чтобы угодить вам, или потому что они вас побаиваются, а потом не сдержать своего слова. Не-программисты могут понять технические детали, но у них нет того, что и нам-то тяжело дается – технической мудрости. Они понимают, как работает технология, но не могут понять, почему один подход потребует три месяца, а другой – три дня. (В конце концов, программисты тоже анекдотично ужасны в оценках такого рода.) Это дает отличную возможность для объединения с ними усилий. Разговаривая со своей командой, вы, не задумываясь, используете нечто вроде стенографии – сокращенный язык, эффективный постольку, поскольку у вас имеется большой совместный опыт работы с технологиями вообще и над конкретным продуктом в частности. Необходимо определенное усилие, чтобы не использовать эту стенографическую речь в разговоре с теми, у кого нет подобного опыта, особенно если при этом присутствуют другие участники команды. Этот словарь создает барьер между вами и теми, кто не владеет им. Даже хуже – они просто теряют время. В разговоре с командой не нужно часто напоминать об основных предпосылках и целях, и дискуссия обычно сосредоточена на деталях. С посторонними все должно обстоять с точностью до наоборот. Они могут не понимать то, что для вас самоочевидно. Если вы воспринимаете какие-то вещи как очевидные и не повторяете их, после разговора с посторонним человеком вы можете полагать, что поняли друг друга, хотя на деле сохранилось серьезное недопонимание. Необходимо заранее предполагать, что вас могут понять неправильно, и внимательно следить, чтобы не пропустить моменты неправильного понимания. Попробуйте добиться от них краткого изложения сказанного, чтобы убедиться в том, что они поняли правильно. Если есть возможность встречаться с ними чаще, потратьте немного времени и спросите у них, эффективно ли ваше общение, и как можно его улучшить. Если имеются проблемы, связанные с общением, то прежде чем разочаровываться в их манере общения, попробуйте изменить собственную. Я люблю работать с не-инженерами. Это дает хорошую возможность учиться и учить. Например, вы можете научиться выражаться намного яснее. Инженеры умеют извлекать порядок из хаоса, ясность из путаницы. Это-то в нас и нравится не-инженерам. Поскольку мы обладаем технической мудростью и обычно можем разобраться в деловых вопросах, нам нередко удается найти простое решение проблемы. Не-инженеры часто предлагают решения, которые, на их взгляд, упростят нам жизнь. Они делают это по доброте душевной и из желания помочь, хотя на самом деле существует гораздо более удобное общее решение, увидеть которое можно, лишь соединив их видение проблемы с нашей технической мудростью. Лично мне нравится концепция экстремального программирования за то, что позволяет справиться с этой неэффективностью. Возможность быстро соединить оценку с идеей облегчает поиск идеи, обеспечивающей наиболее выгодное соотношение преимуществ и затрат. -------------------------------------------------------------------------------- [1] "врезаться" Глава 4. Более сложные понятия. Содержание Технологическое мышление Как отличить трудное от невозможного Как использовать встроенные языки Выбор языков Мудрый выбор компромисса Как бороться с давлением расписания Как понимать пользователя Как заслужить повышение Обслуживание команды Как развить талант Как выбирать над чем работать Как получать максимум возможного от своих коллег по команде Как разделять проблемы Как выполнить скучные задания Как приобретать поддержку дла проекта Как вырастить систему Как правильно общаться Как говорить людям то, что они не хотят слышать Как иметь дело с мифами управления Как иметь дело с организационным хаосом Технологическое мышление Как отличить трудное от невозможного Это наша работа - делать трудные вещи и отбрасывать невозможные. С точки зрения работающих программистов, нечто является невозможным, если его нельзя развить из простой системы, или если оно не может быть оценено. Используя это определение, то, что называют исследованием, является невозможным. Большие объемы простой работы являются трудной задачей, но необязательно невозможной. Эта разница весьма серьезна, поскольку вас могут убедительно попросить сделать что-нибудь практически невозможное, как с научной (академической?), так и с программерской точки зрения. С этого момента, вашей обязанностью будет помочь заказчику найти приемлемое решение, которое будет всего лишь трудным (но не невозможным) и позволит получить максимум от задуманного. Таким решением будет являться то решение, для которого можно уверенно указать сроки выполнения и оценить риски. Невозможно удовлетворить расплывчатые требования вроде: "построить систему, которая вычислит (найдет) наиболее привлекательные прическу и цвет волос для каждого человека". Если требования можно сделать более четкими, то задача превратится из невозвожной в трудную, например: "построить систему, которая вычислит (найдет) привлекательные прическу и цвет волос для человека, позволит просмотреть их, и, если нужно, сделать изменения, а также настолько удовлетворит клиентов модными прическами, что позволит заработать кучу денег". Если нет четкого определения, что должно получиться в результате, то ничего не выйдет. Как использовать встраиваемые языки Внедрение языка программирования в разрабатываемую систему наполняет программиста чуть ли не эротическим возбуждением. Это открывает новые творческие горизонты, это делает систему исключительно мощной, это позволяет управлять системой настолько, насколько хватает вдохновения. Все самые лучшие текстовые редакторы обладают поддержкой встроенных языков, давая больше той части аудитории, которая способна изучить предлагаемый язык.Конечно, язык можно и не использовать, поэтому те, кому это надо, получают дополнительные возможности, а остальные пользователи прекрасно проживут и без программирования. И я, и многие другие программисты попадались на крючок идеи создания встраиваемых языков специального назначения. Я угодил в эту ловушку даже дважды. Существует так много готовых предназначенных для встраивания языков программирования, что стоит дважды хорошо подумать, прежде чем изобретать свой собственный. Прежде чем внедрять в систему язык программирования, стоит спросить себя: поможет это моим пользователям, или скорее навредит? Если предполагаемые пользователи все как один не являются программистами, то как им это поможет? Если же вся целевая группа исключительно программисты, то, может, они бы предпочли наличие API? И какой язык выбрать? Программисты не любят изучать новый язык, применять который им придется только в небольшом количестве случаев; и даже если это будет необходимо, времени на изучение у них будет немного. Создавать новый язык, конечно, очень весело, но прежде всего все-таки надо думать про потребности пользователей. Если только у вас нет действительно уникальных потребностей или же радикальных идей по решению основных задач, стоило бы выбрать какой-нибудь из уже существующих языков, чтобы облегчить жизнь пользователей, уже с ним знакомых. Выбор языка Программист-одиночка, который любит то, чем занимается (хакер), волен выбирать тот язык, который считает наиболее подходящим под задачу. Большинство же программистов в своей работе ограничены в возможности выбирать язык, на котором им придется программировать. Как правило, выбор этот остается за малокомпетентными начальниками со странными прическами, для которых это решение скорее является политическим, нежели чем технологически правильным, и не у всякого разработчика хватит храбрости предложить и отстоять менее стандартное, но более подходящее решение - даже если у боссов уже есть горький опыт бездумного следования популярным решениям. Или же выбор, делаемый командой и нацеленный на получение максимального преимущества от использования наиболее общего для всей группы, перевешивает предпочтения конкретного члена команды. Зачастую руководство делает какой-то выбор на основе наличия на рынке специалистов, программирующих на данном языке, которых легко можно нанять. Конечно, они думают, что таким образом действуют в интересах проекта или компании, и надо бы уважать их стремление, но лично я считаю, что это наиболее часто встречаемое и разрушительное решение из тех, что вообще можно принять. Но, конечно, есть и другие пути. Даже если ядро языка вне вашего контроля, инструменты и прочие программы могут быть написаны и на другом языке. Если язык необходимо будет встраивать в систему (всегда надо помнить о такой возможности), то выбор языка будет во многом зависеть от пристрастий пользователей. Этот факт надо использовать на пользу компании или проекта, выбирая наилучший язык, тем самым делая работу интереснее. На самом деле языком программирования должна называться нотация, изучить которую не так сложно, как изучить живой язык. Для начинающих и некоторых неудачников изучение нового языка представляется чем-то пугающим, но после того, как у вас за плечами уже три языка, изучение нового — все лишь вопрос знакомства с доступными библиотеками. Кто-то думает, что системы, состоящие из компонентов, написанных на трех-четырех языках - это какой-то винегрет. Но мое мнение в том, что такие системы лучше моноязычных по нескольким параметрам: Необходимо слабое связывание между компонентами, написанными на разных языках (хотя ясные интерфейсы могут и отсутствовать). Вы легко можете задействовать новый язык путем переписывания каждого компонента в индивидуальном порядке. Возможно, некоторые модули уже находятся в актуальном состоянии. Некоторые из этих эффектов могут быть психологического характера, но психология тоже важна. В конце концов, цена засилья одного языка превышает все преимущества, которые можно извлечь из него. Разумные компромиссы Как бороться с прессом планирования Минимальное время до выхода на рынок (time-to-market)- это принцип максимально быстрого выпуска хорошего продукта. Он неплох, поскольку отражает финансовые реалии, и достаточно здрав. Пресс планирования (schedule pressure) - попытка выпустить продукт раньше, чем этот продукт вообще можно выпустить. Это разрушительно, непродуктивно и очень распространено. Пресс планирования появляется по разным причинам. Люди, которые ставят задачи программистам, не в полной мере понимают подходы и основную мотивацию программистов. Возможно потому, что они проецируют на нас принципы собственного поведения, они верят, что получат продукт раньше, если нас понукать и понуждать работать быстрее. Возможно, это и так, но получаемое ускорение мизерно, а ущерб - велик. К тому же, они не знают, что именно нужно для разработки программного обеспечения. Не зная этого и не умея создавать ПО самостоятельно, единственное, что они могут - создавать давление и ругаться с программистами. Ключ к борьбе с прессом планирования - превращение его в минимальное время до выхода на рынок. Для этого нужно показать взаимосвязь между объемом работ и продуктом. Лучший способ сделать это - дать честную, подробную и прежде всего, понятную оценку всего необходимого объема работ. У этого подхода есть дополнительное преимущество, позволяющее принимать хорошие управленческие решения относительно возможных вариантов функциональности продукта. Ключевой момент здесь: оценка должна четко прояснить, что объем работы подобен почти несжимаемой жидкости. Нельзя запихать больше работы в определенный отрезок времени, как нельзя налить воды больше, чем может поместиться в емкости определенного объема. В некотором смысле, программист никогда не должен говорить "нет", вместо этого он должен сказать: "чем вы готовы пожертвовать, чтобы получить, что хотите?" Умение делать правильные оценки будет повышать уважение к программистам. Именно так поступают профессионалы в других видах деятельности. Упорный труд программистов станет видимым. Установка нереальных сроков будет мучительно очевидна для всех. Программистов нельзя обмануть. Просьба сделать что-нибудь нереальное будет расценена как неуважение и деморализация. Экстремальное программирование усиливает всё вышесказанное и организует процесс вокруг этой идеи. Я надеюсь, читателям посчастливится использовать его. Как понимать пользователя Ваша обязанность - понимать пользователя и помогать в этом вашему шефу. Так как пользователь не принимает такого участия при создании продукта, как вы, он ведет себя немного иначе: Пользователь обычно делает короткие заявления. У пользователя есть своя работа; в основном, он думает о небольших улучшениях в продукте, а не о значительных. Пользователь не может иметь представление о всем круге пользователей вашего продукта. Это ваша обязанность — дать пользователю именно то, что он действительно хочет, а не то, что он говорит, что хочет. Тем не менее, лучше предложить ему что-то и заставить его согласиться с тем, что ваше предложение это именно то, что ему нужно, перед тем как вы начнете, [чем он не будет иметь представления о том, как это делается]. Ваша вера в свои собственные идеи об этом должны меняться. Вы должны сохранять самонадеянность и ложную скромность, зная чего именно хочет заказчик. Программисты обучаются, чтобы разрабатывать и создавать. Исследователи рынка обучаются, чтобы выяснять чего хотят люди. Эти два типа людей или два образа мышления в одном человеке, работая сообща, дают самые лучшие шансы для формулирования правильного видения. Чем больше времени вы проведете с пользователями, тем лучше вы сможете понять, что именно будет пользоваться успехом. Вы должны стараться проверять свои идеи на них изо всех сил. Вы должны есть и пить вместе с ними по возможности. Guy Kawasaki[Rules] подчеркнул важность наблюдения за пользователями в дополнение к простому выслушиванию их требований. Я верю, что у разработчиков и консультантов часто возникают огромные трудности, когда они пытаются заставить своих клиентов пояснить, что они действительно хотят. Если вы собираетесь быть консультантом, я бы посоветовал вам выбирать клиентов, основываясь не только на их кошельках, но и на ясности их ума. Как получить повышение Чтобы получить повышение на какую-нибудь роль, сначала попробуйте поиграть в эту роль Чтобы получить повышение на должность, сначала выясните, что ожидается от человека, занимающего эту должность, и сделайте это Чтобы получить повышение заработной платы, ведите переговоры, вооружившись фактами Если вы чувствуете, что вам пора продвигаться по службе, поговорите об этом с вашим шефом. Спросите явно, что вам необходимо сделать, чтобы получить повышение, и попытайтесь выполнить это. Это звучит банально, но часто наше понимание того, что нам нужно сделать значительно отличается от соображений шефа. К тому же, это будет подколкой вашему шефу. Вероятно, большинство программистов в каком-то смысле сильно переоценивают свои возможности — в конце концов, не можем же мы все быть в 10% лучших! Однако, я видел людей, которые были слишком недооценены. Нельзя ожидать, что чья-та оценка будет всегда соответствовать действительности, но, я думаю, в большинстве случаев люди достаточно справедливы с одной оговоркой: они не могут оценить вас, не видя вашей работы. Иногда, по случайности или личным обстоятельствам кто-то не заметит многого. Если вы много работаете дома или географически отделены от вашей команды и шефа, это особенно сложно. Служба в вашей команде Как разработать талант Ницше сильно преувеличивал, когда говорил: "Все, что нас не убивает, делает нас сильнее" Ваша главная ответственность - ответственность перед командой. Вы должны прекрасно знать каждого из членов своей команды. Вы должны нагружать ее, но не перегружать. Следует разговаривать с членами команды о том, как их лучше нагрузить. Если они участвуют в этом, они будут хорошо мотивированы. На каждый проект или каждый следующий проект, постарайтесь нагружать их в двух направлениях - как они предложили и как по вашему мнению будет лучше для них. [Нагружайте их не за счет бОльшего количества работы, а за счет новых навыков или лучше новых ролей для игры в команде.] Вы должны позволять людям (включая себя) изредка ошибаться и должны запланировать некоторое количество ошибок. Если никогда не ошибаться, не будет ощущения приключения. Если нерегулярные ошибки отсутствуют, значит вы плохо стараетесь. Когда кто-то ошибается, вы должны быть настолько добры с ним, насколько это возможно, при этом не обходясь с ним так, как если бы он преуспел. Пытайтесь подкупить и хорошо мотивировать каждого члена команды. Если кто-то еще не мотивирован, спросите его прямо, что же ему для этого нужно. Возможно, вам придется оставить его неудовлетворенным, но вы все равно должны знать желания каждого. Вы не можете опустить руки, работая с кем-то, кто умышленно не работает над своей долей нагрузки из-за низких моральных качеств или неудовлетворенности, и позволить ему болтаться мертвым грузом. Вы должны пытаться замотивировать его и сделать его производительным. Держитесь этой политики, пока хватает терпения. Когда терпение лопнет, увольте его. Вы не можете позволить остаться в команде кому-либо, кто работает меньше своих возможностей, поскольку это нечестно по отношению к команде. Четко доведите до сильных членов команды, что вы считаете их сильными, путём высказывания этого мнения публично. Восхваление должно быть публичным, а критика - приватной. Сильные члены команды, естественно, будут иметь более трудные задачи, чем слабые. Это совершенно естественно и никто не будет обеспокоен этим до тех пор, пока все упорно работают. Есть странный факт, не отражаемый в зарплате: хороший программист более производителен, чем 10 плохих программистов. Это ведет к странной ситуации. Довольно часто вы будете двигаться быстрее, если просто уберете слабых программистов. Если вы сделаете это, работа действительно будет продвигаться более быстрыми темпами в краткосрочной перспективе. Однако, ваше племя потеряет несколько важных преимуществ, а именно: обучение более слабых членов, распространение племенных знаний и возможность восстановления после потери сильного члена. Сильный должен быть аккуратен в этом отношении и должен обдумать эту проблему со всех сторон. Вы часто можете дать сильным членам команды трудную и интересную, но четко очерченую задачу. Как выбирать, над чем работать Вы уравновешиваете ваши личные потребности с потребностями команды, выбирая над какой частью проекта работать. Вы должны делать то, что вы делаете лучше всех, но попытайтесь найти способ нагрузить себя, выполняя не бОльшее количество работы, а тренируя новые навыки. Лидерские способности и навыки общения являются более важными, чем технические. Если вы достаточно сильны, возьмите на себя самую сложную или рискованную работу и сделайте ее как можно скорее, чтобы снизить риск. Как получать все от вашей команды Чтобы получить все от вашей команды, развивайте хороший командный дух и старайтесь, чтобы каждая личность была персонально заинтересована и задействована. Для укрепления командного духа такие банальные вещи как одежда с логотипом компании и вечеринки хороши, но не так, как личное уважение. Если каждый человек уважает остальных членов команды, никто не будет никого опускать. Командный дух рождается, когда люди делают одолжение для команды и думают об интересах команды прежде, чем о своих. Как руководитель, вы не можете требовать больше, чем вы вкладываете сами. [...] Иногда, это означает позволять вашим коллегам ошибаться. То есть, если это не сильно вредит проекту, нужно позволять команде поступать так, как они считают нужным, в соответствии с общим мнением, даже если вы стопроцентно уверены, что это неверно. В таком случае, просто открыто выскажите свое несогласие, но продолжайте придерживаться общего мнения. Не нойте, как будто вас к этому вынудили, просто заявите, что вы несогласны, но считаете, что мнение команды важнее. Зачастую, это заставит их отступить. Не настаивайте, чтобы они продолжали действовать в соответствии с первоначальным планом, если они от него отказались. Если найдется человек, который не согласится после обсуждения вопросов со всех возможных сторон, просто скажите, что вы должны принять решение и огласите его. Если есть возможность определить, что ваше решение оказалось неверным, как можно скорее исправляйте ситуацию и поощряйте тех, кто был прав. Спросите вашу команду, всех вместе и индивидуально. Что по их мнению подняло бы командный дух и создало бы эффективную команду? Хвалите часто, но не чрезмерно. Особенно хвалите тех, кто с вами не согласен, если они достойны похвалы. Хвалите прилюдно, а критикуйте наедине, с одним исключением. Иногда развитие человека или исправление им ошибки не может быть отмечено без привлечения внимания окружающих к факту самой ошибки, так что такого рода рост стоит отметить конфиденциально. Как распределить задачи? Занятно - взять проект некоей программы и разделить на задания, которые будут выполнены индивидуально. Это должно ускорить процесс. Иногда менеджеры любят думать, что оценка может быть сделана без обсуждения личного вклада в будущую работу. Это недопустимо, так как производительность людей меняется существенно. Тот, кто имеет особое знание предмета, к тому же постоянно совершенствуется, может оказать значительное влияние на производительность. Так же, как композитор учитывает тембр инструмента, на котором будут играть партию или как тренер спортивной команды принимает во внимание сильные стороны каждого игрока, опытный лидер команды, скорее не сможет отделить членов команды от разбиения проекта на задачи, которые им будут назначены. Это частично объясняет, что высокоэффективная команда не должна быть развалена. Есть, конечно, опасность что в этом случае людям станет скучно, так как они совершенствуют свои сильные качества и совсем не улучшают слабые, и не приобретают новых навыков. Однако, специализация - очень полезный инструмент повышения производительности, если не злоупотреблять. Как управлять скучными задачами? Иногда невозможно избежать скучных задач, которые являются важными для успеха компании или проекта. Эти задачи могут действительно подорвать боевой дух тех, кто должен их выполнить. По словам программиста Ларри Уолла, лучший способ справиться с этим - призвать на помощь лень. Попробуйте найти способ заставить компьютер выполнить задачу за вас или помочь коллегам сделать это. Поработав в течение недели над программой, которая сделает недельный объём ручной работы, вы получите огромное преимущество, будучи более образованным, а иногда и возможность повторить решение схожих задач. Если всё пропало, извинитесь перед теми, кто должен выполнить скучное задание, но ни в коем случае не позволяйте им делать это в одиночку. Поручите делать работу группе, по меньшей мере, из двух человек и поспособствуйте здоровому взаимодействию, дабы задача была выполнена. Как заручиться поддержкой для проекта Чтобы проект получил поддержку, нужно создать и распространить концепцию, которая продемонстрирует реальную ценность для организации в целом. Разрешите другим людям принять участие в создании этой концепции. Это даст им повод поддержать вас, а вы получите выгоду в виде их идей. Для своего проекта набирайте ключевых помощников (?) самостоятельно (лично). Везде, где только можно, не рассказывайте, а показывайте. Если есть возможность, создайте прототип или макет (модель) для демонстрации ваших идей. Прототип всегда является мощным средством, а в разработке ПО он имеет огромное превосходство перед любым текстовым описанием. Как выращивать систему Семя дерева содержит в себе идею зрелого дерева, но оно не представляет собой всю форму и силу взрослого дерева. Зародыш вырастает. Он становится крупнее. Он становится больше похож на зрелое дерево и имеет больше способностей (?). Со временем оно приносит плоды. Потом оно умирает и служит пищей для других организмов. Мы можем себе позволить рассматривать ПО таким же образом. А мост на это не похож. Не бывает маленьких мостов-младенцев, бывают только недостроенные мосты. Мосты намного проще, чем ПО. Представлять ПО в виде растения -- это правильно (хорошо), потому что мы можем добиться значительных результатов до того, как мы получим совершенную мысленную модель. Мы можем получить отклик (отзывы) от пользователей и использовать их для исправления процесса роста. Обрезка слабых веток способствует оздоровлению. Программист должен разработать завершенную систему, которую можно развернуть (установить) и использовать. Но продвинутый программист должен сделать больше. Вы должны разработать путь роста, который приведет к завершенной системе. Это ваша обязанность (?), взять росток идеи и построить путь, который, как можно более гладко, приведет его к полезному продукту (?). Чтобы добиться этого, вы должны представить конечный результат и распространить его таким образом, чтобы команда разработчиков прониклась им. Кроме этого, вы должны показать им путь, ведущий из любого места, где бы они не находились, к тому месту, куда они хотят прийти, без больших скачков. Дерево должно все время оставаться живым. Оно не может в определенный момент исчезнуть и появиться позже. Этот подход воплощен в разработке по спирали. Для маркировки прохождения пути используются промежуточные отметки, которые никогда не отстоят далеко друг от друга. В высококонкурентной среде бизнеса лучше всего как можно раньше выпускать промежуточные версии, которые сразу же начнут приносить прибыль, даже если они очень далеки от окончательного отлично спроектированного результата. Одна из обязанностей программиста — соблюдать баланс между быстрым доходом и будущим доходом, мудро выбирая путь роста, выраженный в промежуточных этапах. Продвинутый программист несет тройную ответственность: за выращивание ПО, команды и людей. Читатель Rob Hafernik так прокомментировал этот раздел, что я не могу сделать ничего лучше, как процитировать его полностью: Я думаю что вы недостаточно выразили значительность этого. Это касается не только систем, но и алгоритмов, пользовательского интерфейса, моделей данных и т.д. Когда вы работаете над большой системой, жизненно важно иметь осязаемые результаты по пути к промежуточным целям. Нет ничего кошмарнее (ужаснее), закончить (проект) и обнаружить, что ничего не работает (не собирается работать) (посмотрите на недавний облом с Voter News System). Я бы пошел даже дальше и сформулировал это как закон природы: никакая большая и сложная система не может быть создана с нуля, а только может быть развита из простой системы в сложную с помощью последовательности шагов. На это можно ответить только: воистину (+1) [да будет свет]. Как правильно общаться Чтобы научиться [правильно] общаться, нужно понять, насколько это сложно. Это умение [в себе]. Оно усложняется еще тем, что люди, с которыми придется общаться, [не совсем нормальные]. Они не прикладывают усилий, чтобы понять вас. Они недостаточно понятно выражаются [говорят и пишут]. Они часто переутомлены или подвержены скуке, и, как минимум, сосредоточены на своей работе вместо того, чтобы взглянуть на более широкий круг проблем, которые вы затрагиваете. Одним из преимуществ обучения и практики в писательстве, ораторстве и [слушании] является то, что, как только вы достигнете в этом успеха, вы сможете легче увидеть, в чем состоят проблемы, и как их исправить. Программист -- это социальное существо, выживание которого зависит от общения внутри его команды. Advanced программист -- это социальное существо, удовлетворенность которого зависит от общения с людьми вне его команды. Программист создает порядок из хаоса. Один интересный способ сделать это -- внести предложение по какому-либо вопросу [за пределами команды]. Это может быть сделано устно, или в виде наброска, или в виде официального документа. Инициатива дает огромное преимущество в установке сроков обсуждения. При этом, вы можете оказаться подвержены критике, или, в худшем случае, пренебрежению или отказу. Advanced программист должен быть готов к этому, потому что большие возможности влекут за собой большую ответственность. Предпринимателям-непрограммистам требуются программисты, которые должны стать лидерами в некотором смысле. Программисты являются частью моста между идеями и действительностью, опирающегося на реальность. Я еще не овладел [правильным общением] в совершенстве, но в настоящее время я стараюсь применять следующий [four-pronged, удар вилкой, наносящий одновременно четыре укола :)] подход. После того, как я приведу свои мысли в порядок и полностью подготовлюсь, я рассказываю о них людям, раздаю им (рассылаю) [техническое] предложение (как в бумажном, так и в электронном виде), показываю демо-версию и, затем, терпеливо повторяю весь процесс. Я много думал над тем, что мы недостаточно терпеливы в подобном непростом виде общения. Не нужно унывать, если ваши идеи не были приняты сразу же. Если вложить энергию в их подготовку, никто за это о вас плохо не подумает. Как говорить людям вещи, которые они не хотят услышать Вам часто придется говорить людям вещи, которые заставят их чувствовать себя неуютно. Помните, что вы делаете это не просто так. Даже, если нельзя сделать ничего с проблемой, вы должны сообщить об этом как можно раньше, чтобы они были в курсе. Лучше всего сообщить о проблеме одновременно предложив и ее решение. Второй приемлемый способ -- попросить помочь разобраться в проблеме. Если существует опасность, что вам не поверят, вы должны собрать некоторые подтверждения вашей позиции. Одной из наиболее неприятных и чаще встречаемых вещей, которые вам придется говорить -- это: "мы выбиваемся из графика". Добросовестные программисты не любят этого говорить, но должны это сделать как можно раньше. Нет ничего хуже откладывания дел при срыве сроков, даже если это дело заключается в оповещении всех. Делая это, лучше действовать от лица всей команды [...] Вам потребуется мнение всей команды, в каком состоянии вы сейчас находитесь, что можно с этим сделать, и с какими последствиями придется столкнуться команде. Как поступать с управленческими мифами Слово "миф" обычно обозначает выдумку. Но это слово имеет и более глубокое значение. Оно также обозначает рассказ [религиозного значения], объясняющий устройство мира и отношение к ней [место в ней] человечества. Менеджеры склонны забывать чему они научились будучи программистами и верить в определенные мифы. Будет так же грубо и безуспешно пытаться убедить их, что эти мифы ложны, как попытаться разуверить глубоко религиозного человека в его вере. Поэтому, вы должны распознать эти мифы: Больше документирования всегда лучше. (Они требуют ее и, при этом, хотят, чтобы вы не тратили на нее свое время). Программисты взаимозаменяемы. (Программисты могут отличаться по производительности на порядок). Для ускорения дохлого проекта можно добавить ресурсов. (Дополнительные затраты на взаимодействие с новыми людьми почти всегда приносят больше вреда, чем пользы). Время разработки можно достоверно оценить. (Это даже теоретически невозможно). Производительность программистов можно измерить с помощью некоторой простой метрики, например, количества строк кода. (Если сила в краткости, то количество строк -- это плохо). Если появляется возможность, можно попытаться объяснить эти вещи. Но не расстраивайтесь, если не получится, и не нужно портить свою репутацию, агрессивно воюя с этими мифами. Каждый из этих мифов укрепляет менеджеров в идее, что они действительно могут управлять процессом. Правда в том, что хорошие менеджеры помогают, а плохие -- мешают. Как [быть] с Организационным Хаосом Иногда случаются периоды времени, когда в компании наступает полный бардак, например, сокращения, поглощения, [ipos -- initial public offer?], увольнения, расширения и т.д. Они выбивают из колеи всех, хотя, возможно, программисты подвержены этому чуть меньше, поскольку их самооценка больше основана на компетентности, чем должности. Организационный бардак -- это отличная возможность для программистов продемонстрировать свои способности. Я оставил это на закуску, потому что это большой программерский секрет. Не читайте дальше, если вы не программер. Инженеры наделены силой создавать и поддерживать. Неинженеры могут помыкать людьми, но, в обычной софтверной компании, не могут создать ничего без инженеров, также как и инженеры обычно не могут продавать продукт и эффективно управлять бизнесом. Эта сила является средством от почти всех проблем, связанных с временным организационным беспорядком. Столкнувшись с ним, забейте на него полностью и продолжайте как ни в чем не бывало. Вас, конечно, могут уволить, но, даже если это случится, вы, вероятнее всего, найдете новую работу, благодаря этой своей силе. Чаще всего, какой-нибудь измученный (утомленный) человек, не имеющий этой силы, придет к вам и будет заставлять вас сделать какую-нибудь глупость. Если вы действительно уверены, что это глупость, лучше всего улыбаться и кивать, пока он не уйдет, а самому продолжать делать то, что лучше, на ваш взгляд, для компании. Если вы руководитель, попросите подчиненных делать то же самое, и не обращать внимания на то, что говорят другие. Такой план действий является наилучшим для вас лично, и наилучшим для компании или проекта. Глоссарий Здесь собраны термины, использованные в этой статье. Они не обязательно имеют общепринятое значение. Эрик С. Реймонд (Eric S. Raymond) составил огромный и содержательный глоссарий[HackerDict], который можно к собственному изумлению с удовольствием прочесть от корки до корки, начав с какого-нибудь фрагмента. хз-хз (unk-unk) Жаргонное выражение, обозначающее "неизвестную неизвестность". Проблемы, которые в настоящее время не удается даже концептуализировать. Они лишь крадут проектное время и ломают график. шеф (boss) Человек или организация, который или которая ставит перед вами задачи. В некоторых случаях это вся нация целиком. вставка printlin’ов (printlining) Вставка в программу строго на временной основе инструкций, которые выводят информацию о ходе выполнения программы в отладочных целях. журналирование (logging) Методика написания программ, в соответствии с которой они могут порождать настраиваемый журнал, описывающий ход их выполнения. разделяй и властвуй (divide and conquer) Техника проектирования и, что еще более важно, отладки сверху вниз, которая состоит в последовательном разделении задачи или головоломки на меньшие по размеру задачи или головоломки. пустышка (vapor) Иллюзорные и зачастую мошеннические обещания программного обеспечения, которого еще нет в продаже, и которое скорее всего никогда и не материализуется во что-нибудь осязаемое. шеф (boss) Человек, который ставит перед вами задачи. В некоторых случаях в роли шефа выступает пользователь. команда (tribe) Люди, которые разделяют с вами верность общей цели. низко висящий фрукт (low-hanging fruit) Большие улучшения, которые обходятся дешево. Заказчик (Entrepreneur) Инициатор проектов. мусор (garbage) Объекты, которые больше не нужны, но загромождают память. бизнес (business) Группа людей, которые организованно делают деньги. компания (company) Группа людей, которые организованно делают деньги. команда (tribe) Группа людей, которых объединяет с вами взаимная верность и культурное сходство. поисковая слепота (scroll blindness) Эффект, в силу которого невозможно найти необходимую информацию, которая погребена под завалами другой, менее интересной информации. по настенным часам (wall-clock) Реальное время, которое показывают часы на стене, в отличие от процессорного времени. узкое место (bottleneck) Аспект, сильнее всего ограничивающий производительность системы. Фактор, который определяет предел производительности. мастер-копия (master) Уникальный информационный фрагмент, из которого порождаются все кэшируемые копии, и который выступает в качестве официального определения этих данных. выделено в куче Про память можно всегда сказать, что она выделена в куче, если механизм ее освобождения достаточно сложен. мусор (garbage) Выделенная память, которая больше не имеет никакого полезного смысла. сборщик мусора (garbage collector) Система утилизации мусора. утечка памяти (memory leak) Появление ненужных ссылок на объекты, которые мешает сборке мусора (или ошибка в сборщике мусора либо системе управления памятью!), в результате которого память, необходимая программе, со временем последовательно увеличивается. Экстремальное программирование (Extreme Programming) Стиль программирования, при котором особое значение придается общению с заказчиком и автоматизированному тестированию. упереться в стену (hitting the wall) Исчерпать определенный ресурс, в результате чего производительность падает резко, а не постепенно. программирование впрок (speculative programming) Создание функции прежде, чем станет ясно, что она действительно будет полезна. сокрытие информации (information hiding) Принцип разработки, который поощряет изолированность объектов и отсутствие зависимостей между ними за счет использования интерфейсов, предоставляющих как можно меньше информации. объектно-ориентированное программирование (object-oriented programming) Стиль программирования, при котором особое значение придается управлению состоянием внутри объектов. языки описания (communication languages) Язык, предназначенный в первую очередь для стандартизации, а не выполнения. рамки и стрелки (boxes and arrows) Свободный, неформальный стиль составления диаграмм, состоящих из рамок, соединенных стрелками для отображения взаимосвязей. Это контрастирует с формальными методиками создания диаграмм, такими как UML. lingua franca Язык, который популярен настолько, что стал уже стандартом de facto в своей области, как французский одно время был языком международной дипломатии. купить или разработать (buy vs. build) Описывает дилемму: потратить ли деньги на программное обеспечение или разработать его самостоятельно. простая работа Работа, которая почти не требует творчества и не влечет за собой почти никакого риска. Простую работу легко оценить. программная нотация Синоним понятия "язык программирования", подчеркивающий математическую природу языков программирования и их простоту в сравнении с естественными языками. солома (strawman) Документ, служащий отправной точкой в технической дискуссии. Солома может превратиться в хворост, жесть, дерево, железо и т. д. технический документ (wite-paper) Информативный документ, задача которого – объяснить или продать продукт или идею аудитории, отличной от программистов, авторов этого продукта или идеи. Содержание Библиография и вебсайтография Библиография и вебсайтография Книги [Rules00] Guy Kawasaki, Michelle Moreno, and Gary Kawasaki. 2000. HarperBusiness. Rules for Revolutionaries: The Capitalist Manifesto for Creating and Marketing New Products and Services. [RDev96] Steve McConnell. 1996. Microsoft Press. Redmond, Wash. Rapid Development: Taming Wild Software Schedules. [CodeC93] Steve McConnell. 1993. Microsoft Press. Redmond, Wash. Code Complete. [XP99] Kent Beck. 1999. 0201616416. Addison-Wesley. Extreme Programming Explained: Embrace Change. [PlanXP00] Kent Beck and Martin Fowler. 2000. 0201710919. Addison-Wesley. Planning Extreme Programming. [Prag99] Andrew Hunt, David Thomas, and Ward Cunningham. 1999. 020161622X. Addison-Wesley. The Pragmatic Programmer: From Journeyman to Master. [Stronger] Friedrich Nietzsche. 1889. Twilight of the Idols, "Maxims and Arrows", раздел 8. Веб сайты [PGSite] Paul Graham. 2002. Статьи на его веб-сайте: http://www.paulgraham.com/articles.html. Все статьи, но особенно "Beating the Averages". [Hacker] Eric S. Raymond. 2003. How to Become a Hacker. http://www.catb.org/~esr/faqs/hacker-howto.html. [HackDict] Eric S. Raymond. 2003. The New Hacker Dictionary. http://catb.org/esr/jargon/jargon.html. [ExpCS] Edsger W. Dijkstra. 1986. How Experimental is Computing Science?. http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF. [Knife] Edsger W. Dijkstra. 1984. On a Cultural Gap. http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF . Приложение Б. История (на февраль 2003 г.) Отклики и дополнения Присылайте мне любые комментарии по поводу этой статьи. Я рассматриваю все предложения, многие из которых уже позволили улучшить статью. Статья размещена в рамках лицензии GNU Free Documentation License. Эта лицензия не предназначена специально для статей. Предполагается, что статья – это связный и убедительный набор доводов, изложенный в письменном виде с одной точки зрения и от одного лица. Надеюсь, что эта статья коротка и приятна для чтения. Надеюсь также, что она поучительна. Хотя это и не учебник, она разбита на множество небольших разделов, к которым легко добавить новые. Если у вас возникнет желание, можете смело дополнять эту статью так, как считаете нужным, в соответствии с условиями Лицензии. Может быть, и несколько самонадеянно полагать, что этот документ достоин дополнений. Но надежда умирает последней. Я был бы рад, если бы эти дополнения коснулись следующего: Добавление исчерпывающего списка литературы к каждому разделу Добавление новых и более качественных разделов Перевод на другие языки, хотя бы отдельными подразделами Комментарии или критические замечания, встроенные в текст Возможность создания файлов других форматов, таких как форматы Palm и HTML более высокого качества Если вы сообщите мне о своей работе, я рассмотрю возможностью включения ее в следующие версии в соответствии с условиями Лицензии. Разумеется, вы можете создавать собственные версии этого документа без моего ведома, как разъяснено в Лицензии. Спасибо. Роберт Л. Рид Оригинальная версия Оригинальная версия этого документа была начата Робертом Л. Ридом в 2000 г. и впервые опубликована в электронном виде на сайте Samizdat Press (http://Samizdat.mines.edu) в 2002 г. Она посвящается программистам компании Hire.com. После того, как статья была упомянута в Slashdot в 2003 г., около 75 человек прислали мне электронные письма с предложениями и сообщениями об опечатках. Я благодарен им всем. Было много дубликатов, но следующие люди либо сделали наиболее значимые предложения, либо первые обнаружили ошибку, которую я впоследствии исправил: Morgan McGuire, David Mason, Tom Moertel, Ninja Programmer (145252) из Slashdot, Ben Vierck, Rob Hafernik, Mark Howe, Pieter Pareit, Brian Grayson, Zed A. Shaw, Steve Benz, Maksim Ioffe, Andrew Wu, David Jeschke и Tom Corcoran. Наконец, хотелось бы поблагодарить Christina Vallery, чья редакция и корректура значительно улучшила второй черновик, а также Wayne Allen, который побудил меня начать эту работу. Биография автора оригинальной версии Роберт Л. Рид живет в Остине, Техас, со своей женой и двумя детьми. В настоящее время он является главным инженером компании Hire.com, в которой проработал четыре года. До этого он был основателем компании 4R Technology, которая производила инструмент для контроля качества с помощью анализа сканированных изображений для нужд бумажной промышленности. Роб получил степень доктора философии в Техасском университете в Остине в 1995 г. по специальности "Вычислительная техника" в области теории баз данных. В 1987 г. он получил степень бакалавра гуманитарных наук по специальности "Вычислительная техника" в университете Райса. Работает программистом с 16 лет. Приложение В. Лицензия GNU Free Documentation License Версия 1.2, ноябрь 2002 г. Содержание ПРЕАМБУЛА СФЕРА ПРИМЕНЕНИЯ И ОСНОВНЫЕ ОПРЕДЕЛЕНИЯ ДОСЛОВНОЕ КОПИРОВАНИЕ ТИРАЖИРОВАНИЕ ИЗМЕНЕНИЯ ОБЪЕДИНЕНИЕ ДОКУМЕНТОВ СОБРАНИЕ ДОКУМЕНТОВ ОБЪЕДИНЕНИЕ С НЕЗАВИСИМЫМИ РАБОТАМИ ПЕРЕВОД ЗАКЛЮЧЕНИЕ ПОСЛЕДУЮЩИЕ ИЗМЕНЕНИЯ ДАННОЙ ЛИЦЕНЗИИ ПРИЛОЖЕНИЕ: Как использовать эту лицензию для ваших документов Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Этот документ можно копировать, а также распространять его дословные копии, однако вносить в него изменения запрещено. Примечание. Это неофициальный русский перевод. Он не был опубликован Фондом Свободного ПО, не устанавливает законные условия распространения ПО и приведен только для справки. ПРЕАМБУЛА Целью настоящей Лицензии является создание "свободных" руководств, учебников и других функциональных и полезных документов. Под свободой понимается право пользователя копировать и распространять эти документы в оригинальной или модифицированной форме на коммерческой или некоммерческой основе. Кроме того, Лицензия сохраняет за автором и издателем право получить должную оценку их работы, не неся в то же время ответственность за изменения, произведенные другими. Лицензия является разновидностью "copyleft", то есть документы, производные от этого, должны быть свободными в том же самом смысле. Данная Лицензия дополняет copyleft-лицензию GNU General Public License, разработанную для свободного ПО. Лицензия предназначена для руководств по свободному ПО, поскольку свободное ПО нуждается в свободной документации: свободная программа должна поставляться с руководствами, имеющими ту же степень свободы, что и сама программа. Однако, Лицензия не ограничена руководствами по программному обеспечению. Ее можно использовать для любых текстовых материалов независимо от их темы, а также от того, были ли они опубликованы в печатной форме. Рекомендуется использовать Лицензию главным образом для работ обучающего и справочного характера. СФЕРА ПРИМЕНЕНИЯ И ОСНОВНЫЕ ОПРЕДЕЛЕНИЯ Лицензия применима для любого руководства или другого текста на любом носителе, который содержит указание владельца авторских прав на то, что текст может распространяться в соответствии с условиями Лицензии. Такое указание предоставляет право использования данного текста по всему миру, безвозмездно, в течение неограниченного времени в соответствии с приведенными здесь условиями. Далее, "Документ" обозначает такое руководство или текст. Лицензиатом (далее "Вы") является любой читатель. Вы принимаете условия Лицензии, если копируете, модифицируете или распространяете данный текст способом, который в соответствии с законами об авторских правах требует разрешения. "Модифицированная версия" Документа – это любой текст, содержащий Документ или его часть в дословном виде, с изменениями и/или в переводе на другой язык. "Дополнительный раздел" – это именованное приложение или предисловие к Документу, которое описывает исключительно отношение авторов или издателей Документа к общей теме Документа (или другим предметам, касающимся ее) и не содержит ничего, непосредственно связанного с общей темой. (Так, если Документ является частью учебника математики, Дополнительный раздел не может излагать математические вопросы.) Упомянутое отношение может представлять собой историческую взаимосвязь с темой или предметами, касающимися ее, а также юридическими, коммерческими, философскими, этическими или политическими положениями. "Неизменяемые разделы" – это определенные Дополнительные разделы, которые отмечены как неизменяемые в примечании, в котором говорится, что Документ распространяется в соответствии с условиями данной Лицензии. Если раздел не удовлетворяет приведенному выше определению Дополнительного раздела, он не может быть отмечен как Неизменяемый. Документ может не содержать Неизменяемых разделов. Если Документ не определяет явно Неизменяемые разделы, то их в нем нет. "Текст на Обложке" - некий короткий отрывок текста, который помещён на Лицевой или задней обложке, уведомляющий что Документ выпущен на условиях этой лицензии. Текст на лицевой обложке может быть не более 5 слов, а на задней обложке не более 25 ["Прозрачная"?] копия Документа - это машиночитаемая копия, представленая в формате, спецификация которого доступна широкой публике и подходит для редактирования в обычных текстовых редакторах или (для изображений в пикселях) в обычных графических программах или (для рисования) в графическом редакторе, находящимся в широком доступе, и подходит для ввода в программы форматирования текстов или для автоматического перевода в многочисленные форматы, подходящие для ввода в программы форматирования текстов. В ином случае, копия созданая в [Прозрачном] формате, чья разметка или отсутствие разметки, мешает или препятствует внесению последующих изменений читателями, не является [Прозрачной]. Формат изображения не является Прозрачным если используется для отображения любого количества текста. Копия не являющаяся ["Прозрачной"] называется "Непрозрачной" Примеры подходящих форматов для [Прозрачных] копий, влючают простой текст в формате ASCII без разметки, формат ввода Texinfo, LaTeX, SGML или XML использующие общедоступные DTD, и утверждённые стандарты базового HTML, PostScript или PDF, предназначенные для изменения человеком. Примеры форматов прозрачных изображений включают: PNG, XCF и JPG. Непрозрачные форматы включают проприетарные форматы, которые могут быть считаны или отредактированы только проприетарными текстовыми процессорами, SGML или XML для которых DTD и/или инструменты обработки отсутствуют в широком доступе, а также машиногенерированый HTML, PostScript или PDF, выполненный некоторыми текстовыми процессорами только для [отображения]. "Титульной Страничкой" для печатной книги, является сама титульная страничка плюс последующие странички с четким описанием материала, который по условиям Лицензии должен присутствовать на титульной страничке. Для работ в форматах, которые не подразумевают её наличие, "Титульной Страничкой" является текст возле названия работы, предшествующий началу тела работы Раздел "XYZ [ЭЮЯ]" означает именованую подгруппу Документа, чьё название или точно XYZ, или содержит XYZ, далее в скобках перевод XYZ на другой язык. (Здесь XYZ обозначает определённое название секции упомянутые ниже, такие как: "Acknowledgements" ["Благодарность"], "Dedications" ["Посвящение"], "Endorsements" ["Утверждение?"], "History" ["История"].) "Сохранить Название" раздела, который вы модифицируете означает, что согласно этому определению он останется разделом "XYZ" Документ может включать Гарантийные Правовые оговорки совместно с уведомлением о том, что эта Лицензия относится к Документу. Эти Гарантийные Правовые оговорки, как и полагается, включены с ссылкой на эту Лицензию, но только, что касается отказа от гарантий: любое другое значение, которое могут иметь эти Гарантийные Правовые оговорки, недействительно и не имеет никакого эффекта на значение этой Лицензии. ДОСЛОВНОЕ КОПИРОВАНИЕ Вы можете копировать и распространять Документы на любом носителе на платной или бесплатной основе при условии, что эта лицензия, уведомление об авторском праве и уведомления о лицензии гласят о том, что лицензия относящаяся к Документу воспроизведена на всех копиях, и что вы не добавляли никаких дополнительных условий к настоящим условиям Лицензии. Вы не можете использовать технические приёмы для того, чтобы затруднить или контролировать чтение или дальнейшее копирование распространяемых вами материалов. Однако, вы можете получать вознаграждение в обмен на копию. Если вы распространяете достаточно большое количество копий, вы также должны следовать условиям из 3 раздела Вы также можете предоставлять копии, на тех же вышеизложенных условиях, и публично демонстрировать копии. ТИРАЖИРОВАНИЕ Если вы издаёте печатные копии (или копии на носителях, которые имеют отпечатанные обложки) Документа, в количестве превыщающем 100 экземпляров, и лицензия Документа требует наличие Текста для Обложки, вы должны приложить копии, которые ясно и чётко передают все Тексты на обложку: Текст для Лицевой Обложки на лицевой стороне, и соответственно Текст для Задней Обложки на обратной стороне. Обе обложки также должны чётко и ясно указывать, что вы являетесь издателем этих копий. Лицевая обложка должна отображать полное название работы дословно, всё должно быть видимо и иметь одинаковый рельеф. Вы можете добавлять другой материал на обложку. Копирование с изменениями ограничено обложкой, и до тех пор пока сохраняется название Документа, и удовлетворяются условия, может считаться [дословным] копированием в остальных случаях. Если необходимый текст для обложки слишком большой чтобы разместиться на ней, вам необходимо разместить начало текста (в разумных пределах) на текущей а продолжение текста, разместить на смежных страничках. Если вы издаёте или распространяете "Непрозрачные" копии Документа в количестве более 100 экземпляров, то вы должны либо предоставить машиночитаемую [Прозрачную] копию вместе с каждой "Непрозрачной" копией, либо в каждой Непрозрачной копии указать общедоступное сетевое расположение, откуда пользователи, используя открытые сетевые протоколы, могут скачать полную [Прозрачную] копию Документа, без добавочного материала. В последнем случае, до начала тиражирования Непрозрачных копий, вы должны предпринять разумные шаги чтобы убедиться, что данная [Прозрачная] копия останется доступной в указанном месте поистечении как минимум года с момента выхода в свет последней Непрозрачной копии данной версии (распространяемой непосредственно вами, вашими агентами или розничными продавцами). Желательно, но не обязательно связываться с авторами Документа перед повторным распространением большого количества копий, для получения его обновлённой версии. ВНЕСЕНИЕ ИЗМЕНЕНИЙ Вы можете копировать и распространять Изменённую Версию Документа на условиях, указанных выше в разделах 2 и 3, предусматривающих, что Изменённая версия, выпущенная вами, в точности соответствует данной Лицензии, с Изменённой Версией в качестве Документа, таким образом лицензируя распространение и модификацию Измененной Версии обладателем этой копии. Дополнительно для Изменённой версии вы должны выполнить следущее: На Титульном Листе (и на обложках, если таковые имеются) используйте заглавие, отличное заглавия Документа, и его предыдущих версий (которые должены быть перечислены в секции History [Истории] данного Документа, если таковые имеются) Вы можете использовать название предыдущей версии, если оригинальный издатель той версии дает разрешение на это. Перечислите авторов, одного или более человек или юридических лиц, ответственных за модификации в Изменённой Версии на Титульном листе, вместе с по крайней мере пятью основными авторами Документа (или со всеми основными авторами, если их менее пяти человек), если они не освобождят Вас из этого требования. Разместите на Титульной страничке Изменённой версии своё имя в качестве издателя. Сохраните все уведомления об авторском праве Документа. Добавьте соответствующее уведомление об авторском праве для своих модификаций, рядом с другими уведомлениями об авторском праве. Включите, сразу же после уведомлений об авторском праве, уведомления о лицензии, дающее разрешение на публичное использование Измененной Версии в соответствии с этой Лицензией, в форме, показанной в Приложении ниже. Сохраните в данной лицензии полный перечень НеИзменяемых разделов и необходимого Текста на обложку, указанных в лицензии Документа. Включите неизменную копию этой Лицензии. Сохраните раздел под названием "History" ["История"], сохраните его Заглавие, и добавьте в него пункт, содержащий как минимум название, год, новых авторов и издателя Изменённой версии, как на Титульной Странице. Если раздела под названием "History" ["История"] не существует в Документе, создайте его, начиная с указания заглавия, года, авторов и издателя Документа как указано на Титульной Страничке, затем добавьте пункт описывающий Изменённую Версию как указано в предыдущем предложении. Сохраните сетевое расположение, указанное в Документе, для общего доступа к [Прозрачной] копии Документа, а также сетевое расположение для Документов, предыдущих версий, на которых Документ был основан, если таковые имеются. Всё это может располагаться в секции "History" ["История"]. Вы можете не включать сетевое расположение для работ, опубликованых как минимум четырмя годами ранее данного Документа, или если издатель дал разрешение на это. Для любого раздела с названием "Благодарности" или "Посвящения", сохраните Название раздела, и постарайтесь сохранить в них стиль и смысл всех благодарностей и/или посвящений. Сохраните все НеИзменяемые Разделы Документа, неизменные ни в тексте, ни в названиях. Номера разделов или их эквиваленты не считаются частью названия разделов. Удалите все разделы с названием "Endorsements". Так как подобные разделы не могут быть включены в Измененную Версию. Не переименовывайте существующие разделы в раздел под названием "Endorsments" или любой другой НеИзменяемый раздел с конфликтующим названием. Сохраните любые Гарантийные Правовые оговорки. Если Измененная Версия включает новые разделы вступительной части или если дополнения, определены как Вторичные Разделы и не содержат материала, скопированного с Документа, некоторые или все разделы, по Вашему выбору, вы можете определить как НеИзменяемые. Чтобы сделать это, добавьте их названия в список НеИзменяемых Разделов в лицензионном уведомлении Измененной Версии. Эти названия должны отличаться от любых других названий разделов. Вы можете добавить раздел под названием ["Одобрения"], если он содержит только одобрения различными сторонами вашей Измененной Версии - например, утверждения экспертной оценки или одобрение организацией, что текст был признан авторитетным и соответствует стандартам. Вы можете добавить фрагмент до 5 слов в качестве Текста на Лицевой обложке и до 25 слов слов в качестве Текста на Обратную обложку в конце Текста на Обложку в Изменённой версии. Только один фрагмент текста может быть добавлен (или изменён) юридическим лицом. Если документ уже содержит текст на обложку, который предварительно добавлен вами, для той же обложки, или изменена тем же юридическим лицом, от имени которого вы действуете, то вы не можете добавлять его; но вы можете заменить старый текст, при явном разрешении предыдущего издателя который добавил его. Данной Лицензией автор(ы) и издатель(и) Документа не дают прав общественности на использование их имён для Изменённых Версий Докуметов, утверждая или подразумевая их согласие. ОБЪЕДИНЕНИЕ ДОКУМЕНТОВ Вы можете объеденить Документ с другими документами выпущенными на условиях этой лицензии, и условиями для изменённых версий, приведёнными выше в разделе 4, которые предусматривают включение в комбинации со всеми НеИзменяемыми Разделами, всех оригинальных документов без изменений, и перечисление их всех в качестве НеИзменяемых Разделов в соответствующих лицензионных уведомлениях, а так же сохранение всех Гарантийных Правовых оговорок. Совместная работа должна содержать только одну копию этой Лицензии, и многократные идентичные НеИзменяемые Разделы могут быть заменены единственной копией. Если существует много НеИзменяемых разделов с одинаковым названием, но различным содержанием, сделайте название каждого такого раздела уникальным, добавляя в конце в скобках имя оригинального автора или издателя этого раздела если он известен; так же можно установить уникальный номер. Подкорректируйте названия разделов в списке НеИзменяемых Разделов в лицензионном уведомлении совместной работы. Совместно вы должны объединить любые разделы под названием "История" в различных оригиналах документа, формируя один раздел под названием "История"; аналогично объедините все разделы под названиями "Благодарности" и "Посвящения". Вы должны удалить все разделы под названием "Одобрения". СОБРАНИЕ ДОКУМЕНТОВ Вы можете собрать коллекцию, состоящую из Документа и других документов созданных согласно этой Лицензии, и заменить отдельные копии этой Лицензии на одну единственную, которая включена в коллекцию, при условии, что Вы следуете правилам этой Лицензии для [дословного] копирования каждого документа во всех отношениях. Вы можете извлечь единственный документ из этой коллекции, и распространять его индивидуально согласно условиям этой Лицензии, которая подразумевает необходимость включения копии этой Лицензии в этот документ, и следование условиям Лицензии во всех отношениях относительно [дословного] копирования этого документа. ОБЪЕДИНЕНИЕ С НЕЗАВИСИМЫМИ РАБОТАМИ Объединение Документа или его производных с другими раздельными и независимыми документами или работами в хранилище информации или на распространяемом носителе, называется "aggregate" [совокупность] если авторское право в результате объединения не используется для ограничиния законных прав пользователей, не участвовавших в этом. Когда Документ включен в [совокупность], эта Лицензия перестаёт относится к другим работам в совокупности, которые не являются самостоятельными, а производными работами Документа. Если требование к Тексту для Обложки из раздела 3 применимо к этим копиям Документа, тогда, если Документ занимает менее половины всей совокупности, то Текст для Обложки Документа может быть помещён на обложку наряду с Документом из совокупности, или на электронный эквивалент обложки, если Документ существует в электронной форме. Иначе он должен быть помещён на отпечатаных обложах, наряду со всей совокупностью ПЕРЕВОД Перевод это своего рода модификация, таким образом Вы можете распространять переводы Документа в соответствии с разделом 4. Замена НеИзменяемых Разделов переводами требует специального разрешения от обладателей авторского права, но Вы можете включать переводы некоторых или всех НеИзменяемых Разделов в дополнение к оригинальным версиям этих разделов. Вы можете включать перевод этой Лицензии, и всех лицензионных уведомлений в Документ, и любых Гарантийных Правовых оговорках, при условии, что Вы также включаете оригинальную английскую версию этой Лицензии и оригинальные версии тех уведомлений и правовых оговорок. В случае разногласия между переводом и оригинальной версией этой Лицензии или правовой оговорки, будет преобладать оригинальная версия. Если раздел в Документе Назван "Благодарности", "Посвящения", или "История", то требование (раздел 4), Сохранить его Название (раздел 1) обычно требует изменения фактического названия. ЗАКЛЮЧЕНИЕ Вы не можете копировать, изменять, сублицензировать, или распространять Документ на условиях отличных от явно предусмотреных этой Лицензией. Любая другая попытка скопировать, изменить, сублицензировать или распространять Документ, недействительна, и автоматически ограничивается Вашими правами согласно этой Лицензии. Однако, стороны, получившие копии, или права от Вас, согласно этой Лицензии не будут ограничиваться их лицензией, до тех пор пока стороны действуют в полном соответствии с ней. ПОСЛЕДУЮЩИЕ ИЗМЕНЕНИЯ ДАННОЙ ЛИЦЕНЗИИ Время от времени Free Software Foundation [Фонд свободного программного обеспечения] может опубликовать новые, пересмотренные версии Лицензии GNU Free Documentation License. Новые версии будут похожи по духу текущей версии, но могут отличаться в деталях, что является реакцией на новые проблемы и нужды. См. http://www.gnu.org/copyleft/. Каждая версия Лицензии имеет отличительный номер. Если Документ устанавливает определённый номер Лицензии "или любой другой более поздней версии", относящейся к нему, у вас Есть возможность следовать условиям соглашения либо указанной версии, либо любой другой более поздней версии, которая была опубликована (не черновик) Free Software Foundation. Если Документ не устанавливает какого-либо номера версии Лицензии, вы можете выбрать любую, когда либо опубликованую (не черновик) Free Software Foundation. ПРИЛОЖЕНИЕ: Как использовать эту лицензию для своих документов. Чтобы использовать эту Лицензию в документе, написанным вами, включите копию Лицензии в документ и добавьте следующий копирайт и лицензионные уведомления сразу после титульной страницы: Copyright (c) ГОД ВАШЕ ИМЯ. Разрешено копирование, распространение и/или изменение этого документа на условиях лицензии GNU Free Documentation License, версии 1.2 или любой другой более поздней версии издаваемой Free Software Foundation; без НеИзменяемых Разделов, без текста на лицевой и задней обложках. Копия лицензии включена в разделе озаглавленном "GNU Free Documentation License". Если у вас имеются НеИзменяемые Разделы, текст на лицевой и задней обложках, замените [это] следующим: с НеИзменяемыми Разделами ПЕРЕЧЕНЬ ИХ НАЗВАНИЙ, с лицевой обложкой ТЕКСТ, и задней обложкой ТЕКСТ. Если у вас имеется НеИзменяемые Разделы без Текста на обложках или какие-либо другие комбинации из этих трёх вариантов, объедените оставшиеся два, чтобы они соответствовали требованиям Если ваш документ содержит нетривиальные примеры программного кода, мы рекомендуем реализовать их по лицензии свободного программного обеспечения, согласно вашему выбору, к примеру GNU General Public License, чтобы разрешить его использование в свободном программном обеспечении. Послесловие Данная работа лицензирована GNU Free Documentation License. Изначально была написана в LaTeX, а зетем была перенесена в DocBook. Доступна как [прозрачная] копия в формате DocBook/XML. Build система и специальные инструкции по обработке являются частью пакета [прозрачной] копии, хотя процесс сборки из исходников зависит от системы. Исходники могут быть собраны или в формате HTML, или в PDF, и перенос в другие форматы возможен и поддерживается. Исходная версия этого документа написана Робертом Л. Ридом безвозмездно и посвящается программистам компании Hire.com ------------------------------------------------------------------------------- http://translated.by/you/how-to-be-a-programmer-a-short-comprehensive-and-personal-summary-1/into-ru/trans/ © Copyright © 2002, 2003 Original (English): How-to-be a Programmer: A Short, Comprehensive, and Personal Summary (http://samizdat.mines.edu/howto/HowToBeAProgrammer.html) Translation: © kaiko, homa, timzes, xgsa, grigsoft, Der, aidsfrag, a-t-a-r-i, suvit, O90, Артём Бисярин, meowth, maxischenko, Андрей Дягель, Владимир, Александр, takas, Gazelle, tilarids, k0sh, Ann, Андрей Колесник, actual, Ануфриев Дмитрий, kambei, Алексей, hooey, iasniisocol, TarzanASG, Илья, RANUX, birkoff-a, XPEH, mors, santadambri, Руслан Гроховецкий, steelrat, serkoff. License: GNU 1.2 translated.by crowd