Общие советы

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

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

Или, может быть, он просто повеселился от души. Картостроители не имеют общего культурного контекста, из которого можно добывать знания, поэтому мы почти все самообученные. Здесь мы собрали некоторые наблюдения, полученные в беседах с картостроителями. Разговаривая с другими картостроителями, мы можем узнать очень многое о картостроении.

 

Трясти надо

 

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

 

Изменения: последовательные или катастрофические?

 

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

 

Границы

 

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

 

Исследуйте перестановки

 

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

 

Поработайте в обратном направлении

 

Мы все знаем, как найти выход из лабиринта, нарисованного в детской книжке, не правда ли!

 

Верчение тарелок

 

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

 

Расслабляйтесь

 

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

 

Рвите порочные круги

 

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

 

Сбрасывай в "файл подкачки"

 

Есть виды глупости, к которым имеют доступ только картостроители. Картостроитель может быть парализован при попытках оптимизировать последовательность, которая слишком велика, чтобы поместиться в его голове. Вероятно, он хочет понести свадебный торт до того, как установит запасное колесо на машину, чтобы руки были чистыми, но запасное колесо здесь, а торт у Фреда. Когда такое случается с современными операционными системами со страничной организацией памяти, они освобождаются от ненужных страниц - переходят к стратегии подкачки страниц (swap). Они просто сбрасывают в файл подкачки целые процессы, пока не освободится нужный объем памяти, а затем возвращаются к размещению страниц. Не дай себя парализовать -- просто выполняй какую-то работу, а затем снова посмотри на проблему.

 

Упражнение с одеялом

 

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

 

Картостроение и Процесс

 

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

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

 

Ангелы, драконы и философский камень

 

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

Бесконечность была горячей темой, и наши предки разбили это понятие на три вида. Концептуальная бесконечность проста -- ты просто говоришь "навсегда" и получаешь ее там, где это нужно. Еще есть потенциальная бесконечность. Ты можешь дать кому-нибудь указание типа "Считай непрерывно". Теоретически, в результате можно получить бесконечную последовательность чисел, но произойдет ли это на самом деле? Можешь ли ты на самом деле сделать так, чтобы перед тобой оказалось бесконечное число вещей, чтобы проделывать с ними удивительные фокусы? Они пришли к выводу, что если бы коллекция из бесконечного числа чего-нибудь, начиная с капусты и кончая королями, существовала на самом деле, то она заняла бы бесконечный объем, поэтому если бы существовала какая-нибудь бесконечная коллекция каких-нибудь вещей любого размера, то нас здесь попросту бы не было. Не было бы ничего, кроме кочанов капусты -- повсюду. Мы здесь, поэтому бесконечной коллекции чего-нибудь любого конечного размера не существует -- нигде. Но по-прежнему остается возможность бесконечной коллекции чего-нибудь бесконечно малого. Если что-то может быть бесконечно малым, то Бог (тот, кого удобно иметь под рукой в мысленных экспериментах, поскольку он способен сделать все, что может быть сделано в этом мире) смог бы заставить танцевать на кончике иглы бесконечное число ангелов. Наши предки почувствовали, что эта идея смешна, и, таким образом, в этом мире не существует настоящей бесконечности. Сегодня у нас есть две великие физические теории. Одна работает при больших масштабах и использует гладкие кривые для описания пространства. Другая работает в микромире и использует ступеньки (квантование). Нам еще не удалось объединить эти теории вместе, поэтому мы не знаем, использует ли лежащая в основе их обеих более общая теория ступеньки для построения кривых (как фотография в газете), либо она использует кривые для построения ступенек (как ковер на лестнице). Это может быть нечто, что мы еще не можем представить, но если бы пришлось выбирать из этих двух, наши предки выбрали бы ступеньки, из-за ангелов на кончике булавки.

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

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

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

Убедитесь, что у вас есть реалистичное представление о собственных способностях. Обычно требуется его подкорректировать! Достижение успехов в чем-то требует практики, но учитывая, что вы в любом случае будете выполнять работу, хорошо бы знать, чего можно достичь.

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

 

Литературная критика и паттерны проектирования

 

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

Чтобы окончательно прояснить эту позицию, рассмотрим язык ассемблера. Код операции (opcode) может выполнять большинство специфических установок выходов процессора по заданным входным значениям, но мы рассматриваем код операции посредством его мнемоники, например DAA (Десятичная Коррекция Аккумулятора -- Decimal Adjust Accumulator). Даже когда есть взаимное соответствие между кодом операции и мнемоникой, более высокий уровень абстракции мнемоники может скрывать действие кода операции на аккумулятор, который просто преобразует биты в соответствии с алгоритмом. Если мы видим возможности обработки, предоставляемые кодом операции, можем ли мы "злоупотреблять" этим? Ответ зависит от обстоятельств.

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

Мы можем получить строгую и элегантную дисциплину из различия между намерением и действием. Рассмотрим следующий фрагмент:

//Search the list of available dealers and find those that
// handle the triggering stock. Send them notification of
// the event.

for(DealerIterator DI(DealersOnline); DI.more(); DI++)
if(DI.CurrentDealer()->InPortfolio(TheEvent.GetStock()))
DI.CurrentDealer()->HandleEvent(TheEvent);

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

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

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

Эта концепция развита далее в идее Дональда Кнута (Donald Knuth) о "грамотном программировании" (Literate Programming), которое, чтобы его сделать хорошо, требует средств системной поддержки, типа его Сетевой среды (Web environment) -- прообраза WWW (World Wide Web). Но вам не нужно скупать все гири, чтобы получить удовольствие от спорта. Грамотное программирование -- это скорее отношение (позиция), а не инструмент.

На этом уровне литературной критики мы можем получить серьезные выгоды от изучения паттернов проектирования (design patterns). Это компоненты архитектурной технологии, которая гораздо сложнее, чем обычный поток управления (flow control) с обработкой ошибок и другими типичными идиомами. Они чрезвычайно мощные и платформонезависимые. Почитайте прекрасную книгу Гаммы, Хелма, Джонсона и Влиссидеса (Gamma, Helm, Johnson, Vlissides), в которой они описывают паттерн как нечто, что

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

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

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

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

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

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

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