Как называются проблемы в компьютерных программах
Обновлено: 21.11.2024
Решение проблем – основа информатики. Программисты должны сначала понять, как человек решает проблему, затем понять, как преобразовать этот «алгоритм» в то, что может сделать компьютер, и, наконец, как «написать» определенный синтаксис (требуемый компьютеру), чтобы выполнить работу. Иногда бывает так, что машина решает проблему совершенно иначе, чем человек.
Программисты умеют решать проблемы. Для решения проблемы на компьютере необходимо:
Уметь представлять информацию (данные), описывающую проблему.
Определить шаги для преобразования информации из одного представления в другое.
Представление информации
В глубине души компьютер действительно тупой. Он может действительно знать только о нескольких вещах. числа, символы, логические значения и списки (называемые массивами) этих элементов. (См. Типы данных). Все остальное должно быть "аппроксимировано" комбинациями этих типов данных.
Хороший программист "закодирует" все "факты", необходимые для представления проблемы, в переменных (см. Переменные). Кроме того, существуют «хорошие способы» и «плохие способы» кодирования информации. Хорошие способы позволяют компьютеру легко «вычислять» новую информацию.
Алгоритм
Алгоритм (см. Алгоритм) — это набор определенных шагов для решения проблемы. Подумайте об этом так: если бы вы сказали своей 3-летней племяннице сыграть вашу любимую песню на пианино (при условии, что племянница никогда не играла на пианино), вам пришлось бы сказать ей, где находится пианино и как сидеть. на скамейке, и как открыть крышку, и какие клавиши нажимать, и в каком порядке их нажимать, и т.д., и т.п., и т.п.
Суть хороших программистов заключается в том, чтобы определить шаги, необходимые для достижения цели. К сожалению, компьютер знает только очень ограниченный и ограниченный набор возможных шагов. Например, компьютер может сложить два числа. Но если вы хотите найти среднее двух чисел, это выходит за рамки базовых возможностей компьютера. Чтобы найти среднее значение, необходимо:
- Сначала сложите два числа и сохраните результат в переменной.
- Затем: разделите это новое число на два и сохраните результат в переменной.
- Наконец: предоставьте этот номер остальной части программы (или распечатайте его для пользователя).
Инкапсуляция, абстракция и сокрытие сложности
Компьютерщики любят использовать причудливое слово "Инкапсуляция", чтобы показать, насколько мы умны. Это просто термин для вещей, которые мы, люди, делаем каждый день. Он сочетается с другим причудливым термином: «Абстракция».
Абстракция — это идея «игнорирования деталей». Например, лес на самом деле представляет собой чрезвычайно сложную экосистему, содержащую деревья, животных, водные пути и т. д., и т. д., и т. д. Но для ученого-компьютерщика (и для обычного человека) это просто «лес».
Например, если вашему профессору нужна чашка кофе, и он просит вас об одном элементе: "Принесите мне чашку кофе", он использовал как инкапсуляцию, так и абстракцию. Количество шагов, необходимых для фактического получения кофе, можно перечислить. В том числе, вставать, идти по коридору, садиться в машину, подъезжать к кафетерию, платить за кофе и т. д., и т. д., и т. д. Кроме того, представление о том, что такое чашка кофе, абстрактно. Вы приносите кружку кофе или пенопластовую чашку? Он с кофеином или нет? Он свежесваренный или из концентрата? Это из Африки или Америки?
Всей этой информации СЛИШКОМ МНОГО, и мы бы быстро не смогли работать, если бы нам пришлось помнить все эти детали. Таким образом, мы «абстрагируемся» от деталей и запоминаем только несколько важных элементов.
Это подводит нас к идее "скрытия сложности". Сокрытие сложности заключается в том, что в большинстве случаев детали не имеют значения. В компьютерной программе такая простая идея, как рисование квадрата на экране, включает в себя сотни (если не тысячи) (низкоуровневых) компьютерных инструкций. Опять же, человек не мог бы создавать интересные программы, если бы каждый раз, когда он хотел что-то сделать, ему приходилось переписывать (правильно) каждую из этих инструкций. «Экапсулируя» то, что подразумевается под «рисованием квадрата», и «повторно используя» эту операцию снова и снова, мы делаем программирование более удобным.
Инкапсуляция
Идея инкапсуляции заключается в том, чтобы хранить информацию, необходимую для конкретной идеи, в наборе переменных, связанных с одним «объектом». Затем мы создаем функции для управления этим объектом независимо от фактических данных. С этого момента мы относимся к идее с «высокого уровня», а не беспокоимся обо всех частях (данных) и действиях (функциях), необходимых для представления объекта в компьютере.
Грубая сила
Грубая сила – это метод решения проблем, основанный на скорости компьютера (насколько быстро он может повторять шаги) для решения проблемы.Например, если вы хотите узнать, сколько раз число 8 встречается в числе 100, вы можете сделать следующее:
Конечно, это глупый способ для компьютера (или человека) решить эту проблему. Реальный способ сделать это:
Если вы сомневаетесь, вы часто можете использовать «грубую силу» для решения проблемы, но это часто экономит время (по крайней мере, время компьютера), чтобы обдумать проблему и решить ее элегантным способом.
Уильям Э. Перри и я опубликовали нашу вторую совместную книгу под названием "Тестирование грязных систем". Мы определяем грязную систему как систему, в которой может отсутствовать что-либо из следующего:
<р>1. Полная документация2. Полное понимание требований
3. Дизайн/Архитектура не выполняются в стандартизированном формате и/или
4. Плотность дефектов программного обеспечения неизвестна
В нашей новой книге содержится следующая информация.
Ключом к тестированию грязной системы является умение быть "археологом-испытателем". Вы будете копаться в системных артефактах и пытаться собрать воедино представление о системе, которое позволит вам построить план тестирования. Ваша цель — спланировать и провести тест, который будет не просто догадкой.
К счастью, существуют инструменты и методы, которые помогают в процессе снятия слоев неизвестной структуры и функций системы. После диагностики функциональности и структуры грязной системы, а затем разработки плана тестирования для проверки системы пришло время протестировать систему. Именно во время тестового выполнения грязной системы обнаруживаются неожиданные функции и происходят странные вещи, требующие дальнейшего изучения.
Вся работа, выполненная на этапах диагностики и планирования тестирования, окажется очень ценной для создания основы для выполнения теста. Хотя могут возникнуть неожиданности, предварительные исследования и планирование очень помогут в прогнозировании и локализации дефектов.
Подобно тому, как истребитель знает, где найти определенные виды вредителей, благодаря знанию того, где они процветают, вы также можете стать экспертом по устранению ошибок в программном обеспечении, определяя общую среду для размножения категорий программных ошибок.
20 самых распространенных проблем с программным обеспечением
После более чем 30-летнего совместного анализа дефектов программного обеспечения, проведенного нами и нашими коллегами, мы выявили 20 распространенных проблем с программным обеспечением. Эти распространенные проблемы с программным обеспечением возникают в самых разных приложениях и средах, но особенно часто возникают в грязных системах.
<р>1. Неправильные расчеты. Это видно в таких функциях, как финансовые расчеты и расчеты дат. Ключевым фактором является использование математических функций и математических операторов. <р>2. Неправильное редактирование данных — это когда программное обеспечение не применяет существующие изменения данных правильно. Например, редактирование данных может быть закодировано так, чтобы запретить ввод дня месяца, превышающего «31», но не разрешать ввод месяца. Это позволит ввести 30 февраля и другие недопустимые даты. <р>3. Неэффективное редактирование данных. Это когда редактирование данных выполняется и работает правильно, но все же не может предотвратить ввод неверных данных в систему. Примером этого является буквенно-цифровое поле адреса, которое позволяет вводить пробелы перед любыми цифрами или буквами в адресе. Поэтому, когда поиск или сортировка выполняются в поле адреса, поиск или сортировка могут не найти предполагаемый адрес. <р>4. Неправильное кодирование/реализация бизнес-правил. Это относится к одному из наиболее распространенных источников проблем с программным обеспечением — ошибкам, возникающим между тем, что предполагается разработать или внедрить, и тем, что фактически поставлено. Эти дефекты могут быть связаны с неправильными, отсутствующими или расплывчатыми спецификациями системных требований или с неправильным толкованием спецификаций требований. Если вы спрашиваете: "Какие спецификации? Какие требования?", то неправильный код или реализация бизнес-правил, вероятно, является для вас распространенной проблемой. <р>5. Неадекватная производительность программного обеспечения. Это относится к медленному времени отклика системы и пропускной способности транзакций. <р>6. Сбивающие с толку или вводящие в заблуждение данные. Это означает, что данные, показанные пользователям, могут быть правильными, но пользователи могут не полностью понимать, как их интерпретировать. Это не тривиальная проблема. Жизни были потеряны из-за того, что кто-то не предпринял правильных действий на основе данных, доставленных им из компьютерной системы. <р>7. Программное обеспечение, которое сложно использовать. Многие люди на собственном опыте столкнулись с разочарованием, вызванным использованием громоздкого программного обеспечения, в котором сложно ориентироваться и которое требует нескольких шагов для выполнения простых задач. Эта проблема связана с непониманием того, как люди взаимодействуют с компьютерами, а также является результатом истории модификаций, которые не планируются и не координируются для обеспечения простоты использования. Например, добавление многочисленных обходных путей в течение определенного периода времени в устаревших системах может иметь общий эффект запутывания исходной конструкции системы. <р>8. Устаревшее программное обеспечение — Программное обеспечение, которое больше не работает из-за нового оборудования или изменений вспомогательного программного обеспечения. Это относится к программному обеспечению, основанному на функциях, имеющихся в более старых версиях баз данных и операционных систем. Пример этого можно найти в старом коде COBOL, который не будет компилироваться в новых компиляторах из-за использования глаголов, которые больше не поддерживаются в компиляторе. Многие поставщики пытаются сделать новые выпуски вспомогательного программного обеспечения совместимыми с предыдущими версиями, но обычно бывают случаи, когда одна незначительная область отсутствия поддержки со стороны базовой системы может привести к серьезному пересмотру системы. Единственный другой вариант — не обновлять программное обеспечение поддержки. Это решение может быть оправдано в краткосрочной перспективе, но обычно достигается момент, когда программное обеспечение необходимо либо заменить, либо модифицировать. <р>9. Несогласованная обработка — программное обеспечение, которое правильно работает только в одной среде. Это относится к программному обеспечению, которое было разработано только для одной среды и не может быть легко перенесено и использовано в другой среде. Конечно, некоторые программы предназначены для работы только в одной среде. Однако, если организация внедряет новую технологию, требующую переносимости программного обеспечения в новые среды, тогда программное обеспечение необходимо будет модифицировать или заменить, если оно не соответствует новым техническим требованиям. Примером этого является программное обеспечение, которое работает в среде MS-DOS, но не работает в среде Microsoft Windows. <р>10. Трудно поддерживать и понимать. Это относится к способности программиста или разработчика поддерживать программное обеспечение. Чтобы поддерживать программное обеспечение, человек, выполняющий обслуживание, должен сначала проанализировать и понять программное обеспечение. Большая часть существующего сегодня программного обеспечения изначально была написана неструктурированным образом, а затем в течение длительного периода времени исправлялась по мере необходимости. Этот тип структуры программного обеспечения приводит к так называемому «спагетти-коду», который является сложным и неструктурированным. Проблема усугубляется тем, что при внесении изменений в такое программное обеспечение повышается риск непреднамеренного создания новых дефектов. <р>11. Ненадежные результаты или производительность. Это означает, что программное обеспечение не всегда дает правильные результаты или что нельзя полагаться на его правильную работу при каждом использовании. <р>12. Неадекватная поддержка бизнес-потребностей или целей. Это относится к программному обеспечению, которое не может удовлетворить бизнес-потребности. Например, систему может быть сложно изменить в соответствии с потребностями организации, или в ней могут отсутствовать функции, позволяющие пользователям настраивать бизнес-правила. <р>13. Больше не поддерживается поставщиком — это происходит, когда поставщик прекращает поддержку определенного программного продукта. Это может произойти из-за решения поставщика прекратить поддержку продукта, из-за прекращения деятельности поставщика или продажи продукта другому поставщику. <р>14. Неправильные или неадекватные интерфейсы с другими системами. Это означает, что программное обеспечение неправильно принимает входные данные (данные, управление, параметры и т. д.) из других систем или отправляет неверные выходные данные (данные, управление, параметры, печать и т. д.) в другие системы. . Примером этого является ситуация, когда система имеет интерфейсы электронных данных (EDI) с внешними системами, но неправильно получает или форматирует информацию. <р>15. Неправильное сопоставление и объединение данных. Это относится к ситуациям, когда данные получены из одного источника и сопоставляются или объединяются с данными из другого источника. Примеры включают сортировку нескольких файлов в один файл или таблицу или сопоставление данных из главного файла с идентификационным номером, введенным в качестве записи поиска. <р>16. Поиски данных, дающие неверные результаты. Это означает, что поиск извлекает неверные данные в результате поиска. В худшем случае извлеченные данные кажутся правильными по формату, но только путем отслеживания исходных документов и других исходных данных можно определить, что данные неверны для критериев поиска. Примером этого может быть поиск времени, отработанного конкретным сотрудником в системе расчета заработной платы. Имя сотрудника в верхней части информации может отображаться правильно, но подробные данные о времени могут принадлежать другому сотруднику. Единственным способом проверки информации будет сравнение отработанного времени с табелями учета рабочего времени или с таблицами, в которых указан идентификатор сотрудника. <р>17. Неправильная обработка отношений данных. Это означает, что отношения данных не созданы или не поддерживаются правильно между одним или несколькими элементами данных. Эти элементы данных могут находиться в интерактивных интерфейсах, отчетах или файлах. Например, система может позволить пользователю ввести неправильный телефонный код города, недействительный для штата, указанного в адресном поле. <р>18. Неправильная обработка файлов и данных. Это относится к программному обеспечению, которое неправильно извлекает данные из файлов или таблиц. Это может включать получение неверных данных из правильного источника или данных правильного типа из неправильного источника данных.Примером этого может быть извлечение данных из старой версии файла или таблицы, думая, что данные извлекаются из самой последней версии. Другим примером является неспособность программного обеспечения правильно обрабатывать пустые или полные файлы.Второстепенная проблема может быть связана с неспособностью программного обеспечения правильно передавать данные через систему. Примером этого может быть неправильная обработка транзакций, когда данные непреднамеренно удаляются во время обработки.
<р>19. Неадекватные меры безопасности. Это означает, что несанкционированный доступ к системе не контролируется и не обнаруживается должным образом. Кроме того, люди могут также иметь возможность выполнять транзакции, превышающие уровни авторизации, соответствующие их должностным обязанностям. Например, человек без управленческих уровней доступа безопасности может иметь возможность одобрять свои собственные сверхурочные. Или человек, не работающий в отделе расчета заработной платы, может просматривать файлы расчета заработной платы сотрудников. <р>20. Неспособность обрабатывать объемы производственных данных. Это относится к неспособности программного обеспечения обрабатывать данные на уровне, требуемом организацией. Примером этого может быть система, которая требуется для обработки финансовых транзакций на сумму, превышающую 10 миллионов долларов США, но система может обрабатывать только суммы до 9 999 999,99 долларов США. Другим примером является классический случай вычислительной задачи 2000 года, когда даты 2000 года и более поздние ошибочно распознаются как относящиеся к началу 1900 года.Если бы вы разработали тестовые примеры для решения каждой из этих проблем, вам было бы очень сложно полностью охватить их все. Как и все остальное в тестировании, рассмотрение относительного риска и текущей ситуации сужает ваше внимание. Один из подходов заключается в разработке вопросника риска для каждой проблемной области. Другим методом может быть опрос пользователей для оценки влияния риска. Третий метод заключается в изучении прошлых отчетов о дефектах и сопоставлении их с каждой из проблемных областей, придавая наивысший приоритет наиболее проблемным областям.
Как я указал в начале этой статьи, я не претендую на то, чтобы представить окончательный список источников проблем для грязных систем. Если у вас есть другие, я был бы признателен за ваши отзывы.
Программисты обычно имеют дело с проблемами, алгоритмами и компьютерными программами. Это три разных понятия.
Как подсказывает ваша интуиция, проблема — это задача, которую необходимо выполнить. Это лучше всего рассматривать с точки зрения входных данных и соответствующих выходных данных. Определение проблемы не должно содержать каких-либо ограничений на способ ее решения. Метод решения должен разрабатываться только после того, как проблема точно определена и досконально понята. Однако определение проблемы должно включать ограничения на ресурсы, которые могут потребляться любым приемлемым решением. Для любой задачи, которую должен решить компьютер, всегда существуют такие ограничения, сформулированные или подразумеваемые. Например, любая компьютерная программа может использовать только доступную оперативную память и дисковое пространство и должна выполняться в течение «разумного» времени.
Задачи можно рассматривать как функции в математическом смысле. Функция — это соответствие между входными данными (домен) и выходными данными (диапазон). Входными данными для функции может быть одно значение или набор информации. Значения, составляющие вход, называются параметрами функции. Конкретный набор значений параметров называется экземпляром задачи. Например, входным параметром функции сортировки может быть массив целых чисел. Конкретный массив целых чисел с заданным размером и конкретными значениями для каждой позиции в массиве будет примером проблемы сортировки. Разные экземпляры могут генерировать один и тот же вывод. Однако любой экземпляр проблемы должен всегда приводить к одному и тому же результату каждый раз, когда функция вычисляется с использованием этого конкретного ввода.
Это представление о том, что все задачи ведут себя как математические функции, может не соответствовать вашему интуитивному пониманию поведения компьютерных программ. Возможно, вы знаете программы, которым вы можете дать одно и то же входное значение в двух разных случаях, и в результате получится два разных вывода. Например, если вы введете дату в обычное приглашение командной строки Linux, вы получите текущую дату. Естественно, в разные дни дата будет разной, даже если дана одна и та же команда. Однако очевидно, что входные данные для программы даты — это нечто большее, чем команда, которую вы вводите для запуска программы. Программа date вычисляет функцию. Другими словами, в любой конкретный день правильно работающая программа даты может вернуть только один ответ на полностью указанный вход. Для всех компьютерных программ выходные данные полностью определяются полным набором входных данных программы. Даже «генератор случайных чисел» полностью определяется своими входными данными (хотя некоторые системы генерации случайных чисел, похоже, обходят это, принимая случайные входные данные от физического процесса, неподконтрольного пользователю).Ограничения на то, какие функции могут быть реализованы программами, являются частью области вычислительности.
8. 2.1.2. Алгоритмы¶
Алгоритм — это метод или процесс, которому следует следовать для решения проблемы. Если проблема рассматривается как функция, то алгоритм представляет собой реализацию функции, которая преобразует входные данные в соответствующие выходные данные. Задача может быть решена с помощью множества различных алгоритмов. Данный алгоритм решает только одну задачу (т. е. вычисляет конкретную функцию). Модули OpenDSA охватывают множество проблем, и для некоторых из этих проблем мы увидим более одного алгоритма. Для решения важной задачи сортировки существует более дюжины общеизвестных алгоритмов!
По определению что-то можно назвать алгоритмом только в том случае, если оно обладает всеми следующими свойствами.
Он должен быть правильным. Другими словами, он должен вычислить желаемую функцию, преобразовывая каждый ввод в правильный вывод. Обратите внимание, что каждый алгоритм реализует некоторую функцию, потому что каждый алгоритм отображает каждый ввод в некоторый вывод (даже если этот вывод представляет собой сбой программы). Вопрос здесь в том, реализует ли данный алгоритм предназначенную функцию.
Он состоит из серии конкретных шагов. Конкретность означает, что действие, описываемое этим шагом, полностью понятно и выполнимо человеком или машиной, которые должны выполнять алгоритм. Каждый шаг также должен быть выполним за конечное время. Таким образом, алгоритм дает нам «рецепт» решения проблемы путем выполнения ряда шагов, каждый из которых находится в пределах наших возможностей. Возможность выполнения шага может зависеть от того, кто или что предназначено для выполнения рецепта. Например, этапы рецепта печенья в поваренной книге могут считаться достаточно конкретными для обучения повара-человека, но не для программирования автоматизированной фабрики по производству печенья.
Не может быть никакой двусмысленности относительно того, какой шаг будет выполняться следующим. Часто это следующий шаг описания алгоритма. Выбор (например, оператор if) обычно является частью любого языка описания алгоритмов. Выбор позволяет выбрать, какой шаг будет выполняться следующим, но процесс выбора является однозначным в то время, когда выбор сделан.
Он должен состоять из конечного количества шагов. Если бы описание алгоритма состояло из бесконечного числа шагов, мы бы никогда не смогли ни записать его, ни реализовать в виде компьютерной программы. Большинство языков описания алгоритмов (включая английский и «псевдокод») предоставляют способ выполнения повторяющихся действий, известный как итерация. Примеры итерации в языках программирования включают конструкции цикла while и for. Итерация позволяет использовать краткие описания, при этом количество фактически выполненных шагов контролируется входными данными.
Он должен прекратиться. Другими словами, он не может войти в бесконечный цикл.
8. 2.1.3. Программы¶
Мы часто думаем о компьютерной программе как об экземпляре или конкретном представлении алгоритма на каком-либо языке программирования. Алгоритмы обычно представляются в виде программ или частей программ. Естественно, существует множество программ, являющихся экземплярами одного и того же алгоритма, потому что любой современный язык программирования можно использовать для реализации одного и того же набора алгоритмов (хотя некоторые языки программирования могут облегчить жизнь программисту). Чтобы упростить изложение, люди часто используют термины «алгоритм» и «программа» как синонимы, несмотря на то, что на самом деле это разные понятия. По определению, алгоритм должен содержать достаточно деталей, чтобы при необходимости его можно было преобразовать в программу.
Требование о том, что алгоритм должен завершаться, означает, что не все компьютерные программы соответствуют техническому определению алгоритма. Ваша операционная система является одной из таких программ. Однако вы можете думать о различных задачах для операционной системы (каждая с соответствующими входами и выходами) как об отдельных проблемах, каждая из которых решается с помощью определенных алгоритмов, реализованных частью программы операционной системы, и каждая из которых завершается после того, как ее вывод завершен. произведено.
8. 2.1.4. Резюме¶
Подводя итог: проблема — это функция или сопоставление входных данных с выходными. Алгоритм — это рецепт решения проблемы, шаги которого конкретны и недвусмысленны. Алгоритмы должны быть корректными, иметь конечную длину и завершаться для всех входных данных. Программа — это реализация алгоритма на языке программирования. Следующее слайд-шоу должно помочь вам визуализировать различия.
Josch13 через Pixabay
Говорят, что неизведанные территории на старых картах часто помечались зловещим предупреждением: «Здесь будут драконы.Возможно, апокрифическая идея заключалась в том, что никто, забредший в эти неизвестные уголки мира, не должен был делать это, не будучи готовым сразиться с ужасающим врагом. В этих таинственных краях могло случиться все, что угодно, и часто что-то нехорошее.
Программисты могут быть немного более цивилизованными, чем средневековые рыцари, но это не значит, что в современном техническом мире нет своей доли технических драконов, поджидающих нас в непредвиденных местах: сложные проблемы, которые ждут, пока крайний срок не наступит через несколько минут. ; усложнения, которые прочитали руководство и знают, что не указано точно; злые драконы, которые знают, как прокрасться в незавершенные ошибки и несвоевременные сбои, часто сразу после фиксации кода.
Найдутся те, кто спокойно отдыхает по ночам, согреваясь своей наивной самоуверенностью в том, что компьютеры абсолютно предсказуемы и серьезно выдают правильные ответы. О, как мало они знают. Несмотря на всю тяжелую работу проектировщиков микросхем, разработчиков языков и миллионов программистов во всем мире, до сих пор существуют колючие заросли проблем программирования, которые могут поставить на колени даже самых могущественных программистов.
Вот семь самых суровых уголков мира программирования, где мы поставили бы большие маркеры с надписью «Здесь будут драконы».
Многопоточность
Похоже, это хорошая идея: разбить программу на независимые разделы и позволить ОС запускать их как отдельные маленькие программы. Если у процессоров четыре, шесть, восемь или даже больше ядер, почему бы не написать свой код так, чтобы он мог иметь четыре, шесть, восемь или больше потоков, использующих все ядра независимо?
Идея работает, когда части на самом деле полностью разделены и не имеют ничего общего друг с другом. Но как только им нужно получить доступ к одним и тем же переменным или записать биты в одни и те же файлы, все ставки сняты. Один из потоков получит данные первым, и вы не можете предсказать, какой это будет поток.
Таким образом, мы создаем мониторы, семафоры и прочие инструменты для организации многопоточной каши. Когда они работают, они работают. Они просто добавляют еще один уровень сложности и превращают процесс сохранения данных в переменную в элемент, который требует немного больше внимания.
Когда они не работают, это полный хаос. Данные не имеют смысла. Столбцы не складываются. Деньги исчезают со счетов с пуфом. Это все биты в памяти. И удачи в попытках зафиксировать хоть что-то из этого. В большинстве случаев разработчики блокируют большие фрагменты структуры данных, чтобы к ним мог обращаться только один поток. Это может остановить хаос, но только за счет уничтожения большей части положительных сторон работы нескольких потоков с одними и теми же данными. С тем же успехом вы могли бы переписать ее как «однопоточную» программу.
Закрытие
В какой-то момент кто-то решил, что было бы полезно передавать функции, как если бы они были данными. Это хорошо работало в простых случаях, но программисты начали понимать, что проблемы возникают, когда функции выходят за пределы самих себя и получают доступ к другим данным, часто называемым «свободными переменными». Какая версия была правильной? Были ли это данные, когда был инициирован вызов функции? Или это было, когда функция действительно работала? Это особенно важно для JavaScript, где между ними могут быть большие промежутки.
Решение, «замыкание», является одним из самых больших источников головной боли для программистов на JavaScript (а теперь и на Java и Swift). Новички и даже многие ветераны не могут понять, что закрывается и где могут быть границы так называемого закрытия.
Название не помогает — это не похоже на то, что доступ закрыт навсегда, как панель, сообщающая о последнем звонке. Во всяком случае, доступ открыт, но только через червоточину в континууме данных и времени, странный механизм сдвига во времени, который в конечном итоге должен породить научно-фантастическое телешоу. Но называть это «сложным механизмом доступа к стеку» или «системой жонглирования управлением данными» кажется слишком длинным, поэтому мы застряли на «замыканиях». Не говорите мне, нужно ли кому-то платить за несвободные переменные.
Слишком большие данные
Когда ОЗУ начинает заполняться, все начинает идти не так. Неважно, выполняете ли вы новомодный статистический анализ потребительских данных или работаете со скучной старой электронной таблицей. Когда у машины заканчивается оперативная память, она обращается к так называемой виртуальной памяти, которая выливается на сверхмедленный жесткий диск. Это лучше, чем полный сбой или завершение задания, но мальчик делает все медленнее.
Проблема в том, что жесткие диски как минимум в 20–30 раз медленнее оперативной памяти, а массовые дисковые накопители часто медленнее. Если какой-то другой процесс также пытается записывать или читать с диска, все становится значительно хуже, потому что диски могут выполнять только одну операцию за раз.
Активация виртуальной памяти усугубляет другие скрытые проблемы с вашим программным обеспечением. Если есть сбои потоков, они начинают ломаться намного быстрее, потому что потоки, застрявшие в виртуальной памяти жесткого диска, работают намного медленнее, чем другие потоки.Однако это длится лишь короткий период, потому что однажды потоки Wallflower перемещаются в память, а другие потоки зависают. Если код идеален, результат просто намного медленнее. Если это не так, недостатки быстро приводят к катастрофе. Это один небольшой пример.
Управление этим — настоящая проблема для программистов, работающих с большими массивами данных. Любой, кто проявляет некоторую небрежность при построении расточительных структур данных, в конечном итоге получает код, который замедляет работу. Он может нормально работать с несколькими тестовыми примерами, но при реальных нагрузках он приводит к сбою.
NP-завершено
Любой, кто имеет университетское образование в области компьютерных наук, знает о загадочных проблемах, связанных с аббревиатурой, которую редко произносят вслух: недетерминированное полиномиальное полное, также известное как NP-полное. На изучение деталей часто уходит целый семестр, и даже тогда многие студенты компьютерных наук приходят к выводу, что никто не может решить эти задачи, потому что они слишком сложны.
Задачи NP-полные часто довольно сложны, если вы решаете их просто грубой силой. Например, «задача коммивояжёра» может занимать экспоненциально много времени, поскольку маршрут продаж включает всё больше и больше городов. Решение «задачи о рюкзаке» путем нахождения подмножества чисел, наиболее близких к некоторому значению N, решается путем перебора всех возможных подмножеств, что является очень большим числом. Все в страхе убегают от этих проблем, потому что они являются прекрасным примером одного из самых больших призраков в Кремниевой долине: алгоритмов, которые не масштабируются.
Сложность заключается в том, что некоторые NP-полные задачи легко решить с помощью аппроксимации. Алгоритмы не обещают точного решения, но они довольно близки. Они могут не найти идеального маршрута для коммивояжера, но могут подобраться к правильному ответу с точностью до нескольких процентов.
Существование этих довольно хороших решений только делает драконов более загадочными. Никто не может быть уверен, действительно ли проблемы сложны или достаточно просты, если вы готовы удовлетвориться достаточно хорошим ответом.
Безопасность
«Есть известные известные; есть вещи, которые мы знаем, мы знаем», — сказал однажды на пресс-конференции Дональд Рамсфелд, министр обороны во время второй администрации Буша. «Мы также знаем, что есть известные неизвестные; то есть мы знаем, что есть некоторые вещи, которых мы не знаем. Но есть и неизвестные неизвестные — те, о которых мы не знаем, что мы не знаем».
Рамсфелд говорил о войне в Ираке, но то же самое относится и к компьютерной безопасности. Самые большие проблемы — это дыры, о существовании которых мы даже не знаем. Все понимают, что вы должны сделать свой пароль трудным для угадывания — это известное известное. Но кому когда-либо говорили, что ваше сетевое оборудование имеет собственный программный слой, спрятанный внутри? Вероятность того, что кто-то может пропустить взлом вашей ОС и вместо этого нацелиться на этот секретный уровень, является неизвестной неизвестной.
Возможно, сейчас вам известно о возможности подобного взлома, но что, если есть и другие? Мы понятия не имеем, сможем ли мы укрепить дыры, о существовании которых даже не подозреваем. Можно задраить пароли, но есть щели, о которых вы даже не догадываетесь. Это удовольствие от работы с компьютерной безопасностью. А когда дело доходит до программирования, мышление, ориентированное на безопасность, становится все более важным. Вы не можете доверить профессионалам безопасности наведение порядка в вашем беспорядке.
Шифрование
Шифрование кажется мощным и непробиваемым, когда сотрудники правоохранительных органов выступают перед Конгрессом и просят официальных лазеек, чтобы остановить его. Проблема в том, что большая часть шифрования построена на туманном облаке неопределенности. Какие математические доказательства у нас есть, основаны на неопределенных предположениях, например, трудно разложить на множители действительно большие числа или вычислить дискретный логарифм.
Эти проблемы действительно сложны? Публично никто не описал какие-либо алгоритмы их взлома, но это не значит, что решений не существует. Если бы вы нашли способ подслушать каждый разговор и проникнуть в любой банк, вы бы сразу рассказали об этом миру и помогли бы им заткнуть дыры? Или промолчишь?
Настоящей проблемой является использование шифрования в собственном коде. Даже если мы уверены, что базовые алгоритмы безопасны, предстоит проделать большую работу по манипулированию паролями, ключами и подключениями. Если вы сделаете одну ошибку и оставите пароль незащищенным, все откроется.
Управление идентификацией
Всем нравится эта карикатура журнала New Yorker с кульминацией: "В Интернете никто не знает, что вы собака". У него даже есть собственная страница в Википедии с четырьмя сложными разделами. (В интернете никто не знает старой поговорки об анализе юмора и препарировании лягушек.)
Хорошая новость заключается в том, что анонимность может быть полезной и освобождающей. Плохая новость заключается в том, что мы понятия не имеем, как делать что-либо, кроме анонимного общения. Некоторые программисты говорят о «двухфакторной аутентификации», но умные переходят на «N-факторную аутентификацию».
После пароля и, возможно, текстового сообщения на мобильный телефон, у нас не так много стабильного. Считыватели отпечатков пальцев выглядят впечатляюще, но, похоже, многие готовы рассказать, как их можно взломать (см. здесь, здесь и здесь для начала).
Это не имеет большого значения для мира пустой болтовни в Snapchat или Reddit, но поток взломанных страниц Facebook немного сбивает с толку. Нет простого способа справиться с такими серьезными вопросами, как собственность, деньги, здравоохранение или почти все остальное в жизни, кроме бессмысленной светской беседы. Поклонники биткойнов любят болтать о том, насколько надежным может быть блокчейн, но почему-то монеты продолжают грабить (см. здесь и здесь). У нас нет реального метода обработки идентификационных данных.
Измерение твердости
Конечно, когда дело доходит до программирования, есть ли способ измерить сложность задачи? Никто не знает. Мы знаем, что некоторые проблемы решить легко, но совсем другое дело признать одну из них сложной. NP-полнота — это только часть сложной попытки систематизировать сложность алгоритмов и анализа данных. Теория полезна, но не может дать никаких гарантий. Заманчиво сказать, что трудно даже понять, сложна ли проблема, но вы поняли шутку.
Читайте также: