7 найнеприємніших проблем в програмуванні

image
Відомо, що на старих картах, на незвіданих територіях, часто поміщали зловісне попередження: «Тут живуть дракони». Вероятносенс цього попередження полягав у тому, що не варто входити в це простір світу, не будучи готовими битися з вселяє жах противником. Все що завгодно може статися на цих загадкових просторах, і нерідко таке «що завгодно» може закінчитися дуже погано.

Програмісти, можливо, є кілька більш цивілізованими, ніж середньовічні лицарі — однак це зовсім не означає, що сучасний технічний світ не має своїх технічних драконів, що чекають нас в непередбачених місцях: складні проблеми, які спливають саме тоді, коли підходить термін здачі роботи або в моменти особливо високих навантажень і відповідальної роботи; конкуренти, які прочитали керівництво і знають, що недостатньо добре реалізовано; злі «біси», які знають, як використовувати неліквідовані до кінця баги і дефекти програм, причому дізнаються це часто відразу ж після того, як програма здана до використання.

Знаходяться люди, які спокійно сплять вночі, согреваемые своєю наївною впевненістю, що комп'ютери цілком передбачувані і невтомно видають потоком правильні відповіді. Як же мало їм відомо! Незважаючи на серйозні зусилля розробників чіпів, творців мов і мільйонів програмістів, є ще в програмуванні небезпечні хащі, які можуть погубити навіть самих просунутих з програмістів і розробників.

Ось сім з страхітливих куточків світу програмування, на яких легко можна написати: «Тут живуть дракони».

Багатопоточність

Виглядає гарною ідеєю. Розбити вашу програму на незалежні секції і дати можливість операційній системі обробляти їх як окремі невеликі програми. Якщо процесор має чотири, шість, вісім або більше ядер, то чом би не написати програму так, щоб мати чотири, шість, вісім або більше потоків, використовують всі ядра незалежно?

Ідея працює, коли всі частини є, дійсно, повністю роздільними і ніяк не пов'язані один з одним. Але якщо вони мають отримувати доступ до одним і тим же змінним або записує біти в одні і ті ж файли — гра закінчена. Якийсь із потоків вийде на ці дані першим, і неможливо передбачити, який.

Тому ми створюємо монітори-синхронізатори, семафори та інші засоби для впорядкування мультипоточной плутанини. Коли вони працюють, то справа йде. Вони просто вводять інший рівень складності і перетворюють дію за збереження даних у якийсь змінної в операцію, яка вимагає деякого додаткового інтелектуального зусилля.

Коли і якщо вони не працюють, то запановує хаос. Одержані дані втрачають сенс. Стовпці не стикуються. Гроші зникають з рахунків зі свистом. І це все — просто біти пам'яті. І велика удача, якщо вдасться визначити який-небудь з них. У більшості випадків розробники закінчують тим, що блокують значні ділянки структури даних так, щоб тільки один потік міг взаємодіяти з ними. Це дозволяє зупинити хаос, але тільки за рахунок ліквідації здебільшого позитивних сторін наявності декілька потоків, що працюють на тих же даних. Ви просто могли б переписати таку програму як «однопоточную».

Замикання

Десь по ходу справи хтось вирішив, що було б корисно передавати функції, як якщо б вони були даними. Це працювало добре в простих випадках, але програмісти почали усвідомлювати, що виникають проблеми, коли функції стали виходити зовні на самих себе і отримувати доступ до інших даних, часто званими «вільними змінними». Яка версія є правильною в цьому випадку? Дані на момент ініціалізації виклику функції? Або ж на момент її фактичної роботи? Це особливо важливо для JavaScript, де ці моменти можуть бути сильно рознесені.

Рішення — «замикання» — є однією з найбільших причин головного болю для програмістів JavaScript (а тепер і Java і Swift). Новачки і навіть багато досвідчені програмісти не можуть зрозуміти, що замикається і де могли б бути межі цього так званого замикання.

