Category: литература

Category was added automatically. Read all entries about "литература".

Мой любимый язык программирования

Цитата из книги "Изучаем Python" Марка Лутца (купленной вчера по свободной цене) :)

"Все, что можно сделать на Perl, можно сделать и на Python, но при использовании Python вы еще сможете прочитать свой программный код."

Одураченные случайностью

Читаю удивительную книгу: Одураченные случайностью". Книга (если очень кратко) о том, что наш мозг не в состоянии правильно оценивать вероятности.

Не верите? Тогда попробуйте решить вот эту задачу.

Есть болезнь, которой в среднем болеет один человек из тысячи. Тест, выявляющий эту болезнь на ранней стадии, когда еще нет никаких других симптомов, дает ложно-положительный результат (т.е. показывает наличие болезни у здорового человека) в одном проценте случаев (т.е. точен на 99%). Некто решает сделать этот тест себе, тест показывает положительный результат. Какова вероятность того, что этот некто действительно болен?

Да, если вы ЗНАЕТЕ ответ, то попрошу не отвечать :)

ЗЫ. Еще интереснее задать эту задачу знакомым врачам, когда сами будете знать ответ :))

Телефон с сенсорным экраном

Пару раз довелось подержать такое в руках и даже поговорить. Блин, это же полный п-ц.

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

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

Но если звонить еще более-менее получалось, то на экранчике что-нибудь сделать при его размере - это тоже оказалось нелегкой задачей... Нажималось все вокруг, только не то, что нужно. И не удивительно, если на площади пальца размещается по 3-4 иконки, или по три контакта адресной книги сразу :)

В общем, надолго у меня отпало желание иметь такое щастье :)

И самое главное - вот мне реально интересно, производители это тестировали? Или "не держите его так" и все? :)

Стишок из детства

Давным-давно, еще во времена журнала "Веселые картинки" (или "Мурзилка" - не помню уже), попался мне необычный стишок, который запомнился очень надолго. Вот прямо до сейчас.

Не весь, конечно, только первые строчки: "На трубе на водосточной объявление читаю". Вспомнив о нем очередной раз, подумал, что надо передать по наследству! :) Благо, в интернете есть почти все :)) По крайней мере, по этой строчке он нашелся "на раз"!

Collapse )

Лицензионный контент

На днях впервые купил электронную книгу на литресе (http://www.litres.ru/). И все, что литресу нужно было сделать, чтобы я вдруг решил потратить 50 евроцентов за нормально отформатированную для чтения на налодоннике книгу вместо упорного поиска халявы - это добавить поддержку платежей через пейпел.

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

В общем, думаю, что таки буду и дальше этим сервисом пользоваться...

И кстати - ни разу не реклама :)

53. В линкере нет никакой магии

(В оригинале - The Linker Is not a Magical Program)

Удручающе часто (в последний раз – буквально перед написанием этой статьи) программисты представляют процесс преобразования исходного кода в исполняемый файл как-то вот так:

  1. Написать (или исправить) исходный код
  2. Скомпилировать исходный код в объектные файлы
  3. Происходит какое-то чудо
  4. Появляется исполняемый файл

На шаге 3, конечно же, происходит линковка. Что же меня в этом так раздражает? Я работал в техподдержке десятилетиями, и постоянно получаю вопросы вроде:

  • Линкер сообщает что переменная определена более одного раза
  • Линкер сообщает что переменная является неразрешимым символом
  • Почему исполняемый файл такой большой.

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

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

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

extern int iii;

Таким образом создаются внешние ссылки на символ iii. Определение же создает само хранилище для этого символа, появляясь обычно непосредственно в коде, и выглядит примерно вот так:

int iii = 3;

И таких определений может быть только одно. А что, если определение появится в более чем одном файле?

// File a.c
int iii = 3;

// File b.c
double iii(int x) { return 3.7; }

Линкер сообщит о том, что символ iii определен более одного раза.

Если же iii встречается только в виде деклараций, то линкер сообщит о том, что iii является неразрешенной ссылкой.

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

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

Автор оригинала - Walter Bright

Перевод мой, при использовании ссылка на мой живой журнал обязательна!

41. Взаимодействие между процессами влияет на время отклика

(В оригинале - Inter-Process Communication Affects Application Response Time)

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

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

Характерный пример – ripple loading в приложениях, строящих граф отношений между объектами. Ripple loading – это последовательное выполнение большого количества запросов к базе данных для выборки данных, необходимых для построения такого графа (см. Lazy Load в книге «Паттерны архитектуры корпоративных приложений Мартина Фаулера). Если клиент базы данных – это сервер приложений промежуточного уровня, строящий веб-страницу, то запросы к базе данных выполняются последовательно в одном потоке. Их задержки суммируются, повышая общее время отклика. Даже если один запрос к базе данных занимает всего лишь 10 миллисекунд, для страницы, требующей 10 тысяч запросов (что не так уж и редко), задержка отклика составит уже 10 секунд. Другие примеры включают HTTP-запросы от веб-браузера, вызов распределенного объекта, сообщения типа «запрос-ответ» и другие подобные взаимодействия. Чем больше взаимодействий между процессами требуется для получения ответа на воздействие, тем большим будет время задержки.

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

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

Автор оригинала - Randy Stafford

Перевод мой, при использовании ссылка на мой живой журнал обязательна!

21. Разделяйте технические и логические исключения

(В оригинале - Distinguish Business Exceptions from Technical)

В большинстве случаев есть лишь две причины, из-за которых что-то может пойти не так во время выполнения программы. Это технические проблемы, мешающие работе приложения, и бизнес-логика, не дающая нам использовать приложение неправильно. В большинстве современных языков программирования, таких как LISP, Java, Smalltalk, и C#, для обеих ситуаций используется механизм исключений. Однако эти две ситуации столь различны, что их стоит аккуратно разделять и не смешивать. Если для обеих ситуаций использовать одну и ту же иерархию исключений (не говоря уже о том, чтобы использовать одни и те же классы), то это может стать источником серьезной путаницы.

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

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

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

Немного другая, но все еще техническая проблема – это невозможность продолжать работать из-за проблем в среде окружения, например, отсутствие ответа от базы данных. В этом случае вы должны предполагать, что инфраструктура уже попыталась сделать все возможное, чтобы эту проблему решить, например, повторить попытку несколько раз, так и не получив результата. Но хоть причина и другая, для вашего кода ничего не поменялось – вы по-прежнему ничего не можете сделать для решения. Поэтому вы сообщаете о проблеме при помощи исключения, «всплывающего» наверх до общего обработчика.

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

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

Автор оригинала - Dan Bergh Johnsson

Перевод мой, при использовании ссылка на мой живой журнал обязательна!