Previous Entry Share Next Entry
Пол Грэхем (Грэм) -- Быть Популярным, Часть 2
bukvodel
Начало перевода этого очерка ищи в предыдущем посте.

6 Библиотеки

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

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

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

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

7 Синтаксис

Может ли язык с синтаксисом Lisp, или более точно, отсутствием синтаксиса стать популярным? Я не знаю ответа на этот вопрос. Я *думаю*, что синтаксис не является главной причиной почему Lisp не популярен на данный момент не является популярным. У КЛ есть проблемы серьёзнее чем незнакомый синтаксис. Я знаю некоторых программистов, которые комфортно себя чувствуют с префиксным синтаксисом, но всё равно используют по умолчанию Перл, потому что он обладает мощными библиотеками обработки строк и может говорить с ОС.

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

Размытость префиксной нотации является более серьёзной проблемой. Для хакера эксперта это действительно проблема. Никто не хочет писать (aref a x y) когда можно написать a[x,y].



8 Эффективность

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

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

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

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

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

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

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

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

Природа скорости, как она воспринимается конечным пользователем, может меняться. С увеличением числа серверных приложений, может оказаться, что всё большее число программ являются зависимыми от ввода-вывода. Быстрый ввод-вывод может окупить себя. Язык может помочь простыми, прямыми мерами на подобии простых, быстрых, форматированных функций вывода, а так же глубокими структурными изменениями наподобие кэширования и постоянных (persistent) объектов.

Пользователи заинтересованы во времени отклика. Но другим тип эффективности становится всё более и более важным: количество пользователей на один процессор, которое вы можете одновременно поддерживать. Многие интересные приложения, которые будут написаны в ближайшем будущем, будут серверными, и количество пользователей на один сервер является критическим вопросом для каждого, кто размещает подобные приложения. In the capital cost of a business offering a server-based application, this is the divisor.

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

В некоторых приложениях, процессор будет ограничивающим фактором, а скорость выполнения будет иметь наибольшее значение с точки зрения оптимизации. Но часто ограничением будет объём памяти: количество пользователей будет определяться количеством памяти, которое требуется для данных каждого пользователя. Язык может помочь и в этом случае. Хорошая поддержка потоков позволит пользователям разделять одну кучу. Большим подспорьем будут постоянные (persistent) объекты, а также поддержка "ленивой загрузки" на уровне языка.

9 Время

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

Изобретатели удивительных новых вещей очень часто бывают удивлены, когда узнают об этом, но тебе требуется время для того, чтобы донести сообщение!! до людей. Один мой друг редко делает то, о чём его попросили в первый раз. Он знает, что люди иногда просят о вещах, которые им не нужны. Для того, чтобы исключить потерю его времени, он ждёт, чтобы его попросили сделать это в третий или четвёртый раз; к этому времени, те, кто просят, могут быть весьма раздражёнными, но, по крайней мере, они действительно хотят то, о чём они просят.

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

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

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

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

Существуют два способа представить новые технологии: метод органического роста, и метод большого взрыва. Примерами метода органического роста являются "выросшие из коротких штанишек" (seat-of-the-pants) недофинансированные гаражные стартапы. Пара парней, работающих в темноте, разрабатывает некую новую технологию. Они запускают её безо всякого маркетинга и, в начале, у них есть только несколько (фантастически преданных) пользователей. Они продолжают улучшать технологию, а в это время количество пользователей прирастает благодаря сплетням и слухам. И они уже большие ещё до того как они узнают об этом.

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

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

Этот шаблон применим не только к компаниям. Ты также обнаружишь его и в спонсируемых исследованиях. Multics и Common Lisp были проектами Большого Взрыва, а Unix и MacLisp были проектами Органического Роста.

10 Перепланировка

"Лучший способ писать -- это переписывать", написал E. B. White. Каждый хороший писатель знает это, и это хорошо для ПО. Наиболее важная часть планирования -- это перепланировка. ЯП, в особенности, перепланируются не достаточно.