Назва не допомагає — це не схоже на попередження про постійне закриття доступу начебто пропозиції для відвідувачів пабу зробити останній замовлення (перед його закриттям). У будь-якому випадку доступ відкритий, але тільки через червоточину» в континуумі дані-час — дивний механізм зсуву у часі, який має бути навіяний науково-фантастичними серіалами. Але назви «комплексний механізм доступу до пакетів» або «система маніпулювання управлінням даними» представляються занадто довгими, тому було вибрано «замикання». І не будемо починати розмову про те, хто повинен поплатитися за невільні змінні.

Занадто великі дані

Коли ОЗП починає переповнюватися, все падає. Не має значення, чи виконуєте ви наворочений статистичний аналіз споживчих даних або працюєте з звичної старої електронною таблицею. Коли машина виходить за межі ОЗП, то вона звертається до т. зв. віртуальної пам'яті, яка діє на надзвичайно повільному (у порівнянні з ОЗП) жорсткий диск або твердотільний накопичувач. Це, звичайно, краще, ніж повна зупинка або завершення завдання, але робота сповільнюється в будь-якому випадку.

Проблема в тому, що швидкодія жорстких дисків в 20-30 разів менше, ніж у ОЗП, а накопичувачі, масово продаються на ринку, працюють ще повільніше. Якщо якийсь інший процес також намагається в цей час писати на диск або зчитувати з нього, то ситуація стає просто драматичною, оскільки ці накопичувачі можуть виконувати тільки одну задачу в кожен момент часу.

Активація віртуальної пам'яті загострює інші, приховані проблеми вашого програмного забезпечення. Якщо є якісь потокові дефекти, то вони починають проявлятися набагато сильніше, оскільки потоки, які потрапляють у віртуальну пам'ять на жорсткому диску, обробляються набагато повільніше, ніж інші потоки. Інші потоки «підвисають» лише на той час, поки потік-невдаха знаходиться в цій пам'яті. Якщо програми зроблено добре, то результатом є помітне уповільнення. Якщо в програмі є дефекти, то вони швидко призводять до катастрофи. І це лише один маленький приклад.

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

NP-повна задача

Кожен, має університетську освіту з інформатики, знає про таємничих проблеми, прихованих за деяким скороченням, яке рідко роз'яснюють: «поліноміальна для недетермінованою машини Тюрінга завдання пошуку і прийняття рішення» або, інакше, NP-повна задача. Детальне їх вивчення займає цілий семестр курсу інформатики, але і в цьому випадку багато студентів виходять з туманне уявлення. В основному про те, що ніхто не може вирішити ці проблеми за їх виключної труднощі.

Проблеми NP-повної задачі часто є досить складними — якщо намагатися вирішити їх, використовуючи просто грубий, силовий підхід. Наприклад, тривалість рішення "проблеми комівояжера" зростає експоненціально зі збільшенням кількості точок маршруту. Рішення "завдання про рюкзаку" знаходженням підмножини чисел, які підходять ближче всього до деякого значення N, потребує перебору всіх можливих підмножин, число яких надзвичайно велике. Всі з острахом намагаються піти від цих проблем, тому що вони є прикладом одного з найстрашніших комп'ютерних «монстрів»: немасштабируемые алгоритми.

Нюанс у тому, що деякі проблеми NP-повних задач легко вирішуються при деякому наближеному розв'язанні. Відповідні алгоритми не обіцяють точного рішення, але дають результат, досить близький до точного. Вони, можливо, не дадуть ідеального маршруту для комівояжера, але їх рішення буде відрізнятися від правильного лише на кілька відсотків.

Існування таких досить хороших рішень робить «драконів» тільки більш загадковими. Ніхто заздалегідь не може бути впевнений, чи дійсно ці важкі проблеми або ж вони можуть бути порівняно легко вирішені — якщо вас влаштує відповідь, який буде просто хорошим.

Безпека

«Є пізнане знання — те, про що ми знаємо, що знаємо», — одного разу сказав на прес-конференції Дональд Рамсфельд, міністр оборони другий адміністрації президента США Джорджа Буша. «Є також пізнане незнання — те, про що ми знаємо, що не знаємо. Але є ще й непізнане незнання — це те, про що ми не знаємо, не знаємо.»

