Найганебніші помилки у моїй кар'єрі програміста (на даний момент)

Найганебніші помилки у моїй кар'єрі програміста (на даний момент)
Як то кажуть, якщо тобі не соромно за свій старий код, то ти не ростеш як програміст — і я згодна з такою думкою. Я почала програмувати для розваги більше 40 років тому, а 30 років тому і професійно, тому помилок у мене набралося дуже багато. Будучи професором інформатики, я навчаю своїх студентів викладати уроки з помилок — своїх, моїх, чужих. Думаю, настав час розповісти про мої помилки, щоб не розгубити скромність. Сподіваюся, комусь вони виявляться корисними.

Третє місце – компілятор C від Microsoft

Мій шкільний вчитель вважав, що «Ромео і Джульєтту» не можна вважати трагедією, тому що в героїв не було трагічної провини — просто поводилися безглуздо, як і належить підліткам. Тоді я з ним не погодилася, але зараз бачу на його думці раціональне зерно — особливо через програмування.

До закінчення другого курсу MIT я була молода і недосвідчена, як у житті, так і в програмуванні. Влітку я проходила практику в Microsoft, у команді компілятора C. Спочатку я займалася рутиною на кшталт підтримки профілювання, а потім мені довірили роботу над найвеселішою (як я вважала) частиною компілятора оптимізацією бекенда. Зокрема, я мала поліпшити код x86 для операторів розгалуження.

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

То був кошмар. Через багато років мені розповідали, що програміст, який успадкував мій код, мене ненавидів.

Найганебніші помилки у моїй кар'єрі програміста (на даний момент)

Винесений урок

Як пишуть Девід Паттерсон і Джон Хеннессі у книзі «Архітектура комп'ютера та проектування комп'ютерних систем», один із головних принципів архітектури та розробки в тому, щоб у загальних випадках усе працювало якнайшвидше.

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

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

Мені потрібно було покликати досвідченого розробника і разом з ним подумати, які були спільні випадки, і розібратися саме з ними. Я б написала менше коду, але це навіть добре. Як писав засновник Stack Overflow Джефф Етвуд, найлютіший ворог програміста - сам програміст:

Я знаю, що у вас найкращі наміри, як і у всіх нас. Ми створюємо програми та любимо писати код. Так ми вже влаштовані. Ми думаємо, що будь-яку проблему можна вирішити за допомогою ізоленти, саморобного милиця та тріски коду. Як би не було боляче кодерам визнавати це, але найкращий код — код, якого немає. Кожен новий рядок потребує налагодження та підтримки, його потрібно розуміти. Додаючи новий код, ви повинні робити це з небажанням та огидою, тому що всі інші варіанти виявилися вичерпаними. Багато програмістів пишуть надто багато коду, роблячи його нашим ворогом.

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

Найганебніші помилки у моїй кар'єрі програміста (на даний момент)

Друге місце: реклама в соцмережах