Для того, чтобы писать хорошее ПО, ты должен держать в голове две противоположные идеи. Тебе требуется наивная вера молодого хакера в твои способности, и в тоже время, скептицизм ветерана. Ты должен быть способен думать о том, насколько это может быть сложно (http://www.trevorblackwell.com/) одной частью твоего мозга, пока другая думает, что это никогда не заработает (http://www.pdos.lcs.mit.edu/~rtm/).

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

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

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

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

Хорошо всё то, что помогает вам поддерживать цикл перепланировки. Можно снова и снова переписывать прозу, пока ты не будешь счастлив от того, что у тебя получилось. Но ПО, как правило, не перепланируется в достаточной степени. У прозы есть читатели, а у ПО -- *пользователи*. Если писатель перепишет очерк, то люди, читавшие его старую версию, вряд ли будут жаловаться на то, что ход их мыслей был нарушен вновь введёными несовместимостями.

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

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

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

А смысл следующего параграфа я просто не понял:

One solution here might be to design systems so that interfaces are horizontal instead of vertical-- so that modules are always vertically stacked strata of abstraction. Then the interface will tend to be owned by one of them. The lower of two levels will either be a language in which the upper is written, in which case the lower level will own the interface, or it will be a slave, in which case the interface can be dictated by the upper level.

11 Lisp

Всё это ведёт к тому, что для нового Lisp'а надежда есть. Есть надежда для любого языка, который даёт хакерам то, что они хотят, включая Lisp. Я думаю, что мы сделали ошибку думая, что хакеры отвернулись от Lisp'а из-за его необычности. Эта успокаивающая иллюзия может не дать нам увидеть настоящую проблему с Lisp, или, по крайней мере, Common Lisp, заключающуюся в том, что его обламывает делать то, что хакеры хотят делать. Языку хакеров требуются мощные библиотеки и что-нибудь, что можно хакнуть. У КЛ нет ни того, ни другого. Язык хакеров краток и пригоден к хаку. А КЛ нет.

Хорошая новость заключается в том, что Lisp сам по себе не отстой, а КЛ -- отстой. Если мы сможем разработать новый Lisp, который будет настоящим хакерским языком, то, как мне кажется, хакеры будут его использовать. Они будут использовать любой язык, который делает своё дело. Всё что мы должны сделать -- это обеспечить Lisp делает какуюнибудь важную работу лучше чем другие языки.

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

Иногда я думаю, что называть его улучшенной версией Питона будет хорошим маркетинговым трюком. Это звучит клёвее чем Lisp. Для многих людей, Lisp -- это медленный язык для ИИ с большим количеством скобок. Официальная биография Fritz Kunze старательно избегает употребления L-слова. Однако я считаю, что мы не должны бояться называть новый Lisp Lisp'ом. У многих из лучших хакеров всё ещё осталось скрытое уважение к Lisp -- например у тех, кто видит 6.001 и понимает. А они являются именно теми пользователями, которых тебе нужно завоевать.

В "Как стать хакером" Эрик Реймонд ("How to Become a Hacker," Eric Raymond) описывает Lisp как что-то подобное Латыни или Греческому -- язык, который тебе следует выучить в качестве упражнения для интеллекта, даже если ты не будешь его использовать:

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

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

Я думаю, что пока эта идея крутится по близости, хакеры будут достаточно восприимчивы к новому Lisp'у, даже если он будет называться Lisp'ом. Но этот Lisp должен быть хакерским языком, как классические Lisp'ы 1970-ых. Он должен быть насыщенным, простым и пригодным к хаку. И он должен обладать мощными библиотеками позволяющими хакерам делать то, что они хотят делать.

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

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

Серверные приложения также дают ответ на вопрос о том, что именно будет хакаться с использованием этого нового Lisp'а. Не повредит сделать Lisp более подходящим в качестве языка скриптов для Unix. (Сложно будет сделать его ещё менее подходящим.) Но я думаю, что лучше всего будет следовать примеру Tcl, и поставлять этот Lisp вместе с готовой системой для поддержки серверных приложений. Lisp, из-за своей природы естественно подходит для серверных приложений. Lexical closures provide a way to get the effect of subroutines when the ui is just a series of web pages. S-выражения легко вписываются в html, а макросы хороши для его генерации. Есть потребность в лучших инструментах для написания серверных приложений, и есть потребность в новом Lisp'е, и они будут прекрасно работать сообща/вместе.

12 Язык-Мечта

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

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

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

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

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

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

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

//*********************************************

Примечания

[1] Макросы, очень похожие на современное представление о них, были предложены Тимоти Хартом (Timothy Hart) в 1964 году, через два года после того как Lisp 1.5 был выпущен. Изначально, недоставало способов избежать variable capture и multiple evaluation; Hart's examples are subject to both.

[2] В "When the Air Hits Your Brain", нейрохирург Франк Вертосик (Frank Vertosick) приводит разговор в котором его chief resident, Гари, говорит о различие между хирургами и терапевтами ("вшами"):

Гари и я заказали большую пиццу и нашли открытую кабинку. Главный зажёг сигарету. "Посмотри на этих проклятых вшей, тараторят о каких-то болезнях, которые они повстречают раз в жизни. Вот в чём проблема со вшами, им нравится исключительно странные вещи. Они ненавидят то, чем они зарабатывают себе на хлеб и масло. Вот в чём разница между нами и трахаными вшами. Видишь, мы любим большие сочные lumbar disc herniations, а они ненавидят гипертонию..."

Мне Трудно думать об lumbar disc herniations как о чём-то сочном (кроме как буквально). Но всё же, я думаю, что знаю, что они имеют в виду. Мне часто приходилось ловить больших сочных жуков(bug -- жук). Непрограммисту может быть трудно представить, что можно получать удовольствие от работы с жуками. Конечно, было бы лучше, если всё просто работало. И это так, с одной стороны. И всё же, в выслеживании определённых типов жуков присутствует мрачное удовлетворение.

  • 1
с праздником день программиста был недавно)
эффективный похудеть смотрите также pantech

  • 1
?

Log in

No account? Create an account