Рамсфельд говорив про війну в Іраку, але те ж саме справедливо і для комп'ютерної безпеки. Найбільшою проблемою є дірки, про які ми навіть не знаємо, що вони можливі. Всі розуміють, що необхідно зробити свій пароль важким для розгадки; це — пізнане знання. Але хто-небудь коли-небудь хоча б говорив, що мережеве обладнання має свій власний програмний рівень, захований глибоко всередині? Можливість не займатися зломом вашої ОС, а натомість націлюватися на цей «секретний» рівень є непізнаним незнанням.

Можливість такого проникнення тепер можна не розглядати як «непознанную», але можуть існувати й інші? Ми не маємо ні найменшого поняття, можливо закрити діри, якщо ми навіть не знаємо, чи існують вони. Можна ретельно захистити паролі, але існують способи злому, які ми не можемо навіть уявити собі. Робота з комп'ютерною безпекою доставляє, безсумнівно, море задоволення. А коли мова йде про програмування, то мислення, орієнтований на безпеку, стає все більш важливим. Не можна перекладати на професіоналів, які займаються безпекою, розчищення створеної вами плутанини.

Шифрування

Шифрування здається потужним і неприступним, коли співробітники правоохоронних органів стоять перед конгресом і просять дати їм офіційні входи до програми, щоб подолати його. Проблема полягає в тому, що основна частина шифрування побудована на туманному хмарі невизначеності. Які математичні докази у нас є для неясних припущень, на зразок того, що важко розкласти на множники дійсно великі числа або провести дискретне логарифмування?

Ці проблеми, дійсно, важкі? Ніхто публічно не описав якісь алгоритми їх вирішення, але це не означає, що так рішення не існує. Якщо ви знайшли спосіб підслуховувати кожна розмова і проникати в будь-який банк, ви б відразу повідомили про це всьому світові, що допомогти закрити діри? Або ж ви промовчали б?

Реально складним завданням є використання шифрування у власному коді. Навіть якщо базові алгоритми, як ми вважаємо, безпечні, повинно бути зроблено багато роботи по поводженню з паролями, ключами і з'єднаннями. Якщо буде зроблена хоча б одна помилка і якийсь пароль залишиться незахищеним, то все буде марно.

Управління ідентифікацією

Багато люблять малюнок, опублікований в газеті «The New Yorker» в 1993 році, з написом: «В інтернеті ніхто не знає, що ти собака». Він навіть має свою власну сторінку у Вікіпедії з чотирма детально проробленими розділами. (В інтернеті мало хто знає старий жарт про аналіз гумору і препаруванні жаб.)

Гарна новина полягає в тому, що анонімність може бути раскрепощающей і корисною. Погана ж у тому, що ми не маємо ні найменшого поняття, як зробити що-небудь, крім анонімного спілкування. Деякі програмісти кажуть про «двофакторної ідентифікації і аутентифікації», але більш просунуті спрямовуються до «N-факторної».

Крім пароля і, можливо, текстового повідомлення на стільниковий телефон у нас зовсім небагато того, на що можна полажиться. Зчитувачі відбитків пальців виглядають вражаюче, але багато хто, здається, готові розповісти і показати, як така ідентифікація може бути зламана (див. тут, здесь і тут для початківців).

Небагато що з цього має значення для світу марнослів'я в Snapchat або Reddit, але безліч зламаних сторінок Facebook трохи бентежить. Немає якогось легкого способу займатися в мережі серйозними питаннями, такими як власність, гроші, здоров'я і значною мірою все інше в житті, крім «світського» розмови на загальні теми.

Фанати биткоинов люблять висловлюватися, наскільки надійним може бути блокчейн, але так чи інакше биткоины продовжують красти (див. тут, здесь). Тут у нас немає ніякого реального методу для ідентифікації.

Надійність вимірювання

Звичайно, коли мова йде про програмування, то постає питання — чи є хоча б спосіб, з допомогою якого ми можемо виміряти складність проблеми? Ніхто, насправді, не знає цього. Ми знаємо, що деякі проблеми вирішити легко, але зовсім інша річ визначити, наскільки важко це зробити. NP-повнота є лише однією частиною складної спроби кодифікувати складність алгоритмів і аналізу даних. Теорія корисна, але вона не може запропонувати ніяких гарантій. Заманливо сказати, що важко навіть знати, важка проблема, але це, звичайно, жарт.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.