Коли я працювала в Google над рекламою для соцмереж (пам'ятаєте Myspace?), я написала на C++ щось на зразок цього:

for (int i = 0; i < user->interests->length(); i++) {
  for (int j = 0; j < user->interests(i)->keywords.length(); j++) {
      keywords->add(user->interests(i)->keywords(i)) {
  }
}

Програмісти, можливо, відразу побачать помилку: останнім аргументом має бути j, а не i. Модульне тестування не виявило помилки, не помітив її і мій перевіряючий. Було здійснено запуск, і якось уночі мій код відправився на сервер і обвалив усі комп'ютери в дата-центрі.

Нічого страшного не сталося. Ніхто нічого не зламався, бо перед глобальним запуском код тестувався в межах одного дата-центру. Хіба що SRE-інженери ненадовго кинули грати у більярд та зробили невеликий відкат. На ранок я отримала email з аварійним дампом, виправила код і додала модульних тестів, які б виявили помилку. Оскільки я слідувала протоколу — інакше мій код просто не пройшов би запуск — інших проблем не виникло.

Найганебніші помилки у моїй кар'єрі програміста (на даний момент)

Винесений урок

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

Насправді, у мене є знайомий програміст — блискучий інженер, якого звільнили за одну помилку. Після цього його взяли на роботу в Google (і незабаром підвищили) — він чесно розповів про помилку на інтерв'ю, і її не вважали фатальною.

Ось що розповідають про Томаса Вотсона, легендарного главу IBM:

Було оголошено держзамовлення на суму близько мільйона доларів. Корпорація IBM – а точніше, особисто Томас Уотсон-старший – дуже хотіла його отримати. На жаль, торговельний представник не зміг цього зробити, і IBM програла тендер. Наступного дня цей співробітник прийшов до кабінету містера Вотсона і поклав йому на стіл конверт. Містер Вотсон навіть не заглядав у нього — він чекав співробітника і знав, що ця заява про звільнення.

Вотсон запитав, що не так.

Торговий представник докладно розповів про перебіг тендеру. Він назвав допущені помилки, яких можна було уникнути. Нарешті, він сказав: «Містер Вотсон, дякую вам за те, що дали мені порозумітися. Я знаю, наскільки ми потребували цього замовлення. Я знаю, наскільки він був важливий», — і зібрався йти.

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

У мене є футболка, на якій написано: «Якщо на помилках справді вчаться, то я вже магістр». Насправді щодо помилок я доктор наук.

Перше місце: App Inventor API

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

Чим гірше, тим краще

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

Як треба: дизайн має бути простим у реалізації та інтерфейсі. Простота інтерфейсу важливіша за простоту реалізації.

Чим гірше, тим краще: дизайн має бути простим у реалізації та інтерфейсі. Простота реалізації важливіша за простоту інтерфейсу.

Забудемо про це на хвилинку. На жаль, я забула про це довгі роки.

Винахідник додатків

Працюючи в Google, я входила до команди Винахідник додатків, онлайнового середовища розробки з підтримкою перетягування об'єктів для початківців Android-розробників. Йшов 2009 рік, і ми поспішали вчасно випустити альфа-версію, щоб улітку провести майстер-класи для вчителів, які могли б користуватися середовищем під час навчання вже восени. Я зголосилася продати спрайти, ностальгуючи по тому, як свого часу я писала ігри на TI-99/4. Для тих, хто не в курсі: спрайт – це двовимірний графічний об'єкт, який може переміщатися та взаємодіяти з іншими програмними елементами. Приклади спрайтів - космічні кораблі, астероїди, кульки та ракетки.

Ми реалізували об'єктно-орієнтований App Inventor в Java, тому там просто купа об'єктів. Оскільки кульки та спрайти поводяться дуже схоже, я створила абстрактний sprite-клас із властивостями (полями) X, Y, Speed ​​(швидкість) та Heading (напрямок). Вони мали одними й тими самими методами виявлення зіткнень, відскоку межі екрану тощо.

Головна відмінність між кулькою та спрайтом у тому, що саме намальовано – заповнене коло чи растр. Оскільки спочатку я реалізувала спрайти, логічно було вказати x-і y-координати верхнього лівого кута місця, де розміщувалося зображення.

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

Найганебніші помилки у моїй кар'єрі програміста (на даний момент)
Насправді потрібно було вказати x- та y-координати центру кола, як цьому вчить будь-який підручник математики та будь-яке інше джерело, яке згадує кола.

Найганебніші помилки у моїй кар'єрі програміста (на даний момент)
На відміну від моїх минулих помилок, від цієї постраждали не лише мої колеги, а й мільйони користувачів App Inventor. Багато з них були дітьми чи зовсім новачками у програмуванні. Їм доводилося виконувати багато зайвих дій під час роботи над кожним додатком, у якому була куля. Якщо решту своїх помилок я згадую зі сміхом, то ця кидає мене в піт і сьогодні.

Я нарешті запатчила цю помилку лише недавно, через десять років. Запатчила, а не виправила, адже як каже Джошуа Блох, API вічні. Не маючи можливості внести зміни, які вплинули на існуючі програми, ми додали властивість OriginAtCenter зі значенням false у старих програмах і true у всіх майбутніх. Користувачі можуть поставити закономірне питання, кому взагалі спало на думку розташувати точку відліку десь, окрім центру. Кому? Одному програмісту, який десять років тому полінувався створити нормальний API.

Винесені уроки

Працюючи над API (що іноді доводиться робити майже кожному програмісту), вам варто слідувати кращим порадам, викладеним у відео Джошуа Блоха.Як створити хороший API і чому він такий важливий»або у цьому короткому списку:

  • API може принести вам як величезну користь, так і величезну шкоду. Хороший API створює постійних клієнтів. Поганий стає вашим вічним кошмаром.
  • Загальнодоступні API, як і діаманти, вічні. Викладіться на всі сто: іншого шансу зробити все, як треба, більше не представиться.
  • Намітки для API мають бути короткими - Одна сторінка з сигнатурами класів і методів та описами, що займають не більше рядки. Це дозволить вам легко реструктурувати API, якщо з першого разу він вийде не ідеальним.
  • Розпишіть сценарії використання, Перш ніж реалізовувати API і навіть працювати над його специфікацією. Таким чином ви уникнете реалізації та специфікації повністю нефункціонального API.

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

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

Висновок

Програмісти роблять помилки щодня — чи то написання коду з багами, чи небажання спробувати щось, що підвищить їхню майстерність та продуктивність. Звичайно, можна бути програмістом і не допускаючи таких серйозних промахів, які робила я. Але стати хорошим програмістом, не усвідомлюючи своїх помилок і не вивчаючи з них уроків, неможливо.

Мені постійно зустрічаються студенти, яким здається, що вони припускаються занадто багато помилок і тому не створені для програмування. Я знаю, наскільки поширений IT синдром самозванця. Сподіваюся, ви засвоїте перераховані мною уроки — але пам'ятаєте головний з них: кожен з нас припускається помилок — сором'язливих, кумедних, страшних. Я буду здивована та засмучена, якщо в майбутньому у мене не набереться матеріалу на продовження статті.

Джерело: habr.com

Додати коментар або відгук