Як то кажуть, якщо тобі не соромно за свій старий код, то ти не ростеш як програміст — і я згодна з такою думкою. Я почала програмувати для розваги більше 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 програла тендер. Наступного дня цей співробітник прийшов до кабінету містера Вотсона і поклав йому на стіл конверт. Містер Вотсон навіть не заглядав у нього — він чекав співробітника і знав, що ця заява про звільнення.
Вотсон запитав, що не так.
Торговий представник докладно розповів про перебіг тендеру. Він назвав допущені помилки, яких можна було уникнути. Нарешті, він сказав: «Містер Вотсон, дякую вам за те, що дали мені порозумітися. Я знаю, наскільки ми потребували цього замовлення. Я знаю, наскільки він був важливий», — і зібрався йти.
Вотсон підійшов до нього біля дверей, подивився йому в очі і повернув конверт зі словами: «Як я можу дати тобі піти? Адже я щойно вклав мільйон доларів у твою освіту.
У мене є футболка, на якій написано: «Якщо на помилках справді вчаться, то я вже магістр». Насправді щодо помилок я доктор наук.
Перше місце: App Inventor API
По-справжньому страшні помилки торкаються величезної кількості користувачів, стають надбанням громадськості, довго виправляються і допускаються тими, хто міг би їх не допускати. Моя найбільша помилка задовольняє всі ці критерії.
Чим гірше, тим краще
Я читала
Як треба: дизайн має бути простим у реалізації та інтерфейсі. Простота інтерфейсу важливіша за простоту реалізації.
Чим гірше, тим краще: дизайн має бути простим у реалізації та інтерфейсі. Простота реалізації важливіша за простоту інтерфейсу.
Забудемо про це на хвилинку. На жаль, я забула про це довгі роки.
Винахідник додатків
Працюючи в Google, я входила до команди
Ми реалізували об'єктно-орієнтований 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.
Якби я написала хоча б невеликий конспект зі штучним сценарієм, швидше за все, я виявила б помилку і виправила б її. Якщо й ні, то це точно зробив би хтось із моїх колег. Будь-яке рішення, яке має далекосяжні наслідки, необхідно обмірковувати хоча б день (це стосується не лише програмування).
Назва есе Річарда Гебріела «Чим гірше, тим краще» вказує на перевагу, яку отримує той, хто першим вийшов на ринок — хай навіть із недосконалим продуктом — поки хтось інший цілу вічність жене за ідеалом. Розмірковуючи над кодом спрайтів, я розумію, що мені навіть необов'язково було писати більше за код, щоб зробити все, як треба. Як не крути, я грубо помилилася.
Висновок
Програмісти роблять помилки щодня — чи то написання коду з багами, чи небажання спробувати щось, що підвищить їхню майстерність та продуктивність. Звичайно, можна бути програмістом і не допускаючи таких серйозних промахів, які робила я. Але стати хорошим програмістом, не усвідомлюючи своїх помилок і не вивчаючи з них уроків, неможливо.
Мені постійно зустрічаються студенти, яким здається, що вони припускаються занадто багато помилок і тому не створені для програмування. Я знаю, наскільки поширений IT синдром самозванця. Сподіваюся, ви засвоїте перераховані мною уроки — але пам'ятаєте головний з них: кожен з нас припускається помилок — сором'язливих, кумедних, страшних. Я буду здивована та засмучена, якщо в майбутньому у мене не набереться матеріалу на продовження статті.
Джерело: habr